driver:gpu: gpu driver upgrade to 1.17
authorshanlong.li <shanlong.li@starfivetech.com>
Fri, 12 Aug 2022 09:55:42 +0000 (02:55 -0700)
committershanlong.li <shanlong.li@starfivetech.com>
Fri, 12 Aug 2022 09:55:42 +0000 (02:55 -0700)
gpu driver upgrade to 1.17

Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
435 files changed:
drivers/gpu/drm/img/Kconfig
drivers/gpu/drm/img/Makefile
drivers/gpu/drm/img/img-drm-nulldisp/Kconfig [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/Makefile [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/drm_netlink_gem.c [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_drv.c [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.c [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.h [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_netlink.c [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc.h [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc_internal.h [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/netlink.h [deleted file]
drivers/gpu/drm/img/img-drm-nulldisp/nulldisp_drm.h [deleted file]
drivers/gpu/drm/img/img-rogue/Makefile
drivers/gpu/drm/img/img-rogue/config_kernel.h
drivers/gpu/drm/img/img-rogue/config_kernel.mk
drivers/gpu/drm/img/img-rogue/generated/rogue/cache_bridge/client_cache_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/cache_bridge/client_cache_direct_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/cache_bridge/common_cache_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/cache_bridge/server_cache_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/cmm_bridge/server_cmm_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/devicememhistory_bridge/client_devicememhistory_direct_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/devicememhistory_bridge/server_devicememhistory_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/di_bridge/common_di_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/di_bridge/server_di_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/dma_bridge/server_dma_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/dmabuf_bridge/common_dmabuf_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/dmabuf_bridge/server_dmabuf_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/htbuffer_bridge/server_htbuffer_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/mm_bridge/client_mm_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/mm_bridge/client_mm_direct_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/mm_bridge/common_mm_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/mm_bridge/server_mm_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pdump_bridge/client_pdump_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/pdump_bridge/client_pdump_direct_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pdump_bridge/common_pdump_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/pdump_bridge/server_pdump_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pdumpctrl_bridge/client_pdumpctrl_direct_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pdumpctrl_bridge/server_pdumpctrl_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pdumpmm_bridge/server_pdumpmm_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/pvrtl_bridge/server_pvrtl_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxbreakpoint_bridge/server_rgxbreakpoint_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxcmp_bridge/common_rgxcmp_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxcmp_bridge/server_rgxcmp_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxfwdbg_bridge/server_rgxfwdbg_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxhwperf_bridge/common_rgxhwperf_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxhwperf_bridge/server_rgxhwperf_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxkicksync_bridge/common_rgxkicksync_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxkicksync_bridge/server_rgxkicksync_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxpdump_bridge/server_rgxpdump_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxregconfig_bridge/server_rgxregconfig_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/common_rgxsignals_bridge.h [deleted file]
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/server_rgxsignals_bridge.c [deleted file]
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxta3d_bridge/common_rgxta3d_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxta3d_bridge/server_rgxta3d_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxtimerquery_bridge/server_rgxtimerquery_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxtq2_bridge/common_rgxtq2_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxtq2_bridge/server_rgxtq2_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxtq_bridge/common_rgxtq_bridge.h
drivers/gpu/drm/img/img-rogue/generated/rogue/rgxtq_bridge/server_rgxtq_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/ri_bridge/server_ri_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/srvcore_bridge/server_srvcore_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/sync_bridge/server_sync_bridge.c
drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/common_syncfallback_bridge.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/server_syncfallback_bridge.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/generated/rogue/synctracking_bridge/server_synctracking_bridge.c
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_1.V.2.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_1.V.4.19.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_1.V.4.5.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_15.V.1.64.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.104.18.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.104.218.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.208.318.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.21.16.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.54.25.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.54.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.54.330.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_22.V.54.38.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_24.V.104.504.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_24.V.208.504.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_24.V.208.505.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_24.V.54.204.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_29.V.108.208.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_29.V.52.202.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_33.V.11.3.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_33.V.22.1.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.104.182.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.104.183.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.104.796.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.103.h [moved from drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.102.h with 92% similarity]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.182.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.183.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_4.V.2.51.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_4.V.2.58.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_4.V.4.55.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_4.V.6.62.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_5.V.1.46.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_6.V.4.35.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_1.39.4.19.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_1.75.2.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_1.82.4.5.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_15.5.1.64.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.102.54.38.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.104.208.318.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.105.208.318.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.30.54.25.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.40.54.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.46.54.330.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.49.21.16.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.67.54.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.68.54.30.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.86.104.218.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_22.87.104.18.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_24.50.208.504.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_24.56.208.505.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_24.66.54.204.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_24.67.104.504.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_29.14.108.208.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_29.19.52.202.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_33.15.11.3.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_33.8.22.1.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.50.54.182.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.52.104.182.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.53.104.796.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.54.54.183.h [moved from drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.30.54.182.h with 90% similarity]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.55.54.103.h [moved from drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.51.54.102.h with 90% similarity]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_36.56.104.183.h [moved from drivers/gpu/drm/img/img-rogue/services/server/devices/rgxsignals.h with 70% similarity]
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_4.31.4.55.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_4.40.2.51.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_4.43.6.62.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_4.45.2.58.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_4.46.6.62.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_5.9.1.46.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/cores/rgxcore_km_6.34.4.35.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/rgx_bvnc_defs_km.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/rgx_bvnc_table_km.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/rgx_cr_defs_km.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/rgxdefs_km.h
drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/rgxmhdefs_km.h
drivers/gpu/drm/img/img-rogue/include/cache_ops.h
drivers/gpu/drm/img/img-rogue/include/devicemem_typedefs.h
drivers/gpu/drm/img/img-rogue/include/drm/pvr_drm.h
drivers/gpu/drm/img/img-rogue/include/drm/pvr_drm_core.h [deleted file]
drivers/gpu/drm/img/img-rogue/include/img_defs.h
drivers/gpu/drm/img/img-rogue/include/img_drm_fourcc_internal.h
drivers/gpu/drm/img/img-rogue/include/img_types.h
drivers/gpu/drm/img/img-rogue/include/linux_sw_sync.h
drivers/gpu/drm/img/img-rogue/include/lock_types.h
drivers/gpu/drm/img/img-rogue/include/log2.h
drivers/gpu/drm/img/img-rogue/include/osfunc_common.h
drivers/gpu/drm/img/img-rogue/include/pdumpdefs.h
drivers/gpu/drm/img/img-rogue/include/pdumpdesc.h
drivers/gpu/drm/img/img-rogue/include/public/powervr/buffer_attribs.h
drivers/gpu/drm/img/img-rogue/include/public/powervr/img_drm_fourcc.h
drivers/gpu/drm/img/img-rogue/include/public/powervr/pvrsrv_sync_ext.h
drivers/gpu/drm/img/img-rogue/include/pvr_buffer_sync_shared.h
drivers/gpu/drm/img/img-rogue/include/pvr_debug.h
drivers/gpu/drm/img/img-rogue/include/pvr_fd_sync_kernel.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_device_types.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_devvar.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_errors.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_memalloc_physheap.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_memallocflags.h
drivers/gpu/drm/img/img-rogue/include/pvrsrv_tlcommon.h
drivers/gpu/drm/img/img-rogue/include/pvrversion.h
drivers/gpu/drm/img/img-rogue/include/rgx_common.h
drivers/gpu/drm/img/img-rogue/include/rgx_common_asserts.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/include/rgx_compat_bvnc.h
drivers/gpu/drm/img/img-rogue/include/rgx_fwif_resetframework.h
drivers/gpu/drm/img/img-rogue/include/rgx_fwif_sf.h
drivers/gpu/drm/img/img-rogue/include/rgx_heap_firmware.h
drivers/gpu/drm/img/img-rogue/include/rgx_hwperf_common.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/include/rgx_meta.h
drivers/gpu/drm/img/img-rogue/include/rgx_mips.h
drivers/gpu/drm/img/img-rogue/include/rgx_riscv.h
drivers/gpu/drm/img/img-rogue/include/rgxfw_log_helper.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgx_fwif_hwperf.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgx_fwif_km.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgx_fwif_shared.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgx_heaps.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgx_hwperf.h
drivers/gpu/drm/img/img-rogue/include/rogue/rgxheapconfig.h
drivers/gpu/drm/img/img-rogue/include/rogue/system/rgx_tc/tc_clocks.h
drivers/gpu/drm/img/img-rogue/include/services_km.h
drivers/gpu/drm/img/img-rogue/include/servicesext.h
drivers/gpu/drm/img/img-rogue/include/sync_checkpoint_external.h
drivers/gpu/drm/img/img-rogue/include/sync_prim_internal.h
drivers/gpu/drm/img/img-rogue/include/system/rgx_tc/odin_defs.h
drivers/gpu/drm/img/img-rogue/include/system/rgx_tc/odin_regs.h
drivers/gpu/drm/img/img-rogue/include/virt_validation_defs.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/sysinfo.h with 76% similarity]
drivers/gpu/drm/img/img-rogue/services/include/km_apphint_defs_common.h
drivers/gpu/drm/img/img-rogue/services/include/pdump.h
drivers/gpu/drm/img/img-rogue/services/include/physheap.h
drivers/gpu/drm/img/img-rogue/services/include/physheap_config.h
drivers/gpu/drm/img/img-rogue/services/include/rgx_bridge.h
drivers/gpu/drm/img/img-rogue/services/include/rogue/km_apphint_defs.h
drivers/gpu/drm/img/img-rogue/services/include/rogue/rgxapi_km.h
drivers/gpu/drm/img/img-rogue/services/include/sync_checkpoint_internal.h
drivers/gpu/drm/img/img-rogue/services/server/common/cache_km.c
drivers/gpu/drm/img/img-rogue/services/server/common/connection_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/debug_common.c
drivers/gpu/drm/img/img-rogue/services/server/common/devicemem_history_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/devicemem_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/di_impl_brg.c
drivers/gpu/drm/img/img-rogue/services/server/common/di_impl_brg.h
drivers/gpu/drm/img/img-rogue/services/server/common/di_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/handle.c
drivers/gpu/drm/img/img-rogue/services/server/common/htbserver.c
drivers/gpu/drm/img/img-rogue/services/server/common/info_page_km.c
drivers/gpu/drm/img/img-rogue/services/server/common/mmu_common.c
drivers/gpu/drm/img/img-rogue/services/server/common/pdump_mmu.c
drivers/gpu/drm/img/img-rogue/services/server/common/pdump_physmem.c
drivers/gpu/drm/img/img-rogue/services/server/common/pdump_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/physheap.c
drivers/gpu/drm/img/img-rogue/services/server/common/physmem.c
drivers/gpu/drm/img/img-rogue/services/server/common/physmem_lma.c
drivers/gpu/drm/img/img-rogue/services/server/common/pmr.c
drivers/gpu/drm/img/img-rogue/services/server/common/power.c
drivers/gpu/drm/img/img-rogue/services/server/common/process_stats.c
drivers/gpu/drm/img/img-rogue/services/server/common/pvr_notifier.c
drivers/gpu/drm/img/img-rogue/services/server/common/pvrsrv.c
drivers/gpu/drm/img/img-rogue/services/server/common/pvrsrv_bridge_init.c
drivers/gpu/drm/img/img-rogue/services/server/common/ri_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/srvcore.c
drivers/gpu/drm/img/img-rogue/services/server/common/sync_checkpoint.c
drivers/gpu/drm/img/img-rogue/services/server/common/sync_fallback_server.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/common/sync_server.c
drivers/gpu/drm/img/img-rogue/services/server/common/tlserver.c
drivers/gpu/drm/img/img-rogue/services/server/common/tlstream.c
drivers/gpu/drm/img/img-rogue/services/server/common/vmm_pvz_client.c
drivers/gpu/drm/img/img-rogue/services/server/common/vz_vmm_vm.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgx_bridge_init.c [moved from drivers/gpu/drm/img/img-rogue/services/server/devices/rgxsignals.c with 56% similarity]
drivers/gpu/drm/img/img-rogue/services/server/devices/rgx_bridge_init.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/sysinfo.h with 80% similarity]
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxbreakpoint.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxbvnc.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxccb.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxccb.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxfwdbg.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxfwimageutils.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxfwimageutils.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxhwperf_common.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxhwperf_common.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxkicksync.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxkicksync.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxmem.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxpdvfs.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxregconfig.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxshader.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxshader.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxtdmtransfer.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxtimecorr.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxtimecorr.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxtimerquery.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxutils.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rgxworkest.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxcompute.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxcompute.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxdebug.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxdebug.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxdevice.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxfwutils.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxfwutils.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxhwperf.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxhwperf.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxinit.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxinit.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxlayer.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxlayer_impl.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxmipsmmuinit.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxmipsmmuinit.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxmmuinit.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxmulticore.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxpdump.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxpower.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxpower.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxsrvinit.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxstartstop.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxta3d.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxta3d.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxtdmtransfer.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxtransfer.c
drivers/gpu/drm/img/img-rogue/services/server/devices/rogue/rgxtransfer.h
drivers/gpu/drm/img/img-rogue/services/server/devices/rogueall_symbols.csv [deleted file]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdevice.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxhwperf.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxhwperf.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/sysconfig.h with 82% similarity]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer_impl.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer_impl.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/sysinfo.h with 80% similarity]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmulticore.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpdump.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxsrvinit.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxstartstop.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxtdmtransfer.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/Kbuild.mk [changed mode: 0755->0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/Linux.mk [changed mode: 0755->0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/allocmem.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/env_connection.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/fwload.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/km_apphint.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/km_apphint.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/module_common.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/module_common.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/osconnection_server.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/osfunc.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/osfunc_arm64.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/osfunc_riscv.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/ossecure_export.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/physmem_dmabuf.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/physmem_osmem_linux.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/physmem_test.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pmr_os.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/private_data.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_bridge_k.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_buffer_sync.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_counting_timeline.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_counting_timeline.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_debugfs.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_drm.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_drv.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_dvfs_device.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_dvfs_device.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_fence.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_fence.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_gputrace.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_platform_drv.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_procfs.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync.h
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync2.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_api.h [moved from drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_drv.h with 58% similarity]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_file.c
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_common.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_common.h [moved from drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_netlink.h with 68% similarity]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_drm.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_drm.h [moved from drivers/gpu/drm/img/img-drm-nulldisp/drm_netlink_gem.h with 75% similarity]
drivers/gpu/drm/img/img-rogue/services/server/env/linux/services_kernel_client.h
drivers/gpu/drm/img/img-rogue/services/server/include/cache_km.h
drivers/gpu/drm/img/img-rogue/services/server/include/connection_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/debug_common.h
drivers/gpu/drm/img/img-rogue/services/server/include/device.h
drivers/gpu/drm/img/img-rogue/services/server/include/devicemem_history_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/devicemem_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/devicemem_server_utils.h
drivers/gpu/drm/img/img-rogue/services/server/include/di_common.h
drivers/gpu/drm/img/img-rogue/services/server/include/di_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/handle.h
drivers/gpu/drm/img/img-rogue/services/server/include/handle_types.h
drivers/gpu/drm/img/img-rogue/services/server/include/htbserver.h
drivers/gpu/drm/img/img-rogue/services/server/include/lists.h
drivers/gpu/drm/img/img-rogue/services/server/include/mmu_common.h
drivers/gpu/drm/img/img-rogue/services/server/include/os_srvinit_param.h
drivers/gpu/drm/img/img-rogue/services/server/include/osconnection_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/osdi_impl.h
drivers/gpu/drm/img/img-rogue/services/server/include/osfunc.h
drivers/gpu/drm/img/img-rogue/services/server/include/oskm_apphint.h
drivers/gpu/drm/img/img-rogue/services/server/include/ossecure_export.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/include/pdump_km.h
drivers/gpu/drm/img/img-rogue/services/server/include/pdump_mmu.h
drivers/gpu/drm/img/img-rogue/services/server/include/pdump_physmem.h
drivers/gpu/drm/img/img-rogue/services/server/include/physmem.h
drivers/gpu/drm/img/img-rogue/services/server/include/physmem_dmabuf.h
drivers/gpu/drm/img/img-rogue/services/server/include/physmem_lma.h
drivers/gpu/drm/img/img-rogue/services/server/include/physmem_osmem.h
drivers/gpu/drm/img/img-rogue/services/server/include/pmr.h
drivers/gpu/drm/img/img-rogue/services/server/include/pmr_impl.h
drivers/gpu/drm/img/img-rogue/services/server/include/power.h
drivers/gpu/drm/img/img-rogue/services/server/include/process_stats.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvr_dvfs.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvr_notifier.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_apphint.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_bridge_init.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_cleanup.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_device.h
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_firmware_boot.h [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_sync_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/srvcore.h
drivers/gpu/drm/img/img-rogue/services/server/include/sync_checkpoint.h
drivers/gpu/drm/img/img-rogue/services/server/include/sync_fallback_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/sync_server.h
drivers/gpu/drm/img/img-rogue/services/server/include/tutils_km.h
drivers/gpu/drm/img/img-rogue/services/server/include/vmm_impl.h
drivers/gpu/drm/img/img-rogue/services/shared/common/devicemem.c
drivers/gpu/drm/img/img-rogue/services/shared/common/devicemem_pdump.c
drivers/gpu/drm/img/img-rogue/services/shared/common/devicemem_utils.c
drivers/gpu/drm/img/img-rogue/services/shared/common/htbuffer.c
drivers/gpu/drm/img/img-rogue/services/shared/common/ra.c
drivers/gpu/drm/img/img-rogue/services/shared/common/sync.c
drivers/gpu/drm/img/img-rogue/services/shared/common/tlclient.c
drivers/gpu/drm/img/img-rogue/services/shared/commonall_symbols.csv [deleted file]
drivers/gpu/drm/img/img-rogue/services/shared/devices/rogue/rgx_hwperf_table.c
drivers/gpu/drm/img/img-rogue/services/shared/include/allocmem.h
drivers/gpu/drm/img/img-rogue/services/shared/include/devicemem.h
drivers/gpu/drm/img/img-rogue/services/shared/include/devicemem_utils.h
drivers/gpu/drm/img/img-rogue/services/shared/include/lock.h
drivers/gpu/drm/img/img-rogue/services/shared/include/osmmap.h
drivers/gpu/drm/img/img-rogue/services/shared/include/ra.h
drivers/gpu/drm/img/img-rogue/services/shared/include/sync.h
drivers/gpu/drm/img/img-rogue/services/shared/include/sync_internal.h
drivers/gpu/drm/img/img-rogue/services/system/common/env/linux/interrupt_support.c [new file with mode: 0644]
drivers/gpu/drm/img/img-rogue/services/system/common/env/linux/pci_support.c [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/common/env/linux/pci_support.c with 100% similarity]
drivers/gpu/drm/img/img-rogue/services/system/include/interrupt_support.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/include/interrupt_support.h with 100% similarity]
drivers/gpu/drm/img/img-rogue/services/system/include/pci_support.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/include/pci_support.h with 100% similarity]
drivers/gpu/drm/img/img-rogue/services/system/include/sysvalidation.h [moved from drivers/gpu/drm/img/img-rogue/services/system/rogue/include/sysvalidation.h with 100% similarity]
drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/Kbuild.mk [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.c [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.h [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_sysconfig.c [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/Kbuild.mk [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/sysconfig.c [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/Kbuild.mk [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/sysconfig.c [deleted file]
drivers/gpu/drm/img/img-rogue/services/system/rogue/sf_7110/sysconfig.c
drivers/gpu/drm/img/img-rogue/services/system/rogue/sf_7110/sysinfo.h
drivers/gpu/drm/img/img-rogue/set_env [deleted file]
drivers/gpu/drm/img/kernel_compatibility.h
drivers/gpu/drm/img/pvr_dma_resv.h
drivers/gpu/drm/img/pvr_vmap.h
drivers/gpu/drm/img/pvrversion.h

index 20c3871..71d66af 100644 (file)
@@ -6,4 +6,3 @@ config DRM_IMG
 
 source "drivers/gpu/drm/img/img-rogue/Kconfig"
 
-source "drivers/gpu/drm/img/img-drm-nulldisp/Kconfig"
index 6d6682f..1b64843 100644 (file)
@@ -2,6 +2,5 @@
 
 obj-$(CONFIG_DRM_IMG) += riscv_vmap.o
 obj-$(CONFIG_DRM_IMG_ROGUE) += img-rogue/
-obj-$(CONFIG_DRM_IMG_NULLDISP) += img-drm-nulldisp/
 
 ccflags-y+= -I$(srctree)/mm
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/Kconfig b/drivers/gpu/drm/img/img-drm-nulldisp/Kconfig
deleted file mode 100644 (file)
index 90be471..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-config DRM_IMG_NULLDISP
-        bool "IMG DRM support null disp"
-        select DRM_IMG
-       select DRM_LEGACY
-        default y
-        help
-          Enable IMG null disp for powerVR GPU
-
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/Makefile b/drivers/gpu/drm/img/img-drm-nulldisp/Makefile
deleted file mode 100644 (file)
index d5ecc12..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-drm_nulldisp-y:=  drm_netlink_gem.o \
-       drm_nulldisp_drv.o \
-       drm_nulldisp_gem.o \
-       drm_nulldisp_netlink.o
-
-ccflags-y+= -I$(srctree)/drivers/gpu/drm/img
-
-
-obj-$(CONFIG_DRM_IMG_NULLDISP) += drm_nulldisp.o
-
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/drm_netlink_gem.c b/drivers/gpu/drm/img/img-drm-nulldisp/drm_netlink_gem.c
deleted file mode 100644 (file)
index 467e1f4..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * @File
- * @Codingstyle LinuxKernel
- * @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.
- */
-
-#include <linux/version.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
-#include <drm/drm_device.h>
-#include <drm/drm_file.h>
-#endif
-
-#include "drm_netlink_gem.h"
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
-#include <drm/drm_vma_manager.h>
-#endif
-
-#include <linux/capability.h>
-
-#include "kernel_compatibility.h"
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-static int netlink_gem_mmap_capsys(struct file *file,
-                                  struct vm_area_struct *vma)
-{
-       struct drm_file *file_priv = file->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       struct drm_vma_offset_node *node;
-       struct drm_gem_object *obj = NULL;
-       int err;
-
-       drm_vma_offset_lock_lookup(dev->vma_offset_manager);
-       node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
-                                                 vma->vm_pgoff,
-                                                 vma_pages(vma));
-       if (node) {
-               obj = container_of(node, struct drm_gem_object, vma_node);
-
-               /* Don't mmap an object that is being destroyed */
-               if (!kref_get_unless_zero(&obj->refcount))
-                       obj = NULL;
-       }
-       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
-
-       if (!obj)
-               return -EINVAL;
-
-       err = drm_vma_node_allow(node, file_priv);
-       if (!err) {
-               err = drm_gem_mmap(file, vma);
-
-               drm_vma_node_revoke(node, file_priv);
-       }
-
-       drm_gem_object_put(obj);
-
-       return err;
-}
-
-int netlink_gem_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       int err;
-
-       err = drm_gem_mmap(file, vma);
-       if (!!err && capable(CAP_SYS_RAWIO))
-               err = netlink_gem_mmap_capsys(file, vma);
-
-       return err;
-}
-#else  /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) */
-int netlink_gem_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct drm_file *file_priv = file->private_data;
-       struct drm_device *dev = file_priv->minor->dev;
-       struct drm_vma_offset_node *node;
-       struct drm_gem_object *obj;
-       int err;
-
-       mutex_lock(&dev->struct_mutex);
-
-       node = drm_vma_offset_exact_lookup(dev->vma_offset_manager,
-                                          vma->vm_pgoff,
-                                          vma_pages(vma));
-       if (!node) {
-               err = -EINVAL;
-               goto exit_unlock;
-       }
-
-       /* Allow Netlink clients to mmap any object for reading */
-       if (!capable(CAP_SYS_RAWIO) || (vma->vm_flags & VM_WRITE)) {
-               if (!drm_vma_node_is_allowed(node, file_priv)) {
-                       err = -EACCES;
-                       goto exit_unlock;
-               }
-       }
-
-       obj = container_of(node, struct drm_gem_object, vma_node);
-
-       err = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT, vma);
-
-exit_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return err;
-}
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) */
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_drv.c b/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_drv.c
deleted file mode 100644 (file)
index fc0945a..0000000
+++ /dev/null
@@ -1,2737 +0,0 @@
-/*
- * @File
- * @Codingstyle LinuxKernel
- * @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.
- */
-
-#include <linux/version.h>
-
-#include <linux/atomic.h>
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/jiffies.h>
-#include "pvr_linux_fence.h"
-#include <linux/workqueue.h>
-#include <linux/dma-mapping.h>
-#include <linux/mutex.h>
-#include <linux/capability.h>
-#include <linux/completion.h>
-#include <linux/dma-buf.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
-#include <drm/drm_drv.h>
-#include <drm/drm_file.h>
-#include <drm/drm_ioctl.h>
-#include <drm/drm_vblank.h>
-#include <linux/platform_device.h>
-#else
-#include <drm/drmP.h>
-#endif
-
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_modes.h>
-#include <drm/drm_plane_helper.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
-#include <drm/drm_atomic_helper.h>
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
-#include <drm/drm_probe_helper.h>
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
-#include <drm/drm_gem_atomic_helper.h>
-#endif
-
-
-#include "pvr_dma_resv.h"
-
-#include "img_drm_fourcc_internal.h"
-#include <pvrversion.h>
-
-#include <drm/drm_fourcc.h>
-
-#include "drm_nulldisp_drv.h"
-#if defined(LMA)
-#include "tc_drv.h"
-#include "drm_pdp_gem.h"
-#include "pdp_drm.h"
-#else
-#include "drm_nulldisp_gem.h"
-#endif
-#include "nulldisp_drm.h"
-#include "drm_netlink_gem.h"
-#include "drm_nulldisp_netlink.h"
-
-#if defined(NULLDISP_USE_ATOMIC)
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#endif
-
-#include "kernel_compatibility.h"
-
-#define DRIVER_NAME "nulldisp"
-#define DRIVER_DESC "Imagination Technologies Null DRM Display Driver"
-#define DRIVER_DATE "20150612"
-
-#if defined(NULLDISP_USE_ATOMIC)
-#define NULLDISP_DRIVER_ATOMIC DRIVER_ATOMIC
-#else
-#define NULLDISP_DRIVER_ATOMIC 0
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
-#define        NULLDISP_DRIVER_PRIME 0
-#else
-#define        NULLDISP_DRIVER_PRIME DRIVER_PRIME
-#endif
-
-#define NULLDISP_FB_WIDTH_MIN 0
-#define NULLDISP_FB_WIDTH_MAX 8192
-#define NULLDISP_FB_HEIGHT_MIN 0
-#define NULLDISP_FB_HEIGHT_MAX 8192
-
-#define NULLDISP_DEFAULT_WIDTH 640
-#define NULLDISP_DEFAULT_HEIGHT 480
-#define NULLDISP_DEFAULT_REFRESH_RATE 60
-
-#define NULLDISP_MAX_PLANES 3
-
-#if defined(NULLDISP_USE_ATOMIC)
-#define NULLDISP_NETLINK_TIMEOUT 5
-#else
-#define NULLDISP_NETLINK_TIMEOUT 30
-#endif
-#define NULLDISP_NETLINK_TIMEOUT_MAX 300
-#define NULLDISP_NETLINK_TIMEOUT_MIN 1
-
-enum nulldisp_crtc_flip_status {
-       NULLDISP_CRTC_FLIP_STATUS_NONE = 0,
-#if !defined(NULLDISP_USE_ATOMIC)
-       NULLDISP_CRTC_FLIP_STATUS_PENDING,
-#endif
-       NULLDISP_CRTC_FLIP_STATUS_DONE,
-};
-
-struct nulldisp_flip_data {
-       struct dma_fence_cb base;
-       struct drm_crtc *crtc;
-       struct dma_fence *wait_fence;
-};
-
-struct nulldisp_crtc {
-       struct drm_crtc base;
-       struct delayed_work vb_work;
-#if defined(NULLDISP_USE_ATOMIC)
-       struct drm_framebuffer *fb;
-       struct completion flip_done;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0))
-       struct completion copy_done;
-#endif
-#else
-       struct work_struct flip_work;
-       struct delayed_work flip_to_work;
-       struct delayed_work copy_to_work;
-
-       struct completion flip_scheduled;
-       struct completion copy_done;
-#endif
-
-       /* Reuse the drm_device event_lock to protect these */
-       atomic_t flip_status;
-       struct drm_pending_vblank_event *flip_event;
-#if !defined(NULLDISP_USE_ATOMIC)
-       struct drm_framebuffer *old_fb;
-       struct nulldisp_flip_data *flip_data;
-#endif
-       bool flip_async;
-};
-
-struct nulldisp_display_device {
-       struct drm_device *dev;
-
-       struct workqueue_struct *workqueue;
-       struct nulldisp_crtc *nulldisp_crtc;
-       struct nlpvrdpy *nlpvrdpy;
-#if defined(LMA)
-       struct pdp_gem_private *pdp_gem_priv;
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)) || \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
-       struct drm_connector *connector;
-#endif
-};
-
-#if !defined(NULLDISP_USE_ATOMIC)
-struct nulldisp_framebuffer {
-       struct drm_framebuffer base;
-       struct drm_gem_object *obj[NULLDISP_MAX_PLANES];
-};
-
-#define to_nulldisp_framebuffer(framebuffer) \
-       container_of(framebuffer, struct nulldisp_framebuffer, base)
-#endif
-
-struct nulldisp_module_params {
-       unsigned int hdisplay;
-       unsigned int vdisplay;
-       unsigned int vrefresh;
-       unsigned int updateto;
-};
-
-#define to_nulldisp_crtc(crtc) \
-       container_of(crtc, struct nulldisp_crtc, base)
-
-#if defined(LMA)
-#define        obj_to_resv(obj) pdp_gem_get_resv(obj)
-#else
-#define        obj_to_resv(obj) nulldisp_gem_get_resv(obj)
-#endif
-
-/*
- * The order of this array helps determine the order in which EGL configs are
- * returned to an application using eglGetConfigs. As such, RGB 8888 formats
- * should appear first, followed by RGB 565 configs. YUV configs should appear
- * last.
- */
-static const uint32_t nulldisp_modeset_formats[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_ARGB8888,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_ABGR2101010,
-#ifdef DRM_FORMAT_ABGR16161616F
-       DRM_FORMAT_ABGR16161616F,
-#endif
-       DRM_FORMAT_NV12,
-       DRM_FORMAT_NV21,
-       DRM_FORMAT_YUYV,
-       DRM_FORMAT_YUV444,
-       DRM_FORMAT_YVU420,
-};
-
-/*
- * Note that nulldisp, being a no-hardware display controller driver,
- * "supports" a number different decompression hardware
- * versions (V0, V1, V2 ...). Real, hardware display controllers are
- * likely to support only a single version.
- */
-static const uint64_t nulldisp_primary_plane_modifiers[] = {
-       DRM_FORMAT_MOD_LINEAR,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0_FIX,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V1,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V2,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V3,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V8,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V10,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V12,
-       DRM_FORMAT_MOD_PVR_FBCDC_8x8_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY25_8x8_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY50_8x8_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY75_8x8_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0_FIX,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V1,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V2,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V3,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V8,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V10,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V12,
-       DRM_FORMAT_MOD_PVR_FBCDC_16x4_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY25_16x4_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY50_16x4_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_LOSSY75_16x4_V13,
-       DRM_FORMAT_MOD_PVR_FBCDC_32x2_V1,
-       DRM_FORMAT_MOD_PVR_FBCDC_32x2_V3,
-       DRM_FORMAT_MOD_PVR_FBCDC_32x2_V8,
-       DRM_FORMAT_MOD_PVR_FBCDC_32x2_V10,
-       DRM_FORMAT_MOD_PVR_FBCDC_32x2_V12,
-       DRM_FORMAT_MOD_INVALID
-};
-
-static struct nulldisp_module_params module_params = {
-       .hdisplay = NULLDISP_DEFAULT_WIDTH,
-       .vdisplay = NULLDISP_DEFAULT_HEIGHT,
-       .vrefresh = NULLDISP_DEFAULT_REFRESH_RATE,
-       .updateto = NULLDISP_NETLINK_TIMEOUT,
-};
-
-static int updateto_param_set(const char *val, const struct kernel_param *kp);
-
-static const struct kernel_param_ops updateto_ops = {
-       .set = updateto_param_set,
-       .get = param_get_uint,
-};
-
-module_param_named(width, module_params.hdisplay, uint, 0444);
-module_param_named(height, module_params.vdisplay, uint, 0444);
-module_param_named(refreshrate, module_params.vrefresh, uint, 0444);
-module_param_cb(updateto, &updateto_ops, &module_params.updateto, 0644);
-
-MODULE_PARM_DESC(width, "Preferred display width in pixels");
-MODULE_PARM_DESC(height, "Preferred display height in pixels");
-MODULE_PARM_DESC(refreshrate, "Preferred display refresh rate");
-MODULE_PARM_DESC(updateto, "Preferred remote update timeout (in seconds)");
-
-/*
- * Please use this function to obtain the module parameters instead of
- * accessing the global "module_params" structure directly.
- */
-static inline const struct nulldisp_module_params *
-nulldisp_get_module_params(void)
-{
-       return &module_params;
-}
-
-static int updateto_param_set(const char *val, const struct kernel_param *kp)
-{
-       unsigned int updateto;
-       int err;
-
-       err = kstrtouint(val, 10, &updateto);
-       if (err)
-               return err;
-
-       if (updateto < NULLDISP_NETLINK_TIMEOUT_MIN ||
-           updateto > NULLDISP_NETLINK_TIMEOUT_MAX)
-               return -EINVAL;
-
-       return param_set_uint(val, kp);
-}
-
-static unsigned long nulldisp_netlink_timeout(void)
-{
-       const struct nulldisp_module_params *module_params =
-               nulldisp_get_module_params();
-       unsigned int updateto;
-
-#if !defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
-       kparam_block_sysfs_write(updateto);
-#else
-       kernel_param_lock(THIS_MODULE);
-#endif
-
-       updateto = module_params->updateto;
-
-#if !defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
-       kparam_unblock_sysfs_write(updateto);
-#else
-       kernel_param_unlock(THIS_MODULE);
-#endif
-
-       return msecs_to_jiffies(updateto * 1000);
-}
-
-/******************************************************************************
- * Linux compatibility functions
- ******************************************************************************/
-static inline void
-nulldisp_drm_fb_set_format(struct drm_framebuffer *fb,
-                          u32 pixel_format)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-       fb->format = drm_format_info(pixel_format);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-       const struct drm_format_info *format = drm_format_info(pixel_format);
-
-       fb->pixel_format = pixel_format;
-
-       fb->depth = format->depth;
-       fb->bits_per_pixel = format->depth ? (format->cpp[0] * 8) : 0;
-#else
-       fb->pixel_format = pixel_format;
-
-       switch (pixel_format) {
-       case DRM_FORMAT_NV12:
-       case DRM_FORMAT_YUYV:
-               /* Unused for YUV formats */
-               fb->depth = 0;
-               fb->bits_per_pixel = 0;
-               break;
-
-       default: /* RGB */
-               drm_fb_get_bpp_depth(pixel_format,
-                                    &fb->depth,
-                                    &fb->bits_per_pixel);
-       }
-#endif
-}
-
-static inline void nulldisp_drm_fb_set_modifier(struct drm_framebuffer *fb,
-                                               uint64_t value)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-       fb->modifier = value;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
-       /* FB modifier values must be the same for all planes */
-       fb->modifier[0] = value;
-       fb->modifier[1] = value;
-       fb->modifier[2] = value;
-       fb->modifier[3] = value;
-#else
-       /* Modifiers are not supported */
-#endif
-}
-
-/******************************************************************************
- * Plane functions
- ******************************************************************************/
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
-static bool nulldisp_primary_format_mod_supported(struct drm_plane *plane,
-                                                 uint32_t format,
-                                                 uint64_t modifier)
-{
-       /*
-        * All 'nulldisp_modeset_formats' are supported for every modifier
-        * in the 'nulldisp_primary_plane_modifiers' array.
-        */
-       return true;
-}
-#endif
-
-#if defined(NULLDISP_USE_ATOMIC)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
-static int nulldisp_plane_helper_atomic_check(struct drm_plane *plane,
-                                             struct drm_plane_state *state)
-{
-       struct drm_crtc_state *crtc_new_state;
-
-       if (!state->crtc)
-               return 0;
-
-       crtc_new_state = drm_atomic_get_new_crtc_state(state->state,
-                                                      state->crtc);
-
-       return drm_atomic_helper_check_plane_state(state, crtc_new_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  false, true);
-}
-
-static void
-nulldisp_plane_helper_atomic_update(struct drm_plane *plane,
-                                   struct drm_plane_state *old_state)
-{
-       struct drm_plane_state *state = plane->state;
-
-       if (state->crtc) {
-               struct nulldisp_crtc *nulldisp_crtc =
-                                       to_nulldisp_crtc(state->crtc);
-
-               nulldisp_crtc->fb = state->fb;
-       }
-}
-
-#else
-static int nulldisp_plane_atomic_check(struct drm_plane *plane,
-                                struct drm_atomic_state *state)
-{
-       struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
-       struct drm_crtc_state *crtc_new_state;
-
-       if (!new_plane_state->crtc)
-               return 0;
-
-       crtc_new_state =
-               drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
-
-       if (!crtc_new_state)
-               return -EINVAL;
-
-       return  drm_atomic_helper_check_plane_state(new_plane_state, crtc_new_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  false, true);
-}
-
-
-static void
-nulldisp_plane_helper_atomic_update(struct drm_plane *plane,
-                                   struct drm_atomic_state *old_state)
-{
-       struct drm_plane_state *state = plane->state;
-
-       if (state->crtc) {
-               struct nulldisp_crtc *nulldisp_crtc =
-                                       to_nulldisp_crtc(state->crtc);
-
-               nulldisp_crtc->fb = state->fb;
-       }
-}
-
-                                       
-#endif
-static const struct drm_plane_helper_funcs nulldisp_plane_helper_funcs = {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
-       .prepare_fb =  drm_gem_fb_prepare_fb,
-       .atomic_check = nulldisp_plane_helper_atomic_check,
-       .atomic_update = nulldisp_plane_helper_atomic_update,
-#else
-       .prepare_fb =  drm_gem_plane_helper_prepare_fb, 
-       .atomic_check = nulldisp_plane_atomic_check,
-       .atomic_update = nulldisp_plane_helper_atomic_update,
-#endif
-
-};
-
-static const struct drm_plane_funcs nulldisp_plane_funcs = {
-       .update_plane = drm_atomic_helper_update_plane,
-       .disable_plane = drm_atomic_helper_disable_plane,
-       .destroy = drm_primary_helper_destroy,
-       .reset = drm_atomic_helper_plane_reset,
-       .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-       .format_mod_supported = nulldisp_primary_format_mod_supported,
-};
-#else  /* defined(NULLDISP_USE_ATOMIC) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
-static int nulldisp_primary_helper_update(struct drm_plane *plane,
-                                         struct drm_crtc *crtc,
-                                         struct drm_framebuffer *fb,
-                                         int crtc_x, int crtc_y,
-                                         unsigned int crtc_w,
-                                         unsigned int crtc_h,
-                                         uint32_t src_x, uint32_t src_y,
-                                         uint32_t src_w, uint32_t src_h,
-                                         struct drm_modeset_acquire_ctx *ctx)
-{
-       struct nulldisp_display_device *nulldisp_dev = crtc->dev->dev_private;
-       struct drm_plane_state plane_state = {
-               .plane = plane,
-               .crtc = crtc,
-               .fb = fb,
-               .crtc_x = crtc_x,
-               .crtc_y = crtc_y,
-               .crtc_w = crtc_w,
-               .crtc_h = crtc_h,
-               .src_x = src_x,
-               .src_y = src_y,
-               .src_w = src_w,
-               .src_h = src_h,
-               .alpha = DRM_BLEND_ALPHA_OPAQUE,
-               .rotation = DRM_MODE_ROTATE_0,
-       };
-       struct drm_crtc_state crtc_state = {
-               .crtc = crtc,
-               .enable = crtc->enabled,
-               .adjusted_mode = crtc->mode,
-               .mode = crtc->mode,
-       };
-       struct drm_mode_set set = {
-               .fb = fb,
-               .crtc = crtc,
-               .mode = &crtc->mode,
-               .x = src_x >> 16, /* convert from fixed point */
-               .y = src_y >> 16, /* convert from fixed point */
-               .connectors = &nulldisp_dev->connector,
-               .num_connectors = 1,
-       };
-       int err;
-
-       BUG_ON(nulldisp_dev->connector->encoder == NULL);
-       BUG_ON(nulldisp_dev->connector->encoder->crtc != crtc);
-
-       err = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       if (err)
-               return err;
-
-       if (!plane_state.visible)
-               return -EINVAL;
-
-       return crtc->funcs->set_config(&set, ctx);
-}
-
-static int nulldisp_primary_helper_disable(struct drm_plane *plane,
-                                          struct drm_modeset_acquire_ctx *ctx)
-{
-       return -EINVAL;
-}
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)) */
-
-static const struct drm_plane_funcs nulldisp_plane_funcs = {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
-       .update_plane = nulldisp_primary_helper_update,
-       .disable_plane = nulldisp_primary_helper_disable,
-#else
-       .update_plane = drm_primary_helper_update,
-       .disable_plane = drm_primary_helper_disable,
-#endif
-       .destroy = drm_primary_helper_destroy,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
-       .format_mod_supported = nulldisp_primary_format_mod_supported,
-#endif
-};
-#endif /* defined(NULLDISP_USE_ATOMIC) */
-
-/******************************************************************************
- * CRTC functions
- ******************************************************************************/
-
-static bool
-nulldisp_crtc_helper_mode_fixup(struct drm_crtc *crtc,
-                               const struct drm_display_mode *mode,
-                               struct drm_display_mode *adjusted_mode)
-{
-       /*
-        * Fix up mode so that it's compatible with the hardware. The results
-        * should be stored in adjusted_mode (i.e. mode should be untouched).
-        */
-       return true;
-}
-
-static void nulldisp_crtc_helper_disable(struct drm_crtc *crtc)
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-
-#if !defined(NULLDISP_USE_ATOMIC)
-       if (atomic_read(&nulldisp_crtc->flip_status) ==
-           NULLDISP_CRTC_FLIP_STATUS_PENDING)
-               wait_for_completion(&nulldisp_crtc->flip_scheduled);
-
-       /*
-        * Flush any outstanding page flip related work. The order this
-        * is done is important, to ensure there are no outstanding
-        * page flips.
-        */
-       flush_work(&nulldisp_crtc->flip_work);
-       flush_delayed_work(&nulldisp_crtc->flip_to_work);
-#endif
-       flush_delayed_work(&nulldisp_crtc->vb_work);
-
-       drm_crtc_vblank_off(crtc);
-       flush_delayed_work(&nulldisp_crtc->vb_work);
-
-       /*
-        * Vblank has been disabled, so the vblank handler shouldn't be
-        * able to reschedule itself.
-        */
-       BUG_ON(cancel_delayed_work(&nulldisp_crtc->vb_work));
-
-       BUG_ON(atomic_read(&nulldisp_crtc->flip_status) !=
-              NULLDISP_CRTC_FLIP_STATUS_NONE);
-
-#if !defined(NULLDISP_USE_ATOMIC)
-       /* Flush any remaining dirty FB work */
-       flush_delayed_work(&nulldisp_crtc->copy_to_work);
-#endif
-}
-
-static void nulldisp_crtc_flip_complete(struct drm_crtc *crtc)
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-
-       /* The flipping process has been completed so reset the flip state */
-       atomic_set(&nulldisp_crtc->flip_status, NULLDISP_CRTC_FLIP_STATUS_NONE);
-       nulldisp_crtc->flip_async = false;
-
-#if !defined(NULLDISP_USE_ATOMIC)
-       if (nulldisp_crtc->flip_data) {
-               dma_fence_put(nulldisp_crtc->flip_data->wait_fence);
-               kfree(nulldisp_crtc->flip_data);
-               nulldisp_crtc->flip_data = NULL;
-       }
-#endif
-       if (nulldisp_crtc->flip_event) {
-               drm_crtc_send_vblank_event(crtc, nulldisp_crtc->flip_event);
-               nulldisp_crtc->flip_event = NULL;
-       }
-
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-}
-
-#if defined(NULLDISP_USE_ATOMIC)
-static void nulldisp_crtc_helper_mode_set_nofb(struct drm_crtc *crtc)
-{
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-static void nulldisp_crtc_helper_atomic_flush(struct drm_crtc *crtc,
-                                             struct drm_crtc_state *old_state)
-{
-#else
-static void nulldisp_crtc_helper_atomic_flush(struct drm_crtc *crtc,
-                                             struct drm_atomic_state *state)
-{
-       struct drm_crtc_state *old_state = drm_atomic_get_new_crtc_state(state, crtc);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-
-       if (!crtc->state->active || !old_state->active)
-               return;
-
-       if (nulldisp_crtc->fb) {
-               struct nulldisp_display_device *nulldisp_dev =
-                                                       crtc->dev->dev_private;
-
-               reinit_completion(&nulldisp_crtc->flip_done);
-
-               if (!nlpvrdpy_send_flip(nulldisp_dev->nlpvrdpy,
-                                      nulldisp_crtc->fb,
-                                      &nulldisp_crtc->fb->obj[0])) {
-                       unsigned long res;
-
-                       res = wait_for_completion_timeout(
-                                       &nulldisp_crtc->flip_done,
-                                       nulldisp_netlink_timeout());
-
-                       if (!res)
-                               DRM_ERROR(
-                                   "timed out waiting for remote update\n");
-               }
-
-               nulldisp_crtc->fb = NULL;
-       }
-
-       if (crtc->state->event) {
-               unsigned long flags;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
-               nulldisp_crtc->flip_async = crtc->state->async_flip;
-#else
-               nulldisp_crtc->flip_async = !!(crtc->state->pageflip_flags
-                                              & DRM_MODE_PAGE_FLIP_ASYNC);
-#endif
-               if (nulldisp_crtc->flip_async)
-                       WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
-               nulldisp_crtc->flip_event = crtc->state->event;
-               crtc->state->event = NULL;
-
-               atomic_set(&nulldisp_crtc->flip_status,
-                          NULLDISP_CRTC_FLIP_STATUS_DONE);
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-               if (nulldisp_crtc->flip_async)
-                       nulldisp_crtc_flip_complete(crtc);
-       }
-}
-
-static void nulldisp_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
-{
-       if (enable)
-               drm_crtc_vblank_on(crtc);
-       else
-               nulldisp_crtc_helper_disable(crtc);
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-static void
-nulldisp_crtc_helper_atomic_enable(struct drm_crtc *crtc,
-                                  struct drm_crtc_state *old_crtc_state)
-#else
-static void
-nulldisp_crtc_helper_atomic_enable(struct drm_crtc *crtc,
-                                  struct drm_atomic_state *state)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-{
-       nulldisp_crtc_set_enabled(crtc, true);
-
-       if (crtc->state->event) {
-               struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-               unsigned long flags;
-
-               WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
-               nulldisp_crtc->flip_event = crtc->state->event;
-               crtc->state->event = NULL;
-
-               atomic_set(&nulldisp_crtc->flip_status,
-                          NULLDISP_CRTC_FLIP_STATUS_DONE);
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-       }
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-static void
-nulldisp_crtc_helper_atomic_disable(struct drm_crtc *crtc,
-                                   struct drm_crtc_state *old_crtc_state)
-#else
-static void
-nulldisp_crtc_helper_atomic_disable(struct drm_crtc *crtc,
-                                   struct drm_atomic_state *state)
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-
-       nulldisp_crtc_set_enabled(crtc, false);
-
-       nulldisp_crtc->fb = NULL;
-
-       if (crtc->state->event) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&crtc->dev->event_lock, flags);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               crtc->state->event = NULL;
-               spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-       }
-}
-#else  /* defined(NULLDISP_USE_ATOMIC) */
-static void nulldisp_crtc_helper_dpms(struct drm_crtc *crtc,
-                                     int mode)
-{
-       /*
-        * Change the power state of the display/pipe/port/etc. If the mode
-        * passed in is unsupported, the provider must use the next lowest
-        * power level.
-        */
-}
-
-static void nulldisp_crtc_helper_prepare(struct drm_crtc *crtc)
-{
-       drm_crtc_vblank_off(crtc);
-
-       /*
-        * Prepare the display/pipe/port/etc for a mode change e.g. put them
-        * in a low power state/turn them off
-        */
-}
-
-static void nulldisp_crtc_helper_commit(struct drm_crtc *crtc)
-{
-       /* Turn the display/pipe/port/etc back on */
-
-       drm_crtc_vblank_on(crtc);
-}
-
-static int
-nulldisp_crtc_helper_mode_set_base_atomic(struct drm_crtc *crtc,
-                                         struct drm_framebuffer *fb,
-                                         int x, int y,
-                                         enum mode_set_atomic atomic)
-{
-       /* Set the display base address or offset from the base address */
-       return 0;
-}
-
-static int nulldisp_crtc_helper_mode_set_base(struct drm_crtc *crtc,
-                                             int x, int y,
-                                             struct drm_framebuffer *old_fb)
-{
-       return nulldisp_crtc_helper_mode_set_base_atomic(crtc,
-                                                        crtc->primary->fb,
-                                                        x,
-                                                        y,
-                                                        0);
-}
-
-static int
-nulldisp_crtc_helper_mode_set(struct drm_crtc *crtc,
-                             struct drm_display_mode *mode,
-                             struct drm_display_mode *adjusted_mode,
-                             int x, int y,
-                             struct drm_framebuffer *old_fb)
-{
-       /* Setup the new mode and/or framebuffer */
-       return nulldisp_crtc_helper_mode_set_base(crtc, x, y, old_fb);
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-static void nulldisp_crtc_helper_load_lut(struct drm_crtc *crtc)
-{
-}
-#endif
-#endif /* defined(NULLDISP_USE_ATOMIC) */
-
-static void nulldisp_crtc_destroy(struct drm_crtc *crtc)
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-
-       DRM_DEBUG_DRIVER("[CRTC:%d]\n", crtc->base.id);
-
-       drm_crtc_cleanup(crtc);
-
-       BUG_ON(atomic_read(&nulldisp_crtc->flip_status) !=
-              NULLDISP_CRTC_FLIP_STATUS_NONE);
-
-       kfree(nulldisp_crtc);
-}
-
-#if !defined(NULLDISP_USE_ATOMIC)
-static void nulldisp_crtc_flip_done(struct nulldisp_crtc *nulldisp_crtc)
-{
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-
-       struct drm_framebuffer *old_fb;
-
-       WARN_ON(atomic_read(&nulldisp_crtc->flip_status) !=
-               NULLDISP_CRTC_FLIP_STATUS_PENDING);
-
-       old_fb = nulldisp_crtc->old_fb;
-       nulldisp_crtc->old_fb = NULL;
-
-       (void) nulldisp_crtc_helper_mode_set_base(crtc, crtc->x, crtc->y,
-                                                 old_fb);
-
-       atomic_set(&nulldisp_crtc->flip_status, NULLDISP_CRTC_FLIP_STATUS_DONE);
-
-       if (nulldisp_crtc->flip_async)
-               nulldisp_crtc_flip_complete(crtc);
-}
-
-static bool nulldisp_set_flip_to(struct nulldisp_crtc *nulldisp_crtc)
-{
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-       struct nulldisp_display_device *nulldisp_dev = crtc->dev->dev_private;
-
-       /* Returns false if work already queued, else true */
-       return queue_delayed_work(nulldisp_dev->workqueue,
-                                 &nulldisp_crtc->flip_to_work,
-                                 nulldisp_netlink_timeout());
-}
-
-static bool nulldisp_set_copy_to(struct nulldisp_crtc *nulldisp_crtc)
-{
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-       struct nulldisp_display_device *nulldisp_dev = crtc->dev->dev_private;
-
-       /* Returns false if work already queued, else true */
-       return queue_delayed_work(nulldisp_dev->workqueue,
-                                 &nulldisp_crtc->copy_to_work,
-                                 nulldisp_netlink_timeout());
-}
-
-static void nulldisp_flip_to_work(struct work_struct *w)
-{
-       struct delayed_work *dw =
-               container_of(w, struct delayed_work, work);
-       struct nulldisp_crtc *nulldisp_crtc =
-               container_of(dw, struct nulldisp_crtc, flip_to_work);
-
-       if (atomic_read(&nulldisp_crtc->flip_status) ==
-           NULLDISP_CRTC_FLIP_STATUS_PENDING)
-               nulldisp_crtc_flip_done(nulldisp_crtc);
-}
-
-static void nulldisp_copy_to_work(struct work_struct *w)
-{
-       struct delayed_work *dw =
-               container_of(w, struct delayed_work, work);
-       struct nulldisp_crtc *nulldisp_crtc =
-               container_of(dw, struct nulldisp_crtc, copy_to_work);
-
-       complete(&nulldisp_crtc->copy_done);
-}
-
-static void nulldisp_flip_work(struct work_struct *w)
-{
-       struct nulldisp_crtc *nulldisp_crtc =
-               container_of(w, struct nulldisp_crtc, flip_work);
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-       struct drm_device *dev = crtc->dev;
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-       struct nulldisp_framebuffer *nulldisp_fb =
-               to_nulldisp_framebuffer(crtc->primary->fb);
-
-       /*
-        * To prevent races with disconnect requests from user space,
-        * set the timeout before sending the flip request.
-        */
-       nulldisp_set_flip_to(nulldisp_crtc);
-
-       if (nlpvrdpy_send_flip(nulldisp_dev->nlpvrdpy,
-                              &nulldisp_fb->base,
-                              &nulldisp_fb->obj[0]))
-               goto fail_cancel;
-
-       return;
-
-fail_cancel:
-       /*
-        * We can't flush the work, as we are running on the same
-        * single threaded workqueue as the work to be flushed.
-        */
-       cancel_delayed_work(&nulldisp_crtc->flip_to_work);
-
-       nulldisp_crtc_flip_done(nulldisp_crtc);
-}
-
-static void nulldisp_crtc_flip_cb(struct dma_fence *fence,
-                                 struct dma_fence_cb *cb)
-{
-       struct nulldisp_flip_data *flip_data =
-               container_of(cb, struct nulldisp_flip_data, base);
-       struct drm_crtc *crtc = flip_data->crtc;
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-       struct drm_device *dev = crtc->dev;
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       (void) queue_work(nulldisp_dev->workqueue,
-                         &nulldisp_crtc->flip_work);
-
-       complete_all(&nulldisp_crtc->flip_scheduled);
-}
-
-static void nulldisp_crtc_flip_schedule_cb(struct dma_fence *fence,
-                                          struct dma_fence_cb *cb)
-{
-       struct nulldisp_flip_data *flip_data =
-               container_of(cb, struct nulldisp_flip_data, base);
-       int err = 0;
-
-       if (flip_data->wait_fence)
-               err = dma_fence_add_callback(flip_data->wait_fence,
-                                            &flip_data->base,
-                                            nulldisp_crtc_flip_cb);
-
-       if (!flip_data->wait_fence || err) {
-               if (err && err != -ENOENT)
-                       DRM_ERROR("flip failed to wait on old buffer\n");
-               nulldisp_crtc_flip_cb(flip_data->wait_fence, &flip_data->base);
-       }
-}
-
-static int nulldisp_crtc_flip_schedule(struct drm_crtc *crtc,
-                                      struct drm_gem_object *obj,
-                                      struct drm_gem_object *old_obj)
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-       struct dma_resv *resv = obj_to_resv(obj);
-       struct dma_resv *old_resv = obj_to_resv(old_obj);
-       struct nulldisp_flip_data *flip_data;
-       struct dma_fence *fence;
-       int err;
-
-       flip_data = kmalloc(sizeof(*flip_data), GFP_KERNEL);
-       if (!flip_data)
-               return -ENOMEM;
-
-       flip_data->crtc = crtc;
-
-       ww_mutex_lock(&old_resv->lock, NULL);
-       flip_data->wait_fence =
-               dma_fence_get(dma_resv_get_excl(old_resv));
-
-       if (old_resv != resv) {
-               ww_mutex_unlock(&old_resv->lock);
-               ww_mutex_lock(&resv->lock, NULL);
-       }
-
-       fence = dma_fence_get(dma_resv_get_excl(resv));
-       ww_mutex_unlock(&resv->lock);
-
-       nulldisp_crtc->flip_data = flip_data;
-       reinit_completion(&nulldisp_crtc->flip_scheduled);
-       atomic_set(&nulldisp_crtc->flip_status,
-                  NULLDISP_CRTC_FLIP_STATUS_PENDING);
-
-       if (fence) {
-               err = dma_fence_add_callback(fence, &flip_data->base,
-                                            nulldisp_crtc_flip_schedule_cb);
-               dma_fence_put(fence);
-               if (err && err != -ENOENT)
-                       goto err_set_flip_status_none;
-       }
-
-       if (!fence || err == -ENOENT) {
-               nulldisp_crtc_flip_schedule_cb(fence, &flip_data->base);
-               err = 0;
-       }
-
-       return err;
-
-err_set_flip_status_none:
-       atomic_set(&nulldisp_crtc->flip_status, NULLDISP_CRTC_FLIP_STATUS_NONE);
-       dma_fence_put(flip_data->wait_fence);
-       kfree(flip_data);
-       return err;
-}
-
-static int nulldisp_crtc_page_flip(struct drm_crtc *crtc,
-                                  struct drm_framebuffer *fb,
-                                  struct drm_pending_vblank_event *event,
-                                  uint32_t page_flip_flags
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
-                                  , struct drm_modeset_acquire_ctx *ctx
-#endif
-                                  )
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-       struct nulldisp_framebuffer *nulldisp_fb = to_nulldisp_framebuffer(fb);
-       struct nulldisp_framebuffer *nulldisp_old_fb =
-               to_nulldisp_framebuffer(crtc->primary->fb);
-       enum nulldisp_crtc_flip_status status;
-       unsigned long flags;
-       int err;
-
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-       status = atomic_read(&nulldisp_crtc->flip_status);
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-       if (status != NULLDISP_CRTC_FLIP_STATUS_NONE)
-               return -EBUSY;
-
-       if (!(page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC)) {
-               err = drm_crtc_vblank_get(crtc);
-               if (err)
-                       return err;
-       }
-
-       nulldisp_crtc->old_fb = crtc->primary->fb;
-       nulldisp_crtc->flip_event = event;
-       nulldisp_crtc->flip_async = !!(page_flip_flags &
-                                      DRM_MODE_PAGE_FLIP_ASYNC);
-
-       /* Set the crtc to point to the new framebuffer */
-       crtc->primary->fb = fb;
-
-       err = nulldisp_crtc_flip_schedule(crtc, nulldisp_fb->obj[0],
-                                         nulldisp_old_fb->obj[0]);
-       if (err) {
-               crtc->primary->fb = nulldisp_crtc->old_fb;
-               nulldisp_crtc->old_fb = NULL;
-               nulldisp_crtc->flip_event = NULL;
-               nulldisp_crtc->flip_async = false;
-
-               DRM_ERROR("failed to schedule flip (err=%d)\n", err);
-               goto err_vblank_put;
-       }
-
-       return 0;
-
-err_vblank_put:
-       if (!(page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC))
-               drm_crtc_vblank_put(crtc);
-       return err;
-}
-#endif /* !defined(NULLDISP_USE_ATOMIC) */
-
-static bool nulldisp_queue_vblank_work(struct nulldisp_crtc *nulldisp_crtc)
-{
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-       struct nulldisp_display_device *nulldisp_dev = crtc->dev->dev_private;
-       int vrefresh;
-       const int vrefresh_default = 60;
-
-       vrefresh = drm_mode_vrefresh(&crtc->hwmode);
-       if (!vrefresh) {
-               vrefresh = vrefresh_default;
-               DRM_INFO_ONCE(
-                       "vertical refresh rate is zero, defaulting to %d\n",
-                       vrefresh);
-       }
-
-       /* Returns false if work already queued, else true */
-       return queue_delayed_work(nulldisp_dev->workqueue,
-                                 &nulldisp_crtc->vb_work,
-                                 usecs_to_jiffies(1000000/vrefresh));
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
-static int nulldisp_enable_vblank(struct drm_crtc *crtc)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
-       (defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)))
-static int nulldisp_enable_vblank(struct drm_device *dev, unsigned int pipe)
-#else
-static int nulldisp_enable_vblank(struct drm_device *dev, int pipe)
-#endif
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
-       struct drm_device *dev = crtc->dev;
-       unsigned int pipe      = drm_crtc_index(crtc);
-#endif
-
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       switch (pipe) {
-       case 0:
-               break;
-       default:
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-               DRM_ERROR("invalid crtc %u\n", pipe);
-#else
-               DRM_ERROR("invalid crtc %d\n", pipe);
-#endif
-               return -EINVAL;
-       }
-
-       if (!nulldisp_queue_vblank_work(nulldisp_dev->nulldisp_crtc)) {
-               DRM_ERROR("work already queued\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
-static void nulldisp_disable_vblank(struct drm_crtc *crtc)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) || \
-       (defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)))
-static void nulldisp_disable_vblank(struct drm_device *dev, unsigned int pipe)
-#else
-static void nulldisp_disable_vblank(struct drm_device *dev, int pipe)
-#endif
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
-       struct drm_device *dev = crtc->dev;
-       unsigned int pipe      = drm_crtc_index(crtc);
-#endif
-
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       switch (pipe) {
-       case 0:
-               break;
-       default:
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-               DRM_ERROR("invalid crtc %u\n", pipe);
-#else
-               DRM_ERROR("invalid crtc %d\n", pipe);
-#endif
-               return;
-       }
-
-       /*
-        * Vblank events may be disabled from within the vblank handler,
-        * so don't wait for the work to complete.
-        */
-       (void) cancel_delayed_work(&nulldisp_dev->nulldisp_crtc->vb_work);
-}
-
-static const struct drm_crtc_helper_funcs nulldisp_crtc_helper_funcs = {
-       .mode_fixup = nulldisp_crtc_helper_mode_fixup,
-#if defined(NULLDISP_USE_ATOMIC)
-       .mode_set_nofb = nulldisp_crtc_helper_mode_set_nofb,
-       .atomic_flush = nulldisp_crtc_helper_atomic_flush,
-       .atomic_enable = nulldisp_crtc_helper_atomic_enable,
-       .atomic_disable = nulldisp_crtc_helper_atomic_disable,
-#else
-       .dpms = nulldisp_crtc_helper_dpms,
-       .prepare = nulldisp_crtc_helper_prepare,
-       .commit = nulldisp_crtc_helper_commit,
-       .mode_set = nulldisp_crtc_helper_mode_set,
-       .mode_set_base = nulldisp_crtc_helper_mode_set_base,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-       .load_lut = nulldisp_crtc_helper_load_lut,
-#endif
-       .mode_set_base_atomic = nulldisp_crtc_helper_mode_set_base_atomic,
-       .disable = nulldisp_crtc_helper_disable,
-#endif /* defined(NULLDISP_USE_ATOMIC) */
-};
-
-static const struct drm_crtc_funcs nulldisp_crtc_funcs = {
-       .destroy = nulldisp_crtc_destroy,
-#if defined(NULLDISP_USE_ATOMIC)
-       .reset = drm_atomic_helper_crtc_reset,
-       .set_config = drm_atomic_helper_set_config,
-       .page_flip = drm_atomic_helper_page_flip,
-       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
-#else
-       .reset = NULL,
-       .cursor_set = NULL,
-       .cursor_move = NULL,
-       .gamma_set = NULL,
-       .set_config = drm_crtc_helper_set_config,
-       .page_flip = nulldisp_crtc_page_flip,
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0))
-       .enable_vblank  = nulldisp_enable_vblank,
-       .disable_vblank = nulldisp_disable_vblank,
-#endif
-};
-
-static void nulldisp_handle_vblank(struct work_struct *w)
-{
-       struct delayed_work *dw =
-               container_of(w, struct delayed_work, work);
-       struct nulldisp_crtc *nulldisp_crtc =
-               container_of(dw, struct nulldisp_crtc, vb_work);
-       struct drm_crtc *crtc = &nulldisp_crtc->base;
-       struct drm_device *dev = crtc->dev;
-       enum nulldisp_crtc_flip_status status;
-
-       /*
-        * Reschedule the handler, if necessary. This is done before
-        * calling drm_crtc_vblank_put, so that the work can be cancelled
-        * if vblank events are disabled.
-        */
-       if (drm_handle_vblank(dev, 0))
-               (void) nulldisp_queue_vblank_work(nulldisp_crtc);
-
-       status = atomic_read(&nulldisp_crtc->flip_status);
-       if (status == NULLDISP_CRTC_FLIP_STATUS_DONE) {
-               if (!nulldisp_crtc->flip_async)
-                       nulldisp_crtc_flip_complete(crtc);
-#if !defined(NULLDISP_USE_ATOMIC)
-               drm_crtc_vblank_put(crtc);
-#endif
-       }
-
-}
-
-static struct nulldisp_crtc *
-nulldisp_crtc_create(struct nulldisp_display_device *nulldisp_dev)
-{
-       struct nulldisp_crtc *nulldisp_crtc;
-       struct drm_crtc *crtc;
-       struct drm_plane *primary;
-
-       nulldisp_crtc = kzalloc(sizeof(*nulldisp_crtc), GFP_KERNEL);
-       if (!nulldisp_crtc)
-               goto err_return;
-
-       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-       if (!primary)
-               goto err_free_crtc;
-
-       crtc = &nulldisp_crtc->base;
-
-       atomic_set(&nulldisp_crtc->flip_status, NULLDISP_CRTC_FLIP_STATUS_NONE);
-#if defined(NULLDISP_USE_ATOMIC)
-       init_completion(&nulldisp_crtc->flip_done);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0))
-       init_completion(&nulldisp_crtc->copy_done);
-#endif
-#else
-       init_completion(&nulldisp_crtc->flip_scheduled);
-       init_completion(&nulldisp_crtc->copy_done);
-#endif
-
-       if (drm_universal_plane_init(nulldisp_dev->dev, primary, 0,
-                                    &nulldisp_plane_funcs,
-                                    nulldisp_modeset_formats,
-                                    ARRAY_SIZE(nulldisp_modeset_formats),
-                                    nulldisp_primary_plane_modifiers,
-                                    DRM_PLANE_TYPE_PRIMARY, NULL)) {
-               goto err_free_primary;
-       }
-
-#if defined(NULLDISP_USE_ATOMIC)
-       drm_plane_helper_add(primary, &nulldisp_plane_helper_funcs);
-#endif
-
-       if (drm_crtc_init_with_planes(nulldisp_dev->dev, crtc, primary,
-                                     NULL, &nulldisp_crtc_funcs, NULL)) {
-               goto err_cleanup_plane;
-       }
-
-       drm_crtc_helper_add(crtc, &nulldisp_crtc_helper_funcs);
-
-       INIT_DELAYED_WORK(&nulldisp_crtc->vb_work, nulldisp_handle_vblank);
-#if !defined(NULLDISP_USE_ATOMIC)
-       INIT_WORK(&nulldisp_crtc->flip_work, nulldisp_flip_work);
-       INIT_DELAYED_WORK(&nulldisp_crtc->copy_to_work, nulldisp_copy_to_work);
-       INIT_DELAYED_WORK(&nulldisp_crtc->flip_to_work, nulldisp_flip_to_work);
-#endif
-
-       DRM_DEBUG_DRIVER("[CRTC:%d]\n", crtc->base.id);
-
-       return nulldisp_crtc;
-
-err_cleanup_plane:
-       drm_plane_cleanup(primary);
-err_free_primary:
-       kfree(primary);
-err_free_crtc:
-       kfree(nulldisp_crtc);
-err_return:
-       return NULL;
-}
-
-
-/******************************************************************************
- * Connector functions
- ******************************************************************************/
-
-static int
-nulldisp_validate_module_parameters(void)
-{
-       const struct nulldisp_module_params *module_params =
-               nulldisp_get_module_params();
-
-       if (!module_params->hdisplay ||
-           !module_params->vdisplay ||
-           !module_params->vrefresh ||
-           (module_params->hdisplay > NULLDISP_FB_WIDTH_MAX) ||
-           (module_params->vdisplay > NULLDISP_FB_HEIGHT_MAX))
-               return -EINVAL;
-
-       return 0;
-}
-
-static bool
-nulldisp_set_preferred_mode(struct drm_connector *connector,
-                           uint32_t hdisplay,
-                           uint32_t vdisplay,
-                           uint32_t vrefresh)
-{
-       struct drm_display_mode *mode;
-
-       /*
-        * Mark the first mode, matching the hdisplay, vdisplay and
-        * vrefresh, preferred.
-        */
-       list_for_each_entry(mode, &connector->probed_modes, head)
-               if (mode->hdisplay == hdisplay &&
-                   mode->vdisplay == vdisplay &&
-                   drm_mode_vrefresh(mode) == vrefresh) {
-                       mode->type |= DRM_MODE_TYPE_PREFERRED;
-                       return true;
-               }
-
-       return false;
-}
-
-static bool
-nulldisp_connector_add_preferred_mode(struct drm_connector *connector,
-                                     uint32_t hdisplay,
-                                     uint32_t vdisplay,
-                                     uint32_t vrefresh)
-{
-       struct drm_display_mode *preferred_mode;
-
-       preferred_mode = drm_cvt_mode(connector->dev,
-                                     hdisplay, vdisplay, vrefresh,
-                                     false, false, false);
-       if (!preferred_mode) {
-               DRM_DEBUG_DRIVER("[CONNECTOR:%s]:create mode %dx%d@%d failed\n",
-                                connector->name,
-                                hdisplay,
-                                vdisplay,
-                                vrefresh);
-
-               return false;
-       }
-
-       preferred_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-
-       drm_mode_probed_add(connector, preferred_mode);
-
-       return true;
-}
-
-/*
- * Gather modes. Here we can get the EDID data from the monitor and
- * turn it into drm_display_mode structures.
- */
-static int
-nulldisp_connector_helper_get_modes(struct drm_connector *connector)
-{
-       int modes_count;
-       struct drm_device *dev = connector->dev;
-       const struct nulldisp_module_params *module_params =
-               nulldisp_get_module_params();
-       uint32_t hdisplay = module_params->hdisplay;
-       uint32_t vdisplay = module_params->vdisplay;
-       uint32_t vrefresh = module_params->vrefresh;
-
-       /* Add common modes */
-       modes_count = drm_add_modes_noedid(connector,
-                                          dev->mode_config.max_width,
-                                          dev->mode_config.max_height);
-
-       /*
-        * Check if any of the connector modes match the preferred mode
-        * criteria specified by the module parameters. If the mode is
-        * found - flag it as preferred. Otherwise create the preferred
-        * mode based on the module parameters criteria, and flag it as
-        * preferred.
-        */
-       if (!nulldisp_set_preferred_mode(connector,
-                                        hdisplay,
-                                        vdisplay,
-                                        vrefresh))
-               if (nulldisp_connector_add_preferred_mode(connector,
-                                                         hdisplay,
-                                                         vdisplay,
-                                                         vrefresh))
-                       modes_count++;
-
-       /* Sort the connector modes by relevance */
-       drm_mode_sort(&connector->probed_modes);
-
-       return modes_count;
-}
-
-static int
-nulldisp_connector_helper_mode_valid(struct drm_connector *connector,
-                                    struct drm_display_mode *mode)
-{
-       /*
-        * This function is called on each gathered mode (e.g. via EDID)
-        * and gives the driver a chance to reject it if the hardware
-        * cannot support it.
-        */
-       return MODE_OK;
-}
-
-#if !defined(NULLDISP_USE_ATOMIC)
-static struct drm_encoder *
-nulldisp_connector_helper_best_encoder(struct drm_connector *connector)
-{
-       /* Pick the first encoder we find */
-       if (connector->encoder_ids[0] != 0) {
-               struct drm_encoder *encoder;
-
-               encoder = drm_encoder_find(connector->dev,
-                                          NULL,
-                                          connector->encoder_ids[0]);
-               if (encoder) {
-                       DRM_DEBUG_DRIVER(
-                               "[ENCODER:%d:%s] best for [CONNECTOR:%d:%s]\n",
-                                encoder->base.id,
-                                encoder->name,
-                                connector->base.id,
-                                connector->name);
-                       return encoder;
-               }
-       }
-
-       return NULL;
-}
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-static enum drm_connector_status
-nulldisp_connector_detect(struct drm_connector *connector,
-                         bool force)
-{
-       /* Return whether or not a monitor is attached to the connector */
-       return connector_status_connected;
-}
-#endif
-
-static void nulldisp_connector_destroy(struct drm_connector *connector)
-{
-       DRM_DEBUG_DRIVER("[CONNECTOR:%d:%s]\n",
-                        connector->base.id,
-                        connector->name);
-
-       drm_connector_update_edid_property(connector, NULL);
-       drm_connector_cleanup(connector);
-
-       kfree(connector);
-}
-
-static void nulldisp_connector_force(struct drm_connector *connector)
-{
-}
-
-static const struct drm_connector_helper_funcs
-nulldisp_connector_helper_funcs = {
-       .get_modes = nulldisp_connector_helper_get_modes,
-       .mode_valid = nulldisp_connector_helper_mode_valid,
-       /*
-        * For atomic, don't set atomic_best_encoder or best_encoder. This will
-        * cause the DRM core to fallback to drm_atomic_helper_best_encoder().
-        * This is fine as we only have a single connector and encoder.
-        */
-#if !defined(NULLDISP_USE_ATOMIC)
-       .best_encoder = nulldisp_connector_helper_best_encoder,
-#endif
-};
-
-static const struct drm_connector_funcs nulldisp_connector_funcs = {
-#if defined(NULLDISP_USE_ATOMIC)
-       .reset = drm_atomic_helper_connector_reset,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-#else
-       .dpms = drm_helper_connector_dpms,
-       .reset = NULL,
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
-       .detect = nulldisp_connector_detect,
-#endif
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = nulldisp_connector_destroy,
-       .force = nulldisp_connector_force,
-};
-
-static struct drm_connector *
-nulldisp_connector_create(struct nulldisp_display_device *nulldisp_dev,
-                         int type)
-{
-       struct drm_connector *connector;
-
-       connector = kzalloc(sizeof(*connector), GFP_KERNEL);
-       if (!connector)
-               return NULL;
-
-       drm_connector_init(nulldisp_dev->dev,
-                          connector,
-                          &nulldisp_connector_funcs,
-                          type);
-       drm_connector_helper_add(connector, &nulldisp_connector_helper_funcs);
-
-       connector->dpms = DRM_MODE_DPMS_OFF;
-       connector->interlace_allowed = false;
-       connector->doublescan_allowed = false;
-       connector->display_info.subpixel_order = SubPixelUnknown;
-
-       DRM_DEBUG_DRIVER("[CONNECTOR:%d:%s]\n",
-                        connector->base.id,
-                        connector->name);
-
-       return connector;
-}
-
-
-/******************************************************************************
- * Encoder functions
- ******************************************************************************/
-
-static void nulldisp_encoder_helper_dpms(struct drm_encoder *encoder,
-                                        int mode)
-{
-       /*
-        * Set the display power state or active encoder based on the mode. If
-        * the mode passed in is unsupported, the provider must use the next
-        * lowest power level.
-        */
-}
-
-static bool
-nulldisp_encoder_helper_mode_fixup(struct drm_encoder *encoder,
-                                  const struct drm_display_mode *mode,
-                                  struct drm_display_mode *adjusted_mode)
-{
-       /*
-        * Fix up mode so that it's compatible with the hardware. The results
-        * should be stored in adjusted_mode (i.e. mode should be untouched).
-        */
-       return true;
-}
-
-static void nulldisp_encoder_helper_prepare(struct drm_encoder *encoder)
-{
-       /*
-        * Prepare the encoder for a mode change e.g. set the active encoder
-        * accordingly/turn the encoder off
-        */
-}
-
-static void nulldisp_encoder_helper_commit(struct drm_encoder *encoder)
-{
-       /* Turn the encoder back on/set the active encoder */
-}
-
-static void
-nulldisp_encoder_helper_mode_set(struct drm_encoder *encoder,
-                                struct drm_display_mode *mode,
-                                struct drm_display_mode *adjusted_mode)
-{
-       /* Setup the encoder for the new mode */
-}
-
-static void nulldisp_encoder_destroy(struct drm_encoder *encoder)
-{
-       DRM_DEBUG_DRIVER("[ENCODER:%d:%s]\n", encoder->base.id, encoder->name);
-
-       drm_encoder_cleanup(encoder);
-       kfree(encoder);
-}
-
-static const struct drm_encoder_helper_funcs nulldisp_encoder_helper_funcs = {
-       .dpms = nulldisp_encoder_helper_dpms,
-       .mode_fixup = nulldisp_encoder_helper_mode_fixup,
-       .prepare = nulldisp_encoder_helper_prepare,
-       .commit = nulldisp_encoder_helper_commit,
-       .mode_set = nulldisp_encoder_helper_mode_set,
-       .detect = NULL,
-       .disable = NULL,
-};
-
-static const struct drm_encoder_funcs nulldisp_encoder_funcs = {
-       .reset = NULL,
-       .destroy = nulldisp_encoder_destroy,
-};
-
-static struct drm_encoder *
-nulldisp_encoder_create(struct nulldisp_display_device *nulldisp_dev,
-                       int type)
-{
-       struct drm_encoder *encoder;
-       int err;
-
-       encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
-       if (!encoder)
-               return ERR_PTR(-ENOMEM);
-
-       err = drm_encoder_init(nulldisp_dev->dev,
-                              encoder,
-                              &nulldisp_encoder_funcs,
-                              type,
-                              NULL);
-       if (err) {
-               DRM_ERROR("Failed to initialise encoder\n");
-               return ERR_PTR(err);
-       }
-       drm_encoder_helper_add(encoder, &nulldisp_encoder_helper_funcs);
-
-       /*
-        * This is a bit field that's used to determine which
-        * CRTCs can drive this encoder.
-        */
-       encoder->possible_crtcs = 0x1;
-
-       DRM_DEBUG_DRIVER("[ENCODER:%d:%s]\n", encoder->base.id, encoder->name);
-
-       return encoder;
-}
-
-
-/******************************************************************************
- * Framebuffer functions
- ******************************************************************************/
-
-#if defined(NULLDISP_USE_ATOMIC)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0))
-static int
-nulldisp_framebuffer_dirty(struct drm_framebuffer *framebuffer,
-                          struct drm_file *file_priv,
-                          unsigned int flags,
-                          unsigned int color,
-                          struct drm_clip_rect *clips,
-                          unsigned int num_clips)
-{
-       struct nulldisp_display_device *nulldisp_dev =
-               framebuffer->dev->dev_private;
-       struct nulldisp_crtc *nulldisp_crtc = nulldisp_dev->nulldisp_crtc;
-
-       reinit_completion(&nulldisp_crtc->copy_done);
-
-       if (!nlpvrdpy_send_copy(nulldisp_dev->nlpvrdpy,
-                               framebuffer,
-                               &framebuffer->obj[0])) {
-               unsigned long res;
-
-               res = wait_for_completion_timeout(&nulldisp_crtc->copy_done,
-                                                 nulldisp_netlink_timeout());
-
-               if (!res)
-                       DRM_ERROR("timed out waiting for remote update\n");
-       }
-
-       return 0;
-}
-
-static const struct drm_framebuffer_funcs nulldisp_framebuffer_funcs = {
-       .destroy = drm_gem_fb_destroy,
-       .create_handle = drm_gem_fb_create_handle,
-       .dirty = nulldisp_framebuffer_dirty,
-};
-
-static struct drm_framebuffer *
-nulldisp_fb_create(struct drm_device *dev, struct drm_file *file,
-                  const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       return drm_gem_fb_create_with_funcs(dev, file, mode_cmd,
-                                           &nulldisp_framebuffer_funcs);
-}
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0)) */
-#define nulldisp_fb_create drm_gem_fb_create_with_dirty
-#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0)) */
-#else /* defined(NULLDISP_USE_ATOMIC) */
-static void nulldisp_framebuffer_destroy(struct drm_framebuffer *framebuffer)
-{
-       struct nulldisp_framebuffer *nulldisp_framebuffer =
-               to_nulldisp_framebuffer(framebuffer);
-       int i;
-
-       DRM_DEBUG_DRIVER("[FB:%d]\n", framebuffer->base.id);
-
-       drm_framebuffer_cleanup(framebuffer);
-
-       for (i = 0; i < nulldisp_drm_fb_num_planes(framebuffer); i++)
-               drm_gem_object_put(nulldisp_framebuffer->obj[i]);
-
-       kfree(nulldisp_framebuffer);
-}
-
-static int
-nulldisp_framebuffer_create_handle(struct drm_framebuffer *framebuffer,
-                                  struct drm_file *file_priv,
-                                  unsigned int *handle)
-{
-       struct nulldisp_framebuffer *nulldisp_framebuffer =
-               to_nulldisp_framebuffer(framebuffer);
-
-       DRM_DEBUG_DRIVER("[FB:%d]\n", framebuffer->base.id);
-
-       return drm_gem_handle_create(file_priv,
-                                    nulldisp_framebuffer->obj[0],
-                                    handle);
-}
-
-static int
-nulldisp_framebuffer_dirty(struct drm_framebuffer *framebuffer,
-                          struct drm_file *file_priv,
-                          unsigned int flags,
-                          unsigned int color,
-                          struct drm_clip_rect *clips,
-                          unsigned int num_clips)
-{
-       struct nulldisp_framebuffer *nulldisp_fb =
-               to_nulldisp_framebuffer(framebuffer);
-       struct nulldisp_display_device *nulldisp_dev =
-               framebuffer->dev->dev_private;
-       struct nulldisp_crtc *nulldisp_crtc = nulldisp_dev->nulldisp_crtc;
-
-       /*
-        * To prevent races with disconnect requests from user space,
-        * set the timeout before sending the copy request.
-        */
-       nulldisp_set_copy_to(nulldisp_crtc);
-
-       if (nlpvrdpy_send_copy(nulldisp_dev->nlpvrdpy,
-                              &nulldisp_fb->base,
-                              &nulldisp_fb->obj[0]))
-               goto fail_flush;
-
-       wait_for_completion(&nulldisp_crtc->copy_done);
-
-       return 0;
-
-fail_flush:
-       flush_delayed_work(&nulldisp_crtc->copy_to_work);
-
-       wait_for_completion(&nulldisp_crtc->copy_done);
-
-       return 0;
-
-}
-
-static const struct drm_framebuffer_funcs nulldisp_framebuffer_funcs = {
-       .destroy = nulldisp_framebuffer_destroy,
-       .create_handle = nulldisp_framebuffer_create_handle,
-       .dirty = nulldisp_framebuffer_dirty,
-};
-
-static int
-nulldisp_framebuffer_init(struct drm_device *dev,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
-       (defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)))
-                         const
-#endif
-                         struct drm_mode_fb_cmd2 *mode_cmd,
-                         struct nulldisp_framebuffer *nulldisp_framebuffer,
-                         struct drm_gem_object **obj)
-{
-       struct drm_framebuffer *fb = &nulldisp_framebuffer->base;
-       int err;
-       int i;
-
-       fb->dev = dev;
-
-       nulldisp_drm_fb_set_format(fb, mode_cmd->pixel_format);
-
-       fb->width        = mode_cmd->width;
-       fb->height       = mode_cmd->height;
-       fb->flags        = mode_cmd->flags;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
-       nulldisp_drm_fb_set_modifier(fb, mode_cmd->modifier[0]);
-#endif
-
-       for (i = 0; i < nulldisp_drm_fb_num_planes(fb); i++) {
-               fb->pitches[i]  = mode_cmd->pitches[i];
-               fb->offsets[i]  = mode_cmd->offsets[i];
-
-               nulldisp_framebuffer->obj[i] = obj[i];
-       }
-
-       err = drm_framebuffer_init(dev, fb, &nulldisp_framebuffer_funcs);
-       if (err) {
-               DRM_ERROR("failed to initialise framebuffer structure (%d)\n",
-                         err);
-               return err;
-       }
-
-       DRM_DEBUG_DRIVER("[FB:%d]\n", fb->base.id);
-
-       return 0;
-}
-
-static struct drm_framebuffer *
-nulldisp_fb_create(struct drm_device *dev,
-                  struct drm_file *file_priv,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) || \
-       (defined(CHROMIUMOS_KERNEL) && \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)))
-                  const
-#endif
-                  struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       struct drm_gem_object *obj[NULLDISP_MAX_PLANES];
-       struct nulldisp_framebuffer *nulldisp_framebuffer;
-       int err;
-       int i;
-
-       nulldisp_framebuffer = kzalloc(sizeof(*nulldisp_framebuffer),
-                                      GFP_KERNEL);
-       if (!nulldisp_framebuffer) {
-               err = -ENOMEM;
-               goto fail_exit;
-       }
-
-       for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
-               obj[i] = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
-               if (!obj[i]) {
-                       DRM_ERROR("failed to find buffer with handle %u\n",
-                                 mode_cmd->handles[i]);
-                       err = -ENOENT;
-                       goto fail_unreference;
-               }
-       }
-
-       err = nulldisp_framebuffer_init(dev,
-                                       mode_cmd,
-                                       nulldisp_framebuffer,
-                                       obj);
-       if (err)
-               goto fail_unreference;
-
-       DRM_DEBUG_DRIVER("[FB:%d]\n", nulldisp_framebuffer->base.base.id);
-
-       return &nulldisp_framebuffer->base;
-
-fail_unreference:
-       kfree(nulldisp_framebuffer);
-
-       while (i--)
-               drm_gem_object_put(obj[i]);
-
-fail_exit:
-       return ERR_PTR(err);
-}
-#endif /* defined(NULLDISP_USE_ATOMIC) */
-
-static const struct drm_mode_config_funcs nulldisp_mode_config_funcs = {
-       .fb_create = nulldisp_fb_create,
-       .output_poll_changed = NULL,
-#if defined(NULLDISP_USE_ATOMIC)
-       .atomic_check = drm_atomic_helper_check,
-       .atomic_commit = drm_atomic_helper_commit,
-#endif
-};
-
-static int nulldisp_nl_flipped_cb(void *data)
-{
-       struct nulldisp_crtc *nulldisp_crtc = data;
-
-#if defined(NULLDISP_USE_ATOMIC)
-       complete(&nulldisp_crtc->flip_done);
-#else
-       flush_delayed_work(&nulldisp_crtc->flip_to_work);
-#endif
-       flush_delayed_work(&nulldisp_crtc->vb_work);
-
-       return 0;
-}
-
-static int nulldisp_nl_copied_cb(void *data)
-{
-#if defined(NULLDISP_USE_ATOMIC)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0))
-       struct nulldisp_crtc *nulldisp_crtc = data;
-
-       complete(&nulldisp_crtc->copy_done);
-#endif
-#else
-       struct nulldisp_crtc *nulldisp_crtc = data;
-
-       flush_delayed_work(&nulldisp_crtc->copy_to_work);
-#endif
-       return 0;
-}
-
-static void nulldisp_nl_disconnect_cb(void *data)
-{
-       struct nulldisp_crtc *nulldisp_crtc = data;
-
-#if defined(NULLDISP_USE_ATOMIC)
-       complete(&nulldisp_crtc->flip_done);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0))
-       complete(&nulldisp_crtc->copy_done);
-#endif
-#else
-       flush_delayed_work(&nulldisp_crtc->flip_to_work);
-       flush_delayed_work(&nulldisp_crtc->copy_to_work);
-#endif
-}
-
-static int nulldisp_early_load(struct drm_device *dev)
-{
-       struct nulldisp_display_device *nulldisp_dev;
-       struct drm_connector *connector;
-       struct drm_encoder *encoder;
-       int err;
-
-       platform_set_drvdata(to_platform_device(dev->dev), dev);
-
-       nulldisp_dev = kzalloc(sizeof(*nulldisp_dev), GFP_KERNEL);
-       if (!nulldisp_dev)
-               return -ENOMEM;
-
-       dev->dev_private = nulldisp_dev;
-       nulldisp_dev->dev = dev;
-
-       drm_mode_config_init(dev);
-
-       dev->mode_config.funcs = (void *)&nulldisp_mode_config_funcs;
-       dev->mode_config.min_width = NULLDISP_FB_WIDTH_MIN;
-       dev->mode_config.max_width = NULLDISP_FB_WIDTH_MAX;
-       dev->mode_config.min_height = NULLDISP_FB_HEIGHT_MIN;
-       dev->mode_config.max_height = NULLDISP_FB_HEIGHT_MAX;
-       dev->mode_config.fb_base = 0;
-       dev->mode_config.async_page_flip = true;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
-       dev->mode_config.allow_fb_modifiers = true;
-#endif
-
-       nulldisp_dev->nulldisp_crtc = nulldisp_crtc_create(nulldisp_dev);
-       if (!nulldisp_dev->nulldisp_crtc) {
-               DRM_ERROR("failed to create a CRTC.\n");
-
-               err = -ENOMEM;
-               goto err_config_cleanup;
-       }
-
-       connector = nulldisp_connector_create(nulldisp_dev,
-                                             DRM_MODE_CONNECTOR_Unknown);
-       if (!connector) {
-               DRM_ERROR("failed to create a connector.\n");
-
-               err = -ENOMEM;
-               goto err_config_cleanup;
-       }
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-       nulldisp_dev->connector = connector;
-#endif
-       encoder = nulldisp_encoder_create(nulldisp_dev,
-                                         DRM_MODE_ENCODER_NONE);
-       if (IS_ERR(encoder)) {
-               DRM_ERROR("failed to create an encoder.\n");
-
-               err = PTR_ERR(encoder);
-               goto err_config_cleanup;
-       }
-
-       err = drm_connector_attach_encoder(connector, encoder);
-       if (err) {
-               DRM_ERROR("failed to attach [ENCODER:%d:%s] to [CONNECTOR:%d:%s] (err=%d)\n",
-                         encoder->base.id,
-                         encoder->name,
-                         connector->base.id,
-                         connector->name,
-                         err);
-               goto err_config_cleanup;
-       }
-
-#if defined(LMA)
-       nulldisp_dev->pdp_gem_priv = pdp_gem_init(dev);
-       if (!nulldisp_dev->pdp_gem_priv) {
-               err = -ENOMEM;
-               goto err_config_cleanup;
-       }
-#endif
-       nulldisp_dev->workqueue =
-               create_singlethread_workqueue(DRIVER_NAME);
-       if (!nulldisp_dev->workqueue) {
-               DRM_ERROR("failed to create work queue\n");
-               goto err_gem_cleanup;
-       }
-
-       err = drm_vblank_init(nulldisp_dev->dev, 1);
-       if (err) {
-               DRM_ERROR("failed to complete vblank init (err=%d)\n", err);
-               goto err_workqueue_cleanup;
-       }
-
-       dev->irq_enabled = true;
-
-       nulldisp_dev->nlpvrdpy = nlpvrdpy_create(dev,
-                                                nulldisp_nl_disconnect_cb,
-                                                nulldisp_dev->nulldisp_crtc,
-                                                nulldisp_nl_flipped_cb,
-                                                nulldisp_dev->nulldisp_crtc,
-                                                nulldisp_nl_copied_cb,
-                                                nulldisp_dev->nulldisp_crtc);
-       if (!nulldisp_dev->nlpvrdpy) {
-               DRM_ERROR("Netlink initialisation failed (err=%d)\n", err);
-               goto err_vblank_cleanup;
-       }
-
-       return 0;
-
-err_vblank_cleanup:
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-       /* Called by drm_dev_fini in Linux 4.11.0 and later */
-       drm_vblank_cleanup(dev);
-#endif
-err_workqueue_cleanup:
-       destroy_workqueue(nulldisp_dev->workqueue);
-       dev->irq_enabled = false;
-err_gem_cleanup:
-#if defined(LMA)
-       pdp_gem_cleanup(nulldisp_dev->pdp_gem_priv);
-#endif
-err_config_cleanup:
-       drm_mode_config_cleanup(dev);
-       kfree(nulldisp_dev);
-       return err;
-}
-
-static int nulldisp_late_load(struct drm_device *dev)
-{
-       drm_mode_config_reset(dev);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-       {
-               struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-               int err;
-
-               err = drm_connector_register(nulldisp_dev->connector);
-               if (err) {
-                       DRM_ERROR(
-                           "[CONNECTOR:%d:%s] failed to register (err=%d)\n",
-                           nulldisp_dev->connector->base.id,
-                           nulldisp_dev->connector->name,
-                           err);
-                       return err;
-               }
-       }
-#endif
-       return 0;
-}
-
-static void nulldisp_early_unload(struct drm_device *dev)
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       drm_connector_unregister(nulldisp_dev->connector);
-#endif
-}
-
-static void nulldisp_late_unload(struct drm_device *dev)
-{
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       nlpvrdpy_send_disconnect(nulldisp_dev->nlpvrdpy);
-       nlpvrdpy_destroy(nulldisp_dev->nlpvrdpy);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-       /* Called by drm_dev_fini in Linux 4.11.0 and later */
-       drm_vblank_cleanup(dev);
-#endif
-       destroy_workqueue(nulldisp_dev->workqueue);
-
-       dev->irq_enabled = false;
-
-#if defined(LMA)
-       pdp_gem_cleanup(nulldisp_dev->pdp_gem_priv);
-#endif
-       drm_mode_config_cleanup(dev);
-
-       kfree(nulldisp_dev);
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0))
-static int nulldisp_load(struct drm_device *dev, unsigned long flags)
-{
-       int err;
-
-       err = nulldisp_early_load(dev);
-       if (err)
-               return err;
-
-       err = nulldisp_late_load(dev);
-       if (err) {
-               nulldisp_late_unload(dev);
-               return err;
-       }
-
-       return 0;
-}
-
-static int nulldisp_unload(struct drm_device *dev)
-{
-       nulldisp_early_unload(dev);
-       nulldisp_late_unload(dev);
-
-       return 0;
-}
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
-static void
-nulldisp_crtc_flip_event_cancel(struct drm_crtc *crtc, struct drm_file *file)
-{
-       struct nulldisp_crtc *nulldisp_crtc = to_nulldisp_crtc(crtc);
-       unsigned long flags;
-
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
-
-       if (nulldisp_crtc->flip_event &&
-           nulldisp_crtc->flip_event->base.file_priv == file) {
-               struct drm_pending_event *pending_event =
-                       &nulldisp_crtc->flip_event->base;
-
-               pending_event->destroy(pending_event);
-               nulldisp_crtc->flip_event = NULL;
-       }
-
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-}
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
-static void nulldisp_preclose(struct drm_device *dev, struct drm_file *file)
-{
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-               nulldisp_crtc_flip_event_cancel(crtc, file);
-}
-#endif
-
-static void nulldisp_lastclose(struct drm_device *dev)
-{
-#if defined(NULLDISP_USE_ATOMIC)
-       drm_atomic_helper_shutdown(dev);
-#else
-       struct drm_crtc *crtc;
-
-       drm_modeset_lock_all(dev);
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->primary->fb) {
-                       struct drm_mode_set mode_set = { .crtc = crtc };
-                       int err;
-
-                       err = drm_mode_set_config_internal(&mode_set);
-                       if (err)
-                               DRM_ERROR(
-                                   "failed to disable crtc %p (err=%d)\n",
-                                   crtc, err);
-               }
-       }
-       drm_modeset_unlock_all(dev);
-#endif
-}
-
-static const struct vm_operations_struct nulldisp_gem_vm_ops = {
-#if defined(LMA)
-       .fault  = pdp_gem_object_vm_fault,
-       .open   = drm_gem_vm_open,
-       .close  = drm_gem_vm_close,
-#else
-       .fault  = nulldisp_gem_object_vm_fault,
-       .open   = nulldisp_gem_vm_open,
-       .close  = nulldisp_gem_vm_close,
-#endif
-};
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
-const struct drm_gem_object_funcs nulldisp_gem_funcs = {
-#if defined(LMA)
-       .free = pdp_gem_object_free,
-       .export = pdp_gem_prime_export,
-#else
-       .export = drm_gem_prime_export,
-       .pin = nulldisp_gem_prime_pin,
-       .unpin = nulldisp_gem_prime_unpin,
-       .get_sg_table = nulldisp_gem_prime_get_sg_table,
-       .vmap = nulldisp_gem_prime_vmap,
-       .vunmap = nulldisp_gem_prime_vunmap,
-       .free = nulldisp_gem_object_free,
-#endif /* defined(LMA) */
-       .vm_ops = &nulldisp_gem_vm_ops,
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) */
-
-#if defined(LMA)
-static int pdp_gem_dumb_create(struct drm_file *file,
-                              struct drm_device *dev,
-                              struct drm_mode_create_dumb *args)
-{
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-
-       return pdp_gem_dumb_create_priv(file,
-                                       dev,
-                                       nulldisp_dev->pdp_gem_priv,
-                                       args);
-}
-
-static int nulldisp_gem_object_create_ioctl(struct drm_device *dev,
-                                           void *data,
-                                           struct drm_file *file)
-{
-       struct drm_nulldisp_gem_create *args = data;
-       struct nulldisp_display_device *nulldisp_dev = dev->dev_private;
-       struct drm_pdp_gem_create pdp_args;
-       int err;
-
-       if (args->flags) {
-               DRM_ERROR("invalid flags: %#08x\n", args->flags);
-               return -EINVAL;
-       }
-
-       if (args->handle) {
-               DRM_ERROR("invalid handle (this should always be 0)\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Remapping of nulldisp create args to pdp create args.
-        *
-        * Note: even though the nulldisp and pdp args are identical
-        * in this case, they may potentially change in future.
-        */
-       pdp_args.size = args->size;
-       pdp_args.flags = args->flags;
-       pdp_args.handle = args->handle;
-
-       err = pdp_gem_object_create_ioctl_priv(dev,
-                                              nulldisp_dev->pdp_gem_priv,
-                                              &pdp_args,
-                                              file);
-       if (!err)
-               args->handle = pdp_args.handle;
-
-       return err;
-}
-
-static int nulldisp_gem_object_mmap_ioctl(struct drm_device *dev,
-                                         void *data,
-                                         struct drm_file *file)
-{
-       struct drm_nulldisp_gem_mmap *args = data;
-       struct drm_pdp_gem_mmap pdp_args;
-       int err;
-
-       pdp_args.handle = args->handle;
-       pdp_args.pad = args->pad;
-       pdp_args.offset = args->offset;
-
-       err = pdp_gem_object_mmap_ioctl(dev, &pdp_args, file);
-
-       if (!err)
-               args->offset = pdp_args.offset;
-
-       return err;
-}
-
-static int nulldisp_gem_object_cpu_prep_ioctl(struct drm_device *dev,
-                                             void *data,
-                                             struct drm_file *file)
-{
-       struct drm_nulldisp_gem_cpu_prep *args =
-               (struct drm_nulldisp_gem_cpu_prep *)data;
-       struct drm_pdp_gem_cpu_prep pdp_args;
-
-       pdp_args.handle = args->handle;
-       pdp_args.flags = args->flags;
-
-       return pdp_gem_object_cpu_prep_ioctl(dev, &pdp_args, file);
-}
-
-static int nulldisp_gem_object_cpu_fini_ioctl(struct drm_device *dev,
-                                      void *data,
-                                      struct drm_file *file)
-{
-       struct drm_nulldisp_gem_cpu_fini *args =
-               (struct drm_nulldisp_gem_cpu_fini *)data;
-       struct drm_pdp_gem_cpu_fini pdp_args;
-
-       pdp_args.handle = args->handle;
-       pdp_args.pad = args->pad;
-
-       return pdp_gem_object_cpu_fini_ioctl(dev, &pdp_args, file);
-}
-
-static void pdp_gem_object_free(struct drm_gem_object *obj)
-{
-       struct nulldisp_display_device *nulldisp_dev = obj->dev->dev_private;
-
-       pdp_gem_object_free_priv(nulldisp_dev->pdp_gem_priv, obj);
-}
-#endif
-
-static const struct drm_ioctl_desc nulldisp_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(NULLDISP_GEM_CREATE,
-                         nulldisp_gem_object_create_ioctl,
-                         DRM_AUTH | DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(NULLDISP_GEM_MMAP,
-                         nulldisp_gem_object_mmap_ioctl,
-                         DRM_AUTH | DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(NULLDISP_GEM_CPU_PREP,
-                         nulldisp_gem_object_cpu_prep_ioctl,
-                         DRM_AUTH | DRM_UNLOCKED),
-       DRM_IOCTL_DEF_DRV(NULLDISP_GEM_CPU_FINI,
-                         nulldisp_gem_object_cpu_fini_ioctl,
-                         DRM_AUTH | DRM_UNLOCKED),
-};
-
-static int nulldisp_gem_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       int err;
-
-       err = netlink_gem_mmap(file, vma);
-#if !defined(LMA)
-       if (!err) {
-               struct drm_file *file_priv = file->private_data;
-               struct drm_device *dev = file_priv->minor->dev;
-               struct drm_gem_object *obj;
-
-               mutex_lock(&dev->struct_mutex);
-               obj = vma->vm_private_data;
-
-               if (obj->import_attach)
-                       err = dma_buf_mmap(obj->dma_buf, vma, 0);
-               else
-                       err = nulldisp_gem_object_get_pages(obj);
-
-               mutex_unlock(&dev->struct_mutex);
-       }
-#endif
-       return err;
-}
-
-static const struct file_operations nulldisp_driver_fops = {
-       .owner          = THIS_MODULE,
-       .open           = drm_open,
-       .release        = drm_release,
-       .unlocked_ioctl = drm_ioctl,
-       .mmap           = nulldisp_gem_mmap,
-       .poll           = drm_poll,
-       .read           = drm_read,
-       .llseek         = noop_llseek,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl   = drm_compat_ioctl,
-#endif
-};
-
-static struct drm_driver nulldisp_drm_driver = {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-       .load                           = NULL,
-       .unload                         = NULL,
-#else
-       .load                           = nulldisp_load,
-       .unload                         = nulldisp_unload,
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
-       .preclose                       = nulldisp_preclose,
-#endif
-       .lastclose                      = nulldisp_lastclose,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) && \
-       (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-       .set_busid                      = drm_platform_set_busid,
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
-       .get_vblank_counter             = drm_vblank_count,
-#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-       .get_vblank_counter             = drm_vblank_no_hw_counter,
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0))
-       .enable_vblank                  = nulldisp_enable_vblank,
-       .disable_vblank                 = nulldisp_disable_vblank,
-#endif
-
-       .prime_handle_to_fd             = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle             = drm_gem_prime_fd_to_handle,
-
-#if defined(LMA)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
-       .gem_free_object                = pdp_gem_object_free,
-       .gem_prime_export               = pdp_gem_prime_export,
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) */
-       .gem_prime_import               = pdp_gem_prime_import,
-       .gem_prime_import_sg_table      = pdp_gem_prime_import_sg_table,
-
-       .dumb_create                    = pdp_gem_dumb_create,
-       .dumb_map_offset                = pdp_gem_dumb_map_offset,
-#else
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
-       .gem_prime_pin                  = nulldisp_gem_prime_pin,
-       .gem_prime_unpin                = nulldisp_gem_prime_unpin,
-       .gem_prime_get_sg_table = nulldisp_gem_prime_get_sg_table,
-       .gem_prime_vmap                 = nulldisp_gem_prime_vmap,
-       .gem_prime_vunmap               = nulldisp_gem_prime_vunmap,
-       .gem_free_object                = nulldisp_gem_object_free,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-       .gem_prime_export               = nulldisp_gem_prime_export,
-#else
-       .gem_prime_export               = drm_gem_prime_export,
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) */
-       .gem_prime_import_sg_table      = nulldisp_gem_prime_import_sg_table,
-       .gem_prime_mmap                 = nulldisp_gem_prime_mmap,
-       .gem_prime_import               = drm_gem_prime_import,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-       .gem_prime_res_obj              = nulldisp_gem_prime_res_obj,
-#endif
-       .dumb_create                    = nulldisp_gem_dumb_create,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-       .dumb_map_offset                = nulldisp_gem_dumb_map_offset,
-#endif
-#endif /* defined(LMA) */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0))
-       .dumb_destroy                   = drm_gem_dumb_destroy,
-#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0))
-       .gem_vm_ops                     = &nulldisp_gem_vm_ops,
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 9, 0) */
-       .name                           = DRIVER_NAME,
-       .desc                           = DRIVER_DESC,
-       .date                           = DRIVER_DATE,
-       .major                          = PVRVERSION_MAJ,
-       .minor                          = PVRVERSION_MIN,
-       .patchlevel                     = PVRVERSION_BUILD,
-
-       .driver_features                = DRIVER_GEM |
-                                         DRIVER_MODESET |
-                                         NULLDISP_DRIVER_PRIME |
-                                         NULLDISP_DRIVER_ATOMIC,
-       .ioctls                         = nulldisp_ioctls,
-       .num_ioctls                     = ARRAY_SIZE(nulldisp_ioctls),
-       .fops                           = &nulldisp_driver_fops,
-};
-
-static int nulldisp_probe(struct platform_device *pdev)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-       struct drm_device *ddev;
-       int ret;
-
-       ddev = drm_dev_alloc(&nulldisp_drm_driver, &pdev->dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
-       if (IS_ERR(ddev))
-               return PTR_ERR(ddev);
-#else
-       if (!ddev)
-               return -ENOMEM;
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
-       /* Needed by drm_platform_set_busid */
-       ddev->platformdev = pdev;
-#endif
-       /*
-        * The load callback, called from drm_dev_register, is deprecated,
-        * because of potential race conditions.
-        */
-       BUG_ON(nulldisp_drm_driver.load != NULL);
-
-       ret = nulldisp_early_load(ddev);
-       if (ret)
-               goto err_drm_dev_put;
-
-       ret = drm_dev_register(ddev, 0);
-       if (ret)
-               goto err_drm_dev_late_unload;
-
-       ret = nulldisp_late_load(ddev);
-       if (ret)
-               goto err_drm_dev_unregister;
-
-       drm_mode_config_reset(ddev);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0))
-       DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
-               nulldisp_drm_driver.name,
-               nulldisp_drm_driver.major,
-               nulldisp_drm_driver.minor,
-               nulldisp_drm_driver.patchlevel,
-               nulldisp_drm_driver.date,
-               ddev->primary->index);
-#endif
-       return 0;
-
-err_drm_dev_unregister:
-       drm_dev_unregister(ddev);
-err_drm_dev_late_unload:
-       nulldisp_late_unload(ddev);
-err_drm_dev_put:
-       drm_dev_put(ddev);
-       return  ret;
-#else
-       return drm_platform_init(&nulldisp_drm_driver, pdev);
-#endif
-}
-
-static int nulldisp_remove(struct platform_device *pdev)
-{
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-       /*
-        * The unload callback, called from drm_dev_unregister, is
-        * deprecated.
-        */
-       BUG_ON(nulldisp_drm_driver.unload != NULL);
-
-       nulldisp_early_unload(ddev);
-
-       drm_dev_unregister(ddev);
-
-       nulldisp_late_unload(ddev);
-
-       drm_dev_put(ddev);
-#else
-       drm_put_dev(ddev);
-#endif
-       return 0;
-}
-
-static void nulldisp_shutdown(struct platform_device *pdev)
-{
-}
-
-static struct platform_device_id nulldisp_platform_device_id_table[] = {
-#if defined(LMA)
-       { .name = APOLLO_DEVICE_NAME_PDP, .driver_data = 0 },
-       { .name = ODN_DEVICE_NAME_PDP, .driver_data = 0 },
-#else
-       { .name = "nulldisp", .driver_data = 0 },
-#endif
-       { },
-};
-
-static struct platform_driver nulldisp_platform_driver = {
-       .probe          = nulldisp_probe,
-       .remove         = nulldisp_remove,
-       .shutdown       = nulldisp_shutdown,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = DRIVER_NAME,
-       },
-       .id_table       = nulldisp_platform_device_id_table,
-};
-
-
-#if !defined(LMA)
-static struct platform_device_info nulldisp_device_info = {
-       .name           = "nulldisp",
-       .id             = -1,
-#if defined(NO_HARDWARE)
-       /*
-        * Not all cores have 40 bit physical support, but this
-        * will work unless > 32 bit address is returned on those cores.
-        * In the future this will be fixed properly.
-        */
-       .dma_mask       = DMA_BIT_MASK(40),
-#else
-       .dma_mask       = DMA_BIT_MASK(32),
-#endif
-};
-
-static struct platform_device *nulldisp_dev;
-#endif
-
-static int __init nulldisp_init(void)
-{
-       int err;
-
-       err = nulldisp_validate_module_parameters();
-       if (err) {
-               DRM_ERROR("invalid module parameters (err=%d)\n", err);
-               return err;
-       }
-
-       err = nlpvrdpy_register();
-       if (err) {
-               DRM_ERROR("failed to register with netlink (err=%d)\n", err);
-               return err;
-       }
-
-#if !defined(LMA)
-       nulldisp_dev = platform_device_register_full(&nulldisp_device_info);
-       if (IS_ERR(nulldisp_dev)) {
-               err = PTR_ERR(nulldisp_dev);
-               nulldisp_dev = NULL;
-               goto err_unregister_family;
-       }
-#endif
-       err = platform_driver_register(&nulldisp_platform_driver);
-       if (err)
-               goto err_unregister_family;
-
-       return 0;
-
-err_unregister_family:
-               (void) nlpvrdpy_unregister();
-               return err;
-}
-
-static void __exit nulldisp_exit(void)
-{
-       int err;
-
-       err = nlpvrdpy_unregister();
-       BUG_ON(err);
-
-#if !defined(LMA)
-       if (nulldisp_dev)
-               platform_device_unregister(nulldisp_dev);
-#endif
-       platform_driver_unregister(&nulldisp_platform_driver);
-}
-
-module_init(nulldisp_init);
-module_exit(nulldisp_exit);
-
-MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.c b/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.c
deleted file mode 100644 (file)
index 9cf2fe2..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * @File
- * @Codingstyle LinuxKernel
- * @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.
- */
-
-#include <linux/atomic.h>
-#include <linux/mm_types.h>
-#include <linux/dma-buf.h>
-#include <linux/dma-mapping.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/mutex.h>
-#include <linux/capability.h>
-
-#include "pvr_dma_resv.h"
-#include "drm_nulldisp_gem.h"
-#include "nulldisp_drm.h"
-#include "kernel_compatibility.h"
-#include "riscv_vmap.h"
-
-struct nulldisp_gem_object {
-       struct drm_gem_object base;
-
-       atomic_t pg_refcnt;
-       struct page **pages;
-       dma_addr_t *addrs;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-       struct dma_resv _resv;
-#endif
-       struct dma_resv *resv;
-
-       bool cpu_prep;
-       struct sg_table *import_sgt;
-};
-
-#define to_nulldisp_obj(obj) \
-       container_of(obj, struct nulldisp_gem_object, base)
-
-int nulldisp_gem_object_get_pages(struct drm_gem_object *obj)
-{
-       struct drm_device *dev = obj->dev;
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-       struct page **pages;
-       int err;
-
-       if (WARN_ON(obj->import_attach))
-               return -EEXIST;
-
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
-       if (atomic_inc_return(&nulldisp_obj->pg_refcnt) == 1) {
-               unsigned int npages = obj->size >> PAGE_SHIFT;
-               dma_addr_t *addrs;
-               unsigned int i;
-
-               pages = drm_gem_get_pages(obj);
-               if (IS_ERR(pages)) {
-                       err = PTR_ERR(pages);
-                       goto dec_refcnt;
-               }
-
-               addrs = kmalloc_array(npages, sizeof(*addrs), GFP_KERNEL);
-               if (!addrs) {
-                       err = -ENOMEM;
-                       goto free_pages;
-               }
-
-               for (i = 0; i < npages; i++) {
-                       addrs[i] = dma_map_page(dev->dev, pages[i],
-                                               0, PAGE_SIZE,
-                                               DMA_BIDIRECTIONAL);
-               }
-
-               nulldisp_obj->pages = pages;
-               nulldisp_obj->addrs = addrs;
-       }
-
-       return 0;
-
-free_pages:
-       drm_gem_put_pages(obj, pages, false, false);
-dec_refcnt:
-       atomic_dec(&nulldisp_obj->pg_refcnt);
-       return err;
-}
-
-static void nulldisp_gem_object_put_pages(struct drm_gem_object *obj)
-{
-       struct drm_device *dev = obj->dev;
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-
-       WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
-       if (WARN_ON(atomic_read(&nulldisp_obj->pg_refcnt) == 0))
-               return;
-
-       if (atomic_dec_and_test(&nulldisp_obj->pg_refcnt)) {
-               unsigned int npages = obj->size >> PAGE_SHIFT;
-               unsigned int i;
-
-               for (i = 0; i < npages; i++) {
-                       dma_unmap_page(dev->dev, nulldisp_obj->addrs[i],
-                                      PAGE_SIZE, DMA_BIDIRECTIONAL);
-               }
-
-               kfree(nulldisp_obj->addrs);
-               nulldisp_obj->addrs = NULL;
-
-               drm_gem_put_pages(obj, nulldisp_obj->pages, true, true);
-               nulldisp_obj->pages = NULL;
-       }
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-vm_fault_t nulldisp_gem_object_vm_fault(struct vm_fault *vmf)
-#else
-int nulldisp_gem_object_vm_fault(struct vm_area_struct *vma,
-                                struct vm_fault *vmf)
-#endif
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-       struct vm_area_struct *vma = vmf->vma;
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-       unsigned long addr = vmf->address;
-#else
-       unsigned long addr = (unsigned long)vmf->virtual_address;
-#endif
-       struct drm_gem_object *obj = vma->vm_private_data;
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-       unsigned long pg_off;
-       struct page *page;
-
-       /*
-        * nulldisp_gem_object_get_pages should have been called in
-        * nulldisp_gem_mmap so there's no need to do it here.
-        */
-       if (WARN_ON(atomic_read(&nulldisp_obj->pg_refcnt) == 0))
-               return VM_FAULT_SIGBUS;
-
-       pg_off = (addr - vma->vm_start) >> PAGE_SHIFT;
-       page = nulldisp_obj->pages[pg_off];
-
-       get_page(page);
-       vmf->page = page;
-
-       return 0;
-}
-
-void nulldisp_gem_vm_open(struct vm_area_struct *vma)
-{
-       struct drm_gem_object *obj = vma->vm_private_data;
-
-       drm_gem_vm_open(vma);
-
-       if (!obj->import_attach) {
-               struct drm_device *dev = obj->dev;
-
-               mutex_lock(&dev->struct_mutex);
-               (void) nulldisp_gem_object_get_pages(obj);
-               mutex_unlock(&dev->struct_mutex);
-       }
-}
-
-void nulldisp_gem_vm_close(struct vm_area_struct *vma)
-{
-       struct drm_gem_object *obj = vma->vm_private_data;
-
-       if (!obj->import_attach) {
-               struct drm_device *dev = obj->dev;
-
-               mutex_lock(&dev->struct_mutex);
-               (void) nulldisp_gem_object_put_pages(obj);
-               mutex_unlock(&dev->struct_mutex);
-       }
-
-       drm_gem_vm_close(vma);
-}
-
-void nulldisp_gem_object_free(struct drm_gem_object *obj)
-{
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-
-       WARN_ON(atomic_read(&nulldisp_obj->pg_refcnt) != 0);
-
-       if (obj->import_attach) {
-               kfree(nulldisp_obj->pages);
-               kfree(nulldisp_obj->addrs);
-               drm_gem_free_mmap_offset(obj);
-               drm_prime_gem_destroy(obj, nulldisp_obj->import_sgt);
-       } else {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-               dma_resv_fini(&nulldisp_obj->_resv);
-#endif
-               drm_gem_object_release(obj);
-       }
-
-       kfree(nulldisp_obj);
-}
-
-int nulldisp_gem_prime_pin(struct drm_gem_object *obj)
-{
-       struct drm_device *dev = obj->dev;
-       int err;
-
-       mutex_lock(&dev->struct_mutex);
-       err = nulldisp_gem_object_get_pages(obj);
-       mutex_unlock(&dev->struct_mutex);
-
-       return err;
-}
-
-void nulldisp_gem_prime_unpin(struct drm_gem_object *obj)
-{
-       struct drm_device *dev = obj->dev;
-
-       mutex_lock(&dev->struct_mutex);
-       nulldisp_gem_object_put_pages(obj);
-       mutex_unlock(&dev->struct_mutex);
-}
-
-struct sg_table *
-nulldisp_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-       int nr_pages = obj->size >> PAGE_SHIFT;
-
-       /*
-        * nulldisp_gem_prime_pin should have been called in which case we don't
-        * need to call nulldisp_gem_object_get_pages.
-        */
-       if (WARN_ON(atomic_read(&nulldisp_obj->pg_refcnt) == 0))
-               return NULL;
-
-       return drm_prime_pages_to_sg(obj->dev, nulldisp_obj->pages, nr_pages);
-}
-
-struct drm_gem_object *
-nulldisp_gem_prime_import_sg_table(struct drm_device *dev,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-                                  struct dma_buf_attachment *attach,
-#else
-                                  size_t size,
-#endif
-                                  struct sg_table *sgt)
-{
-       struct nulldisp_gem_object *nulldisp_obj;
-       struct drm_gem_object *obj;
-       struct page **pages;
-       dma_addr_t *addrs;
-       unsigned int npages;
-
-       nulldisp_obj = kzalloc(sizeof(*nulldisp_obj), GFP_KERNEL);
-       if (!nulldisp_obj)
-               return NULL;
-
-       nulldisp_obj->resv = attach->dmabuf->resv;
-
-       obj = &nulldisp_obj->base;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
-       obj->resv = nulldisp_obj->resv;
-#endif
-
-       drm_gem_private_object_init(dev, obj, attach->dmabuf->size);
-
-       npages = obj->size >> PAGE_SHIFT;
-
-       pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL);
-       addrs = kmalloc_array(npages, sizeof(*addrs), GFP_KERNEL);
-       if (!pages || !addrs)
-               goto exit_free_arrays;
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
-       if (drm_prime_sg_to_page_addr_arrays(sgt, pages, addrs, npages))
-               goto exit_free_arrays;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
-       if (drm_prime_sg_to_page_array(sgt, pages, npages))
-               goto exit_free_arrays;
-       if (drm_prime_sg_to_dma_addr_array(sgt, addrs, npages))
-               goto exit_free_arrays;
-#endif
-
-       nulldisp_obj->import_sgt = sgt;
-       nulldisp_obj->pages = pages;
-       nulldisp_obj->addrs = addrs;
-
-       return obj;
-
-exit_free_arrays:
-       kfree(pages);
-       kfree(addrs);
-       drm_prime_gem_destroy(obj, sgt);
-       kfree(nulldisp_obj);
-       return NULL;
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-struct dma_buf *nulldisp_gem_prime_export(
-                                         struct drm_device *dev,
-                                         struct drm_gem_object *obj,
-                                         int flags)
-{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
-       /* Read/write access required */
-       flags |= O_RDWR;
-#endif
-       return drm_gem_prime_export(dev, obj, flags);
-}
-#endif
-
-static void *nulldisp_gem_vmap(struct drm_gem_object *obj)
-{
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-       int nr_pages = obj->size >> PAGE_SHIFT;
-
-       /*
-        * nulldisp_gem_prime_pin should have been called in which case we don't
-        * need to call nulldisp_gem_object_get_pages.
-        */
-       if (WARN_ON(atomic_read(&nulldisp_obj->pg_refcnt) == 0))
-               return NULL;
-       printk("nulldisp_gem_vmap called\n\n\n\n");
-       dump_stack();
-       return riscv_vmap(nulldisp_obj->pages, nr_pages, 0, PAGE_KERNEL);
-       //return vmap(nulldisp_obj->pages, nr_pages, 0, PAGE_KERNEL);
-}
-
-static void nulldisp_gem_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       vunmap(vaddr);
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-void *nulldisp_gem_prime_vmap(struct drm_gem_object *obj)
-{
-       return nulldisp_gem_vmap(obj);
-}
-
-void nulldisp_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
-{
-       nulldisp_gem_vunmap(obj, vaddr);
-}
-#else
-int nulldisp_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
-{
-       void *vaddr = nulldisp_gem_vmap(obj);
-       
-       dma_buf_map_set_vaddr(map, vaddr);
-       return (vaddr == NULL) ? -ENOMEM : 0;
-}
-
-void nulldisp_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map)
-{
-       nulldisp_gem_vunmap(obj, map->vaddr);
-       dma_buf_map_clear(map);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-
-int nulldisp_gem_prime_mmap(struct drm_gem_object *obj,
-                           struct vm_area_struct *vma)
-{
-       int err;
-
-       mutex_lock(&obj->dev->struct_mutex);
-       err = nulldisp_gem_object_get_pages(obj);
-       if (!err)
-               err = drm_gem_mmap_obj(obj, obj->size, vma);
-       mutex_unlock(&obj->dev->struct_mutex);
-
-       return err;
-}
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-struct dma_resv *
-nulldisp_gem_prime_res_obj(struct drm_gem_object *obj)
-{
-       struct nulldisp_gem_object *nulldisp_obj = to_nulldisp_obj(obj);
-
-       return nulldisp_obj->resv;
-}
-#endif
-
-int nulldisp_gem_object_mmap_ioctl(struct drm_device *dev, void *data,
-                                  struct drm_file *file)
-{
-       struct drm_nulldisp_gem_mmap *args =
-               (struct drm_nulldisp_gem_mmap *)data;
-
-       if (args->pad) {
-               DRM_ERROR("invalid pad (this should always be 0)\n");
-               return -EINVAL;
-       }
-
-       if (args->offset) {
-               DRM_ERROR("invalid offset (this should always be 0)\n");
-               return -EINVAL;
-       }
-
-       return nulldisp_gem_dumb_map_offset(file, dev, args->handle,
-                                           &args->offset);
-}
-
-int nulldisp_gem_object_cpu_prep_ioctl(struct drm_device *dev, void *data,
-                                      struct drm_file *file)
-{
-       struct drm_nulldisp_gem_cpu_prep *args =
-               (struct drm_nulldisp_gem_cpu_prep *)data;
-
-       struct drm_gem_object *obj;
-       struct nulldisp_gem_object *nulldisp_obj;
-       bool write = !!(args->flags & NULLDISP_GEM_CPU_PREP_WRITE);
-       bool wait = !(args->flags & NULLDISP_GEM_CPU_PREP_NOWAIT);
-       int err;
-
-       if (args->flags & ~(NULLDISP_GEM_CPU_PREP_READ |
-                           NULLDISP_GEM_CPU_PREP_WRITE |
-                           NULLDISP_GEM_CPU_PREP_NOWAIT)) {
-               DRM_ERROR("invalid flags: %#08x\n", args->flags);
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->struct_mutex);
-
-       obj = drm_gem_object_lookup(file, args->handle);
-       if (!obj) {
-               err = -ENOENT;
-               goto exit_unlock;
-       }
-
-       nulldisp_obj = to_nulldisp_obj(obj);
-
-       if (nulldisp_obj->cpu_prep) {
-               err = -EBUSY;
-               goto exit_unref;
-       }
-
-       if (wait) {
-               long lerr;
-
-               lerr = dma_resv_wait_timeout(nulldisp_obj->resv,
-                                                write,
-                                                true,
-                                                30 * HZ);
-
-               /* Remap return value (0 indicates busy state, > 0 success) */
-               if (lerr > 0)
-                       err = 0;
-               else if (!lerr)
-                       err = -EBUSY;
-               else
-                       err = lerr;
-       } else {
-               /*
-                * Remap return value (false indicates busy state,
-                * true success).
-                */
-               if (!dma_resv_test_signaled(nulldisp_obj->resv,
-                                               write))
-                       err = -EBUSY;
-               else
-                       err = 0;
-       }
-
-       if (!err)
-               nulldisp_obj->cpu_prep = true;
-exit_unref:
-       drm_gem_object_put(obj);
-exit_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return err;
-}
-
-int nulldisp_gem_object_cpu_fini_ioctl(struct drm_device *dev, void *data,
-                                      struct drm_file *file)
-{
-       struct drm_nulldisp_gem_cpu_fini *args =
-               (struct drm_nulldisp_gem_cpu_fini *)data;
-
-       struct drm_gem_object *obj;
-       struct nulldisp_gem_object *nulldisp_obj;
-       int err;
-
-       if (args->pad) {
-               DRM_ERROR("invalid pad (this should always be 0)\n");
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->struct_mutex);
-
-       obj = drm_gem_object_lookup(file, args->handle);
-       if (!obj) {
-               err = -ENOENT;
-               goto exit_unlock;
-       }
-
-       nulldisp_obj = to_nulldisp_obj(obj);
-
-       if (!nulldisp_obj->cpu_prep) {
-               err = -EINVAL;
-               goto exit_unref;
-       }
-
-       nulldisp_obj->cpu_prep = false;
-       err = 0;
-exit_unref:
-       drm_gem_object_put(obj);
-exit_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return err;
-}
-
-static int nulldisp_gem_object_create_priv(struct drm_file *file,
-                                          struct drm_device *dev,
-                                          u64 size,
-                                          u32 *handle)
-{
-       struct nulldisp_gem_object *nulldisp_obj;
-       struct drm_gem_object *obj;
-       struct address_space *mapping;
-       int err;
-
-       nulldisp_obj = kzalloc(sizeof(*nulldisp_obj), GFP_KERNEL);
-       if (!nulldisp_obj)
-               return -ENOMEM;
-
-       obj = &nulldisp_obj->base;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
-       obj->funcs = &nulldisp_gem_funcs;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) */
-
-       err = drm_gem_object_init(dev, obj, size);
-       if (err) {
-               kfree(nulldisp_obj);
-               return err;
-       }
-
-       mapping = file_inode(obj->filp)->i_mapping;
-       mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32 | __GFP_NORETRY);
-
-       err = drm_gem_handle_create(file, obj, handle);
-       if (err)
-               goto exit;
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-       dma_resv_init(&nulldisp_obj->_resv);
-       nulldisp_obj->resv = &nulldisp_obj->_resv;
-#else
-       nulldisp_obj->resv = nulldisp_obj->base.resv;
-#endif
-
-exit:
-       drm_gem_object_put(obj);
-       return err;
-}
-
-int nulldisp_gem_object_create_ioctl(struct drm_device *dev,
-                                    void *data,
-                                    struct drm_file *file)
-{
-       struct drm_nulldisp_gem_create *args = data;
-       u32 handle;
-       int err;
-       u64 aligned_size;
-
-       if (args->flags) {
-               DRM_ERROR("invalid flags: %#08x\n", args->flags);
-               return -EINVAL;
-       }
-
-       if (args->handle) {
-               DRM_ERROR("invalid handle (this should always be 0)\n");
-               return -EINVAL;
-       }
-
-       aligned_size = PAGE_ALIGN(args->size);
-
-       err = nulldisp_gem_object_create_priv(file, dev, aligned_size, &handle);
-       if (!err)
-               args->handle = handle;
-
-       return err;
-}
-
-int nulldisp_gem_dumb_create(struct drm_file *file,
-                            struct drm_device *dev,
-                            struct drm_mode_create_dumb *args)
-{
-       u32 handle;
-       u32 pitch;
-       size_t size;
-       int err;
-
-       pitch = args->width * (ALIGN(args->bpp, 8) >> 3);
-       size = PAGE_ALIGN(pitch * args->height);
-
-       err = nulldisp_gem_object_create_priv(file, dev, size, &handle);
-       if (!err) {
-               args->handle = handle;
-               args->pitch = pitch;
-               args->size = size;
-       }
-
-       return err;
-}
-
-int nulldisp_gem_dumb_map_offset(struct drm_file *file,
-                                struct drm_device *dev,
-                                uint32_t handle,
-                                uint64_t *offset)
-{
-       struct drm_gem_object *obj;
-       int err;
-
-       mutex_lock(&dev->struct_mutex);
-
-       obj = drm_gem_object_lookup(file, handle);
-       if (!obj) {
-               err = -ENOENT;
-               goto exit_unlock;
-       }
-
-       err = drm_gem_create_mmap_offset(obj);
-       if (err)
-               goto exit_obj_unref;
-
-       *offset = drm_vma_node_offset_addr(&obj->vma_node);
-
-exit_obj_unref:
-       drm_gem_object_put(obj);
-exit_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return err;
-}
-
-struct dma_resv *nulldisp_gem_get_resv(struct drm_gem_object *obj)
-{
-       return (to_nulldisp_obj(obj)->resv);
-}
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.h b/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_gem.h
deleted file mode 100644 (file)
index a22a1c6..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * @File
- * @Codingstyle LinuxKernel
- * @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(__DRM_NULLDISP_H__)
-#define __DRM_NULLDISP_H__
-
-#include <linux/version.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
-#include <drm/drm_device.h>
-#include <drm/drm_file.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-
-struct dma_buf_attachment;
-struct vm_area_struct;
-struct vm_fault;
-#else
-#include <drm/drmP.h>
-#endif
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
-extern const struct drm_gem_object_funcs nulldisp_gem_funcs;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-#include <drm/drm_gem.h>
-#endif
-
-int nulldisp_gem_object_get_pages(struct drm_gem_object *obj);
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
-typedef int vm_fault_t;
-#endif
-vm_fault_t nulldisp_gem_object_vm_fault(struct vm_fault *vmf);
-#else
-int nulldisp_gem_object_vm_fault(struct vm_area_struct *vma,
-                                struct vm_fault *vmf);
-#endif
-
-void nulldisp_gem_vm_open(struct vm_area_struct *vma);
-
-void nulldisp_gem_vm_close(struct vm_area_struct *vma);
-
-void nulldisp_gem_object_free(struct drm_gem_object *obj);
-
-int nulldisp_gem_prime_pin(struct drm_gem_object *obj);
-
-void nulldisp_gem_prime_unpin(struct drm_gem_object *obj);
-
-struct sg_table *nulldisp_gem_prime_get_sg_table(struct drm_gem_object *obj);
-
-struct drm_gem_object *
-nulldisp_gem_prime_import_sg_table(struct drm_device *dev,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-                                  struct dma_buf_attachment *attach,
-#else
-                                  size_t size,
-#endif
-                                  struct sg_table *sgt);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-struct dma_buf *nulldisp_gem_prime_export(struct drm_device *dev,
-                                         struct drm_gem_object *obj,
-                                         int flags);
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-void *nulldisp_gem_prime_vmap(struct drm_gem_object *obj);
-#else
-int nulldisp_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-void nulldisp_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
-#else
-void nulldisp_gem_prime_vunmap(struct drm_gem_object *obj, struct dma_buf_map *map);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-
-int nulldisp_gem_prime_mmap(struct drm_gem_object *obj,
-                           struct vm_area_struct *vma);
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0))
-struct dma_resv *
-nulldisp_gem_prime_res_obj(struct drm_gem_object *obj);
-#endif
-
-int nulldisp_gem_dumb_create(struct drm_file *file,
-                            struct drm_device *dev,
-                            struct drm_mode_create_dumb *args);
-
-int nulldisp_gem_dumb_map_offset(struct drm_file *file,
-                                struct drm_device *dev,
-                                uint32_t handle,
-                                uint64_t *offset);
-
-/* internal interfaces */
-struct dma_resv *nulldisp_gem_get_resv(struct drm_gem_object *obj);
-
-int nulldisp_gem_object_mmap_ioctl(struct drm_device *dev,
-                                  void *data,
-                                  struct drm_file *file);
-
-int nulldisp_gem_object_cpu_prep_ioctl(struct drm_device *dev,
-                                      void *data,
-                                      struct drm_file *file);
-
-int nulldisp_gem_object_cpu_fini_ioctl(struct drm_device *dev,
-                                      void *data,
-                                      struct drm_file *file);
-
-int nulldisp_gem_object_create_ioctl(struct drm_device *dev,
-                                    void *data,
-                                    struct drm_file *file);
-
-#endif /* !defined(__DRM_NULLDISP_H__) */
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_netlink.c b/drivers/gpu/drm/img/img-drm-nulldisp/drm_nulldisp_netlink.c
deleted file mode 100644 (file)
index a5e8a74..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * @File
- * @Codingstyle LinuxKernel
- * @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.
- */
-
-#include <linux/version.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
-#include <drm/drm_drv.h>
-#include <drm/drm_file.h>
-#include <drm/drm_framebuffer.h>
-#include <drm/drm_gem.h>
-#include <drm/drm_vma_manager.h>
-#else
-#include <drm/drmP.h>
-#endif
-
-#include <drm/drm_crtc.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/atomic.h>
-#include <linux/types.h>
-#include <net/netlink.h>
-#include <net/genetlink.h>
-#include <linux/bug.h>
-
-#include "drm_netlink_gem.h"
-#include "drm_nulldisp_drv.h"
-#include "drm_nulldisp_netlink.h"
-#include "kernel_compatibility.h"
-
-#include "netlink.h"
-
-struct nlpvrdpy {
-       atomic_t connected;
-       struct net *net;
-       u32 dst_portid;
-       struct drm_device *dev;
-       nlpvrdpy_disconnect_cb disconnect_cb;
-       void *disconnect_cb_data;
-       nlpvrdpy_flipped_cb flipped_cb;
-       void *flipped_cb_data;
-       nlpvrdpy_copied_cb copied_cb;
-       void *copied_cb_data;
-       struct mutex mutex;
-       struct list_head nl_list;
-       bool gem_names_required;
-};
-#define NLPVRDPY_MINOR(nlpvrdpy) \
-       ((unsigned int)((nlpvrdpy)->dev->primary->index))
-
-/* Command internal flags */
-#define        NLPVRDPY_CIF_NLPVRDPY_NOT_CONNECTED     0x00000001
-#define        NLPVRDPY_CIF_NLPVRDPY                   0x00000002
-
-static LIST_HEAD(nlpvrdpy_list);
-static DEFINE_MUTEX(nlpvrdpy_list_mutex);
-
-static inline void nlpvrdpy_lock(struct nlpvrdpy *nlpvrdpy)
-{
-       mutex_lock(&nlpvrdpy->mutex);
-}
-
-static inline void nlpvrdpy_unlock(struct nlpvrdpy *nlpvrdpy)
-{
-       mutex_unlock(&nlpvrdpy->mutex);
-}
-
-struct nlpvrdpy *nlpvrdpy_create(struct drm_device *dev,
-                                       nlpvrdpy_disconnect_cb disconnect_cb,
-                                       void *disconnect_cb_data,
-                                       nlpvrdpy_flipped_cb flipped_cb,
-                                       void *flipped_cb_data,
-                                       nlpvrdpy_copied_cb copied_cb,
-                                       void *copied_cb_data)
-{
-       struct nlpvrdpy *nlpvrdpy = kzalloc(sizeof(*nlpvrdpy), GFP_KERNEL);
-
-       if (!nlpvrdpy)
-               return NULL;
-
-       mutex_init(&nlpvrdpy->mutex);
-       INIT_LIST_HEAD(&nlpvrdpy->nl_list);
-
-       atomic_set(&nlpvrdpy->connected, 0);
-
-       nlpvrdpy->dev = dev;
-       nlpvrdpy->disconnect_cb = disconnect_cb;
-       nlpvrdpy->disconnect_cb_data = disconnect_cb_data;
-       nlpvrdpy->flipped_cb = flipped_cb;
-       nlpvrdpy->flipped_cb_data = flipped_cb_data;
-       nlpvrdpy->copied_cb = copied_cb;
-       nlpvrdpy->copied_cb_data = copied_cb_data;
-
-       mutex_lock(&nlpvrdpy_list_mutex);
-       list_add_tail(&nlpvrdpy->nl_list, &nlpvrdpy_list);
-       mutex_unlock(&nlpvrdpy_list_mutex);
-
-       return nlpvrdpy;
-}
-
-void nlpvrdpy_destroy(struct nlpvrdpy *nlpvrdpy)
-{
-       if (!nlpvrdpy)
-               return;
-
-       mutex_lock(&nlpvrdpy_list_mutex);
-       nlpvrdpy_lock(nlpvrdpy);
-       list_del(&nlpvrdpy->nl_list);
-       nlpvrdpy_unlock(nlpvrdpy);
-       mutex_unlock(&nlpvrdpy_list_mutex);
-
-       mutex_destroy(&nlpvrdpy->mutex);
-
-       kfree(nlpvrdpy);
-}
-
-static struct nlpvrdpy *nlpvrdpy_lookup(u32 minor)
-{
-       struct nlpvrdpy *nlpvrdpy = NULL;
-       struct nlpvrdpy *iter;
-
-       mutex_lock(&nlpvrdpy_list_mutex);
-       list_for_each_entry(iter, &nlpvrdpy_list, nl_list) {
-               if (NLPVRDPY_MINOR(iter) == minor) {
-                       nlpvrdpy = iter;
-                       nlpvrdpy_lock(nlpvrdpy);
-                       break;
-               }
-       }
-       mutex_unlock(&nlpvrdpy_list_mutex);
-
-       return nlpvrdpy;
-}
-
-static int nlpvrdpy_pre_cmd(const struct genl_ops *ops,
-                               struct sk_buff *skb,
-                               struct genl_info *info)
-{
-       struct nlattr **attrs = info->attrs;
-       struct nlpvrdpy *nlpvrdpy = NULL;
-       int ret;
-
-       if (ops->internal_flags & NLPVRDPY_CIF_NLPVRDPY_NOT_CONNECTED) {
-               if (!(ops->flags & GENL_ADMIN_PERM))
-                       return -EINVAL;
-       }
-
-       if (ops->internal_flags & (NLPVRDPY_CIF_NLPVRDPY_NOT_CONNECTED |
-                                       NLPVRDPY_CIF_NLPVRDPY)) {
-               u32 minor;
-
-               if (!attrs[NLPVRDPY_ATTR_MINOR])
-                       return -EINVAL;
-
-               minor = nla_get_u32(attrs[NLPVRDPY_ATTR_MINOR]);
-
-               nlpvrdpy = nlpvrdpy_lookup(minor);
-               if (!nlpvrdpy)
-                       return -ENODEV;
-
-               if (ops->internal_flags & NLPVRDPY_CIF_NLPVRDPY) {
-                       if (!atomic_read(&nlpvrdpy->connected)) {
-                               ret = -ENOTCONN;
-                               goto err_unlock;
-                       }
-                       if ((nlpvrdpy->net != genl_info_net(info)) ||
-                               (nlpvrdpy->dst_portid != info->snd_portid)) {
-                               ret = -EPROTO;
-                               goto err_unlock;
-                       }
-               }
-
-               info->user_ptr[0] = nlpvrdpy;
-       }
-
-       ret = 0;
-
-err_unlock:
-       nlpvrdpy_unlock(nlpvrdpy);
-       return ret;
-}
-
-static void nlpvrdpy_post_cmd(const struct genl_ops *ops,
-                               struct sk_buff *skb,
-                               struct genl_info *info)
-{
-}
-
-static struct genl_family nlpvrdpy_family = {
-       .name = "nlpvrdpy",
-       .version = 1,
-       .maxattr = NLPVRDPY_ATTR_MAX,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0))
-       .policy = nlpvrdpy_policy,
-#endif
-       .pre_doit = &nlpvrdpy_pre_cmd,
-       .post_doit = &nlpvrdpy_post_cmd
-};
-
-/* Must be called with the struct nlpvrdpy mutex held */
-static int nlpvrdpy_send_msg_locked(struct nlpvrdpy *nlpvrdpy,
-                                       struct sk_buff *msg)
-{
-       int err;
-
-       if (atomic_read(&nlpvrdpy->connected)) {
-               err = genlmsg_unicast(nlpvrdpy->net, msg, nlpvrdpy->dst_portid);
-               if (err == -ECONNREFUSED)
-                       atomic_set(&nlpvrdpy->connected, 0);
-       } else {
-               err = -ENOTCONN;
-               nlmsg_free(msg);
-       }
-
-       return err;
-}
-
-static int nlpvrdpy_send_msg(struct nlpvrdpy *nlpvrdpy, struct sk_buff *msg)
-{
-       int err;
-
-       nlpvrdpy_lock(nlpvrdpy);
-       err = nlpvrdpy_send_msg_locked(nlpvrdpy, msg);
-       nlpvrdpy_unlock(nlpvrdpy);
-
-       return err;
-}
-
-void nlpvrdpy_send_disconnect(struct nlpvrdpy *nlpvrdpy)
-{
-       struct sk_buff *msg;
-       void *hdr;
-       int err;
-
-       if (!atomic_read(&nlpvrdpy->connected))
-               return;
-
-       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-       if (!msg)
-               return;
-
-       hdr = genlmsg_put(msg, nlpvrdpy->dst_portid, 0,
-                               &nlpvrdpy_family, 0, NLPVRDPY_CMD_DISCONNECT);
-       if (!hdr)
-               goto err_msg_free;
-
-       err = nla_put_u32(msg, NLPVRDPY_ATTR_MINOR, NLPVRDPY_MINOR(nlpvrdpy));
-       if (err)
-               goto err_msg_free;
-
-       genlmsg_end(msg, hdr);
-
-       nlpvrdpy_lock(nlpvrdpy);
-
-       (void) nlpvrdpy_send_msg_locked(nlpvrdpy, msg);
-
-       atomic_set(&nlpvrdpy->connected, 0);
-       nlpvrdpy->net = NULL;
-       nlpvrdpy->dst_portid = 0;
-
-       nlpvrdpy_unlock(nlpvrdpy);
-
-       return;
-
-err_msg_free:
-       nlmsg_free(msg);
-}
-
-static int nlpvrdpy_get_offsets_and_sizes(struct drm_framebuffer *fb,
-                                         struct drm_gem_object **objs,
-                                         u64 *addr, u64 *size)
-{
-       int i;
-
-       for (i = 0; i < nulldisp_drm_fb_num_planes(fb); i++) {
-               int err;
-               struct drm_gem_object *obj = objs[i];
-
-               err = drm_gem_create_mmap_offset(obj);
-               if (err) {
-                       DRM_ERROR(
-                           "Failed to get mmap offset for buffer[%d] = %p\n",
-                           i, obj);
-                       return err;
-               }
-
-               addr[i] = drm_vma_node_offset_addr(&obj->vma_node);
-               size[i] = obj->size;
-       }
-
-       return 0;
-}
-
-static int nlpvrdpy_put_fb_attributes(struct sk_buff *msg,
-                                     struct drm_framebuffer *fb,
-                                     struct nlpvrdpy *nlpvrdpy,
-                                     struct drm_gem_object **objs)
-{
-       int i, err;
-       const int num_planes = nulldisp_drm_fb_num_planes(fb);
-       u64 plane_addr[NLPVRDPY_MAX_NUM_PLANES],
-           plane_size[NLPVRDPY_MAX_NUM_PLANES];
-
-       err = nlpvrdpy_get_offsets_and_sizes(fb, objs, &plane_addr[0], &plane_size[0]);
-       if (err) {
-               pr_err("%s: nlpvrdpy_get_offsets_and_sizes failed", __func__);
-               return err;
-       }
-
-       err = nla_put_u32(msg, NLPVRDPY_ATTR_MINOR, NLPVRDPY_MINOR(nlpvrdpy));
-       if (err) {
-               pr_err("%s: nla_put_u32 NLPVRDPY_ATTR_MINOR failed", __func__);
-               return err;
-       }
-
-       err = nla_put_u8(msg, NLPVRDPY_ATTR_NUM_PLANES, num_planes);
-       if (err) {
-               pr_err("%s: nla_put_u8 NLPVRDPY_ATTR_NUM_PLANES failed", __func__);
-               return err;
-       }
-
-       err = nla_put_u32(msg, NLPVRDPY_ATTR_WIDTH, fb->width);
-       if (err) {
-               pr_err("%s: nla_put_u32 NLPVRDPY_ATTR_WIDTH failed", __func__);
-               return err;
-       }
-
-       err = nla_put_u32(msg, NLPVRDPY_ATTR_HEIGHT, fb->height);
-       if (err) {
-               pr_err("%s: nla_put_u32 NLPVRDPY_ATTR_HEIGHT failed", __func__);
-               return err;
-       }
-
-       err = nla_put_u32(msg, NLPVRDPY_ATTR_PIXFMT, nulldisp_drm_fb_format(fb));
-       if (err) {
-               pr_err("%s: nla_put_u32 NLPVRDPY_ATTR_PIXFMT failed",
-                      __func__);
-               return err;
-       }
-
-       err = nla_put_u64_64bit(msg, NLPVRDPY_ATTR_FB_MODIFIER,
-                               nulldisp_drm_fb_modifier(fb), NLPVRDPY_ATTR_PAD);
-       if (err) {
-               pr_err("%s: nla_put_u64_64bit NLPVRDPY_ATTR_FB_MODIFIER "
-                      "NLPVRDPY_ATTR_PAD failed", __func__);
-               return err;
-       }
-
-       /* IMG_COLORSPACE_BT601_CONFORMANT_RANGE */
-       err = nla_put_u8(msg, NLPVRDPY_ATTR_YUV_CSC, 1);
-       if (err) {
-               pr_err("%s: nla_put_u8 NLPVRDPY_ATTR_YUV_CSC 1 failed", __func__);
-               return err;
-       }
-
-       /* 8-bit per sample */
-       err = nla_put_u8(msg, NLPVRDPY_ATTR_YUV_BPP, 8);
-       if (err) {
-               pr_err("%s: nla_put_u8 NLPVRDPY_ATTR_YUV_BPP 8 failed", __func__);
-               return err;
-       }
-
-       for (i = 0; i < num_planes; i++) {
-               err = nla_put_u64_64bit(msg, NLPVRDPY_ATTR_PLANE(i, ADDR),
-                                       plane_addr[i], NLPVRDPY_ATTR_PAD);
-               if (err) {
-                       pr_err("%s: nla_put_u64_64bit NLPVRDPY_ATTR_PLANE(%d, ADDR)"
-                              " NLPVRDPY_ATTR_PAD failed", __func__, i);
-                       return err;
-               }
-
-               err = nla_put_u64_64bit(msg, NLPVRDPY_ATTR_PLANE(i, SIZE),
-                                       plane_size[i], NLPVRDPY_ATTR_PAD);
-               if (err) {
-                       pr_err("%s: nla_put_u64_64bit NLPVRDPY_ATTR_PLANE(%d, SIZE)"
-                              " NLPVRDPY_ATTR_PAD failed", __func__, i);
-                       return err;
-               }
-
-               err = nla_put_u64_64bit(msg, NLPVRDPY_ATTR_PLANE(i, OFFSET),
-                                       fb->offsets[i], NLPVRDPY_ATTR_PAD);
-               if (err) {
-                       pr_err("%s: nla_put_u64_64bit NLPVRDPY_ATTR_PLANE(%d, OFFSET)"
-                              " NLPVRDPY_ATTR_PAD failed", __func__, i);
-                       return err;
-               }
-
-               err = nla_put_u64_64bit(msg, NLPVRDPY_ATTR_PLANE(i, PITCH),
-                                       fb->pitches[i], NLPVRDPY_ATTR_PAD);
-               if (err) {
-                       pr_err("%s: nla_put_u64_64bit NLPVRDPY_ATTR_PLANE(%d, PITCH)"
-                              " NLPVRDPY_ATTR_PAD failed", __func__, i);
-                       return err;
-               }
-
-               err = nla_put_u32(msg, NLPVRDPY_ATTR_PLANE(i, GEM_OBJ_NAME), (u32)objs[0]->name);
-               if (err) {
-                       pr_err("%s: nla_put_u32 NLPVRDPY_ATTR_PLANE(%d, GEM_OBJ_NAME)"
-                              " failed", __func__, i);
-                       return err;
-               }
-       }
-
-       WARN_ONCE(num_planes > NLPVRDPY_MAX_NUM_PLANES,
-                 "NLPVRDPY_MAX_NUM_PLANES = [%d], num_planes = [%d]\n",
-                 NLPVRDPY_MAX_NUM_PLANES, num_planes);
-
-       return 0;
-}
-
-static int nlpvrdpy_name_gem_obj(struct drm_device *dev,
-                                struct drm_gem_object *obj)
-{
-       int ret;
-
-       mutex_lock(&dev->object_name_lock);
-       if (!obj->name) {
-               ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_KERNEL);
-               if (ret < 0)
-                       goto exit_unlock;
-
-               obj->name = ret;
-       }
-
-       ret = 0;
-
-exit_unlock:
-       mutex_unlock(&dev->object_name_lock);
-       return ret;
-}
-
-static int nlpvrdpy_name_gem_objs(struct drm_framebuffer *fb,
-                                 struct drm_gem_object **objs)
-{
-       int i;
-       struct drm_device *dev = fb->dev;
-
-       for (i = 0; i < nulldisp_drm_fb_num_planes(fb); i++) {
-               int err = nlpvrdpy_name_gem_obj(dev, objs[i]);
-
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
-}
-
-int nlpvrdpy_send_flip(struct nlpvrdpy *nlpvrdpy,
-                      struct drm_framebuffer *fb,
-                      struct drm_gem_object **objs)
-{
-       struct sk_buff *msg;
-       void *hdr;
-       int err;
-
-       if (!atomic_read(&nlpvrdpy->connected))
-               return -ENOTCONN;
-
-       if (nlpvrdpy->gem_names_required) {
-               err = nlpvrdpy_name_gem_objs(fb, objs);
-               if (err)
-                       return err;
-       }
-
-       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-
-       hdr = genlmsg_put(msg, nlpvrdpy->dst_portid, 0,
-                               &nlpvrdpy_family, 0, NLPVRDPY_CMD_FLIP);
-       if (!hdr) {
-               err = -ENOMEM;
-               goto err_msg_free;
-       }
-
-       err = nlpvrdpy_put_fb_attributes(msg, fb, nlpvrdpy, objs);
-       if (err)
-               goto err_msg_free;
-
-       genlmsg_end(msg, hdr);
-
-       return nlpvrdpy_send_msg(nlpvrdpy, msg);
-
-err_msg_free:
-       nlmsg_free(msg);
-       return err;
-}
-
-int nlpvrdpy_send_copy(struct nlpvrdpy *nlpvrdpy,
-                      struct drm_framebuffer *fb,
-                      struct drm_gem_object **objs)
-{
-       struct sk_buff *msg;
-       void *hdr;
-       int err;
-
-       if (!atomic_read(&nlpvrdpy->connected))
-               return -ENOTCONN;
-
-       if (nlpvrdpy->gem_names_required) {
-               err = nlpvrdpy_name_gem_objs(fb, objs);
-               if (err)
-                       return err;
-       }
-
-       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-
-       hdr = genlmsg_put(msg, nlpvrdpy->dst_portid, 0,
-                               &nlpvrdpy_family, 0, NLPVRDPY_CMD_COPY);
-       if (!hdr) {
-               err = -ENOMEM;
-               goto err_msg_free;
-       }
-
-       err = nlpvrdpy_put_fb_attributes(msg, fb, nlpvrdpy, objs);
-       if (err)
-               goto err_msg_free;
-
-       genlmsg_end(msg, hdr);
-
-       return nlpvrdpy_send_msg(nlpvrdpy, msg);
-
-err_msg_free:
-       nlmsg_free(msg);
-       return err;
-}
-
-static int nlpvrdpy_cmd_connect(struct sk_buff *skb, struct genl_info *info)
-{
-       struct nlpvrdpy *nlpvrdpy = info->user_ptr[0];
-       struct sk_buff *msg;
-       void *hdr;
-       int err;
-
-       if (info->attrs[NLPVRDPY_ATTR_NAMING_REQUIRED])
-               nlpvrdpy->gem_names_required = true;
-
-       msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-
-       hdr = genlmsg_put_reply(msg, info, &nlpvrdpy_family,
-                                               0, NLPVRDPY_CMD_CONNECTED);
-       if (!hdr) {
-               err = -ENOMEM;
-               goto err_msg_free;
-       }
-
-       err = nla_put_string(msg, NLPVRDPY_ATTR_NAME,
-                               nlpvrdpy->dev->driver->name);
-       if (err)
-               goto err_msg_free;
-
-       genlmsg_end(msg, hdr);
-
-       err = genlmsg_reply(msg, info);
-
-       if (!err) {
-               nlpvrdpy_lock(nlpvrdpy);
-
-               nlpvrdpy->net = genl_info_net(info);
-               nlpvrdpy->dst_portid = info->snd_portid;
-               atomic_set(&nlpvrdpy->connected, 1);
-
-               nlpvrdpy_unlock(nlpvrdpy);
-       }
-
-       return err;
-
-err_msg_free:
-       nlmsg_free(msg);
-       return err;
-}
-
-static int nlpvrdpy_cmd_disconnect(struct sk_buff *skb, struct genl_info *info)
-{
-       struct nlpvrdpy *nlpvrdpy = info->user_ptr[0];
-
-       atomic_set(&nlpvrdpy->connected, 0);
-
-       if (nlpvrdpy->disconnect_cb)
-               nlpvrdpy->disconnect_cb(nlpvrdpy->disconnect_cb_data);
-
-       return 0;
-}
-
-static int nlpvrdpy_cmd_flipped(struct sk_buff *skb, struct genl_info *info)
-{
-       struct nlpvrdpy *nlpvrdpy = info->user_ptr[0];
-
-       return (nlpvrdpy->flipped_cb) ?
-                       nlpvrdpy->flipped_cb(nlpvrdpy->flipped_cb_data) :
-                       0;
-}
-
-static int nlpvrdpy_cmd_copied(struct sk_buff *skb, struct genl_info *info)
-{
-       struct nlpvrdpy *nlpvrdpy = info->user_ptr[0];
-
-       return (nlpvrdpy->copied_cb) ?
-                       nlpvrdpy->copied_cb(nlpvrdpy->copied_cb_data) :
-                       0;
-}
-
-static struct genl_ops nlpvrdpy_ops[] = {
-       {
-               .cmd = NLPVRDPY_CMD_CONNECT,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-               .policy = nlpvrdpy_policy,
-#endif
-               .doit = nlpvrdpy_cmd_connect,
-               .flags = GENL_ADMIN_PERM,
-               .internal_flags = NLPVRDPY_CIF_NLPVRDPY_NOT_CONNECTED
-       },
-       {
-               .cmd = NLPVRDPY_CMD_DISCONNECT,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-               .policy = nlpvrdpy_policy,
-#endif
-               .doit = nlpvrdpy_cmd_disconnect,
-               .flags = 0,
-               .internal_flags = NLPVRDPY_CIF_NLPVRDPY
-       },
-       {
-               .cmd = NLPVRDPY_CMD_FLIPPED,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-               .policy = nlpvrdpy_policy,
-#endif
-               .doit = nlpvrdpy_cmd_flipped,
-               .flags = 0,
-               .internal_flags = NLPVRDPY_CIF_NLPVRDPY
-       },
-       {
-               .cmd = NLPVRDPY_CMD_COPIED,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
-               .policy = nlpvrdpy_policy,
-#endif
-               .doit = nlpvrdpy_cmd_copied,
-               .flags = 0,
-               .internal_flags = NLPVRDPY_CIF_NLPVRDPY
-       }
-};
-
-int nlpvrdpy_register(void)
-{
-       nlpvrdpy_family.module = THIS_MODULE;
-       nlpvrdpy_family.ops = nlpvrdpy_ops;
-       nlpvrdpy_family.n_ops = ARRAY_SIZE(nlpvrdpy_ops);
-
-       return genl_register_family(&nlpvrdpy_family);
-}
-
-int nlpvrdpy_unregister(void)
-{
-       return genl_unregister_family(&nlpvrdpy_family);
-}
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc.h b/drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc.h
deleted file mode 100644 (file)
index 4856a8d..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Wrapper around drm_fourcc.h
-@Description    FourCCs and DRM framebuffer modifiers that are not in the
-                Kernel's and libdrm's drm_fourcc.h can be added here.
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@License        MIT
-
-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.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/ /**************************************************************************/
-
-#ifndef IMG_DRM_FOURCC_H
-#define IMG_DRM_FOURCC_H
-
-#if defined(__KERNEL__)
-#include <drm/drm_fourcc.h>
-#else
-/*
- * Include types.h to workaround versions of libdrm older than 2.4.68
- * not including the correct headers.
- */
-#include <linux/types.h>
-
-#include <drm_fourcc.h>
-#endif
-
-/*
- * Don't get too inspired by this example :)
- * ADF doesn't support DRM modifiers, so the memory layout had to be
- * included in the fourcc name, but the proper way to specify information
- * additional to pixel formats is to use DRM modifiers.
- *
- * See upstream drm_fourcc.h for the proper naming convention.
- */
-#ifndef DRM_FORMAT_BGRA8888_DIRECT_16x4
-#define DRM_FORMAT_BGRA8888_DIRECT_16x4 fourcc_code('I', 'M', 'G', '0')
-#endif
-
-#if !defined(__KERNEL__)
-/*
- * A definition for the same format was added in Linux kernel 5.2 in commit
- * 88ab9c76d191ad8645b483f31e2b394b0f3e280e. As such, this definition has been
- * deprecated and the DRM_FORMAT_ABGR16161616F kernel define should be used
- * instead of this one.
- */
-#define DRM_FORMAT_ABGR16_IMG_DEPRECATED fourcc_code('I', 'M', 'G', '1')
-#endif
-
-/*
- * Upstream does not have a packed 10 Bits Per Channel YVU format yet,
- * so let`s make one up.
- * Note: at the moment this format is not intended to be used with
- *       a framebuffer, so the kernels core DRM doesn`t need to know
- *       about this format. This means that the kernel doesn`t need
- *       to be patched.
- */
-#if !defined(__KERNEL__)
-#define DRM_FORMAT_YVU444_PACK10_IMG fourcc_code('I', 'M', 'G', '2')
-#define DRM_FORMAT_YUV422_2PLANE_PACK10_IMG fourcc_code('I', 'M', 'G', '3')
-#define DRM_FORMAT_YUV420_2PLANE_PACK10_IMG fourcc_code('I', 'M', 'G', '4')
-#endif
-
-/*
- * Value chosen in the middle of 255 pool to minimise the chance of hitting
- * the same value potentially defined by other vendors in the drm_fourcc.h
- */
-#define DRM_FORMAT_MOD_VENDOR_PVR 0x92
-
-#ifndef DRM_FORMAT_MOD_VENDOR_NONE
-#define DRM_FORMAT_MOD_VENDOR_NONE 0
-#endif
-
-#ifndef DRM_FORMAT_RESERVED
-#define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
-#endif
-
-#define img_fourcc_mod_combine(uiModHi, uiModLo) \
-       ((__u64) ((__u32) (uiModHi)) << 32 | (__u64) ((__u32) (uiModLo)))
-
-#define img_fourcc_mod_hi(ui64Mod) \
-       ((__u32) ((__u64) (ui64Mod) >> 32))
-
-#define img_fourcc_mod_lo(ui64Mod) \
-       ((__u32) ((__u64) (ui64Mod)) & 0xffffffff)
-
-#ifndef fourcc_mod_code
-#define fourcc_mod_code(vendor, val) \
-       ((((__u64)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | (val & 0x00ffffffffffffffULL))
-#endif
-
-#ifndef DRM_FORMAT_MOD_INVALID
-#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
-#endif
-
-#ifndef DRM_FORMAT_MOD_LINEAR
-#define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
-#endif
-
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7      fourcc_mod_code(PVR, 6)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7     fourcc_mod_code(PVR, 12)
-
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V10     fourcc_mod_code(PVR, 21)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V10    fourcc_mod_code(PVR, 22)
-#define DRM_FORMAT_MOD_PVR_FBCDC_32x2_V10    fourcc_mod_code(PVR, 23)
-
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V12     fourcc_mod_code(PVR, 15)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V12    fourcc_mod_code(PVR, 16)
-
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V13             fourcc_mod_code(PVR, 24)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY25_8x8_V13     fourcc_mod_code(PVR, 25)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY50_8x8_V13     fourcc_mod_code(PVR, 26)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY75_8x8_V13     fourcc_mod_code(PVR, 27)
-
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V13            fourcc_mod_code(PVR, 28)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY25_16x4_V13    fourcc_mod_code(PVR, 29)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY50_16x4_V13    fourcc_mod_code(PVR, 30)
-#define DRM_FORMAT_MOD_PVR_FBCDC_LOSSY75_16x4_V13    fourcc_mod_code(PVR, 31)
-
-#endif /* IMG_DRM_FOURCC_H */
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc_internal.h b/drivers/gpu/drm/img/img-drm-nulldisp/img_drm_fourcc_internal.h
deleted file mode 100644 (file)
index c347457..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          Wrapper around drm_fourcc.h
-@Description    FourCCs and the DRM framebuffer modifiers should be added here
-                unless they are used by kernel code or a known user outside of
-                the DDK. If FourCCs or DRM framebuffer modifiers are required
-                outside of the DDK, they shall be moved to the corresponding
-                public header.
-@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.
-*/ /**************************************************************************/
-
-#ifndef IMG_DRM_FOURCC_INTERNAL_H
-#define IMG_DRM_FOURCC_INTERNAL_H
-
-#include "img_drm_fourcc.h"
-
-/*
- * Modifier names are structured using the following convention,
- * with underscores (_) between items:
- * - prefix: DRM_FORMAT_MOD
- * - identifier for our driver: PVR
- * - category: FBCDC
- *   - compression tile dimension: 8x8, 16x4, 32x2
- *   - FBDC version: V0, V1, V2, V3, V7, V8, V10, V12
- */
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0      fourcc_mod_code(PVR, 1)
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0_FIX  fourcc_mod_code(PVR, 2) /* Fix for HW_BRN_37464 */
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V1      fourcc_mod_code(PVR, 3)
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V2      fourcc_mod_code(PVR, 4)
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V3      fourcc_mod_code(PVR, 5)
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7 - moved to the public header */
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V8      fourcc_mod_code(PVR, 18)
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V10 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V12 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_LOSSY25_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_LOSSY50_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_LOSSY75_V13 - moved to the public header */
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0     fourcc_mod_code(PVR, 7)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0_FIX fourcc_mod_code(PVR, 8) /* Fix for HW_BRN_37464 */
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V1     fourcc_mod_code(PVR, 9)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V2     fourcc_mod_code(PVR, 10)
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V3     fourcc_mod_code(PVR, 11)
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7 - moved to the public header */
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V8     fourcc_mod_code(PVR, 19)
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V10 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V12 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_LOSSY25_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_LOSSY50_V13 - moved to the public header */
-/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_LOSSY75_V13 - moved to the public header */
-#define DRM_FORMAT_MOD_PVR_FBCDC_32x2_V1     fourcc_mod_code(PVR, 13)
-#define DRM_FORMAT_MOD_PVR_FBCDC_32x2_V3     fourcc_mod_code(PVR, 14)
-#define DRM_FORMAT_MOD_PVR_FBCDC_32x2_V8     fourcc_mod_code(PVR, 20)
-/* DRM_FORMAT_MOD_PVR_FBCDC_32x2_V10 - moved to the public header */
-#define DRM_FORMAT_MOD_PVR_FBCDC_32x2_V12    fourcc_mod_code(PVR, 17)
-
-#endif /* IMG_DRM_FOURCC_INTERNAL_H */
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/netlink.h b/drivers/gpu/drm/img/img-drm-nulldisp/netlink.h
deleted file mode 100644 (file)
index 7b0a71f..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * @File
- * @Title       Nulldisp/Netlink interface definition
- * @Codingstyle LinuxKernel
- * @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.
- */
-
-
-#ifndef __NETLINK_H__
-#define __NETLINK_H__
-
-/* For multi-plane pixel formats */
-#define NLPVRDPY_MAX_NUM_PLANES 3
-
-enum nlpvrdpy_cmd {
-       __NLPVRDPY_CMD_INVALID,
-       NLPVRDPY_CMD_CONNECT,
-       NLPVRDPY_CMD_CONNECTED,
-       NLPVRDPY_CMD_DISCONNECT,
-       NLPVRDPY_CMD_FLIP,
-       NLPVRDPY_CMD_FLIPPED,
-       NLPVRDPY_CMD_COPY,
-       NLPVRDPY_CMD_COPIED,
-       __NLPVRDPY_CMD_MAX
-};
-#define NLPVRDPY_CMD_MAX (__NLPVRDPY_CMD_MAX - 1)
-
-enum nlpvrdpy_attr {
-       __NLPVRDPY_ATTR_INVALID,
-       NLPVRDPY_ATTR_NAME,
-       NLPVRDPY_ATTR_MINOR,
-       NLPVRDPY_ATTR_NUM_PLANES,
-       NLPVRDPY_ATTR_WIDTH,
-       NLPVRDPY_ATTR_HEIGHT,
-       NLPVRDPY_ATTR_PIXFMT,
-       NLPVRDPY_ATTR_YUV_CSC,
-       NLPVRDPY_ATTR_YUV_BPP,
-       NLPVRDPY_ATTR_PLANE0_ADDR,
-       NLPVRDPY_ATTR_PLANE0_SIZE,
-       NLPVRDPY_ATTR_PLANE0_OFFSET,
-       NLPVRDPY_ATTR_PLANE0_PITCH,
-       NLPVRDPY_ATTR_PLANE0_GEM_OBJ_NAME,
-       NLPVRDPY_ATTR_PLANE1_ADDR,
-       NLPVRDPY_ATTR_PLANE1_SIZE,
-       NLPVRDPY_ATTR_PLANE1_OFFSET,
-       NLPVRDPY_ATTR_PLANE1_PITCH,
-       NLPVRDPY_ATTR_PLANE1_GEM_OBJ_NAME,
-       NLPVRDPY_ATTR_PLANE2_ADDR,
-       NLPVRDPY_ATTR_PLANE2_SIZE,
-       NLPVRDPY_ATTR_PLANE2_OFFSET,
-       NLPVRDPY_ATTR_PLANE2_PITCH,
-       NLPVRDPY_ATTR_PLANE2_GEM_OBJ_NAME,
-       NLPVRDPY_ATTR_FB_MODIFIER,
-       NLPVRDPY_ATTR_NAMING_REQUIRED,
-       NLPVRDPY_ATTR_PAD,
-       __NLPVRDPY_ATTR_MAX
-};
-#define NLPVRDPY_ATTR_MAX  (__NLPVRDPY_ATTR_MAX - 1)
-
-static struct nla_policy __attribute__((unused))
-nlpvrdpy_policy[NLPVRDPY_ATTR_MAX + 1] = {
-       [NLPVRDPY_ATTR_NAME]                = { .type = NLA_STRING },
-       [NLPVRDPY_ATTR_MINOR]               = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_NUM_PLANES]          = { .type = NLA_U8  },
-       [NLPVRDPY_ATTR_WIDTH]               = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_HEIGHT]              = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_PIXFMT]              = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_YUV_CSC]             = { .type = NLA_U8  },
-       [NLPVRDPY_ATTR_YUV_BPP]             = { .type = NLA_U8  },
-       [NLPVRDPY_ATTR_PLANE0_ADDR]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE0_SIZE]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE0_OFFSET]       = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE0_PITCH]        = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE0_GEM_OBJ_NAME] = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_PLANE1_ADDR]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE1_SIZE]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE1_OFFSET]       = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE1_PITCH]        = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE1_GEM_OBJ_NAME] = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_PLANE2_ADDR]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE2_SIZE]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE2_OFFSET]       = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE2_PITCH]        = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_PLANE2_GEM_OBJ_NAME] = { .type = NLA_U32 },
-       [NLPVRDPY_ATTR_FB_MODIFIER]         = { .type = NLA_U64 },
-       [NLPVRDPY_ATTR_NAMING_REQUIRED]     = { .type = NLA_FLAG },
-};
-
-#define NLPVRDPY_ATTR_PLANE(index, type)                               \
-       ({                                                              \
-               enum nlpvrdpy_attr __retval;                            \
-                                                                       \
-               switch (index) {                                        \
-               case 0:                                                 \
-                       __retval = NLPVRDPY_ATTR_PLANE0_ ## type;       \
-                       break;                                          \
-               case 1:                                                 \
-                       __retval = NLPVRDPY_ATTR_PLANE1_ ## type;       \
-                       break;                                          \
-               case 2:                                                 \
-                       __retval = NLPVRDPY_ATTR_PLANE2_ ## type;       \
-                       break;                                          \
-               default:                                                \
-                       __retval = __NLPVRDPY_ATTR_INVALID;             \
-                       break;                                          \
-               };                                                      \
-                                                                       \
-               __retval;                                               \
-       })
-
-#endif /* __NETLINK_H__ */
diff --git a/drivers/gpu/drm/img/img-drm-nulldisp/nulldisp_drm.h b/drivers/gpu/drm/img/img-drm-nulldisp/nulldisp_drm.h
deleted file mode 100644 (file)
index 8403fb5..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * @File
- * @Title       Nulldisp DRM definitions shared between kernel and user space.
- * @Codingstyle LinuxKernel
- * @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(__NULLDISP_DRM_H__)
-#define __NULLDISP_DRM_H__
-
-#if defined(__KERNEL__)
-#include <drm/drm.h>
-#else
-#include <drm.h>
-#endif
-
-struct drm_nulldisp_gem_create {
-       __u64 size;   /* in */
-       __u32 flags;  /* in */
-       __u32 handle; /* out */
-};
-
-struct drm_nulldisp_gem_mmap {
-       __u32 handle; /* in */
-       __u32 pad;
-       __u64 offset; /* out */
-};
-
-#define NULLDISP_GEM_CPU_PREP_READ   (1 << 0)
-#define NULLDISP_GEM_CPU_PREP_WRITE  (1 << 1)
-#define NULLDISP_GEM_CPU_PREP_NOWAIT (1 << 2)
-
-struct drm_nulldisp_gem_cpu_prep {
-       __u32 handle; /* in */
-       __u32 flags;  /* in */
-};
-
-struct drm_nulldisp_gem_cpu_fini {
-       __u32 handle; /* in */
-       __u32 pad;
-};
-
-/*
- * DRM command numbers, relative to DRM_COMMAND_BASE.
- * These defines must be prefixed with "DRM_".
- */
-#define DRM_NULLDISP_GEM_CREATE   0x00
-#define DRM_NULLDISP_GEM_MMAP     0x01
-#define DRM_NULLDISP_GEM_CPU_PREP 0x02
-#define DRM_NULLDISP_GEM_CPU_FINI 0x03
-
-/* These defines must be prefixed with "DRM_IOCTL_". */
-#define DRM_IOCTL_NULLDISP_GEM_CREATE \
-       DRM_IOWR(DRM_COMMAND_BASE + DRM_NULLDISP_GEM_CREATE, \
-                struct drm_nulldisp_gem_create)
-
-#define DRM_IOCTL_NULLDISP_GEM_MMAP \
-       DRM_IOWR(DRM_COMMAND_BASE + DRM_NULLDISP_GEM_MMAP, \
-                struct drm_nulldisp_gem_mmap)
-
-#define DRM_IOCTL_NULLDISP_GEM_CPU_PREP \
-       DRM_IOW(DRM_COMMAND_BASE + DRM_NULLDISP_GEM_CPU_PREP, \
-               struct drm_nulldisp_gem_cpu_prep)
-
-#define DRM_IOCTL_NULLDISP_GEM_CPU_FINI \
-       DRM_IOW(DRM_COMMAND_BASE + DRM_NULLDISP_GEM_CPU_FINI, \
-               struct drm_nulldisp_gem_cpu_fini)
-
-#endif /* defined(__NULLDISP_DRM_H__) */
index c36e492..5c7f4ea 100755 (executable)
@@ -59,6 +59,7 @@ TOP:=$(TOP:/=)
 BRIDGE_SOURCE_ROOT=$(TOP)/generated/rogue
 TARGET_PRIMARY_ARCH=target_riscv64
 PVR_ARCH=rogue
+PVR_ARCH_DEFS=rogue
 PVR_SYSTEM := sf_7110
 PDUMP ?= 1
 BUILD ?= release
@@ -96,7 +97,9 @@ bridge_base := $(BRIDGE_SOURCE_ROOT)
 ccflags-y += -D__linux__ -include $(srctree)/$(src)/config_kernel.h \
  -include $(srctree)/drivers/gpu/drm/img/kernel_config_compatibility.h \
  -I$(OUT)/include \
- -I$(srctree)/drivers/gpu/drm/img
+ -I$(srctree)/drivers/gpu/drm/img \
+ -I$(srctree)/$(src)/hwdefs/rogue \
+ -I$(srctree)/$(src)/hwdefs/rogue/km
 
 include $(srctree)/$(src)/services/server/env/linux/Kbuild.mk
 include $(srctree)/$(src)/services/system/rogue/sf_7110/Kbuild.mk
index 1f04a71..58d5d23 100644 (file)
@@ -3,15 +3,16 @@
 #define RGX_FW_FILENAME "rgx.fw"
 #define RGX_SH_FILENAME "rgx.sh"
 #define PVR_BUILD_DIR "sf_7110"
-#define PVR_BUILD_TYPE "release"
+#define PVR_BUILD_TYPE "debug"
 #define PVRSRV_MODNAME "pvrsrvkm"
 #define PVRSYNC_MODNAME "pvr_sync"
 #define SUPPORT_RGX 1
-#define DISPLAY_CONTROLLER drm_nulldisp
-#define RELEASE
-#define SUPPORT_PHYSMEM_TEST
+#define DISPLAY_CONTROLLER drm_starfive
+#define PVRSRV_HWPERF_COUNTERS_PERBLK 12
+#define DEBUG
 #define RGX_BVNC_CORE_KM_HEADER "cores/rgxcore_km_36.50.54.182.h"
 #define RGX_BNC_CONFIG_KM_HEADER "configs/rgxconfig_km_36.V.54.182.h"
+#define PVRSRV_DEBUG_HANDLE_LOCK
 #define PDUMP
 #define PVRSRV_NEED_PVR_DPF
 #define PVRSRV_NEED_PVR_ASSERT
@@ -46,7 +47,7 @@
 #define PVRSRV_APPHINT_ENABLESIGNATURECHECKS APPHNT_BLDVAR_ENABLESIGNATURECHECKS
 #define PVRSRV_APPHINT_SIGNATURECHECKSBUFSIZE RGXFW_SIG_BUFFER_SIZE_MIN
 #define PVRSRV_APPHINT_ENABLEFULLSYNCTRACKING IMG_FALSE
-#define PVRSRV_APPHINT_ENABLEPAGEFAULTDEBUG APPHNT_BLDVAR_ENABLEPAGEFAULTDEBUG
+#define PVRSRV_APPHINT_ENABLEPAGEFAULTDEBUG IMG_TRUE
 #define PVRSRV_APPHINT_VALIDATEIRQ 0
 #define PVRSRV_APPHINT_DISABLECLOCKGATING 0
 #define PVRSRV_APPHINT_DISABLEDMOVERLAP 0
@@ -54,7 +55,6 @@
 #define PVRSRV_APPHINT_ENABLERANDOMCONTEXTSWITCH 0
 #define PVRSRV_APPHINT_ENABLESOFTRESETCNTEXTSWITCH 0
 #define PVRSRV_APPHINT_ENABLEFWCONTEXTSWITCH RGXFWIF_INICFG_OS_CTXSWITCH_DM_ALL
-#define PVRSRV_APPHINT_VDMCONTEXTSWITCHMODE RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX
 #define PVRSRV_APPHINT_ENABLERDPOWERISLAND RGX_RD_POWER_ISLAND_DEFAULT
 #define PVRSRV_APPHINT_FIRMWAREPERF FW_PERF_CONF_NONE
 #define PVRSRV_APPHINT_FWCONTEXTSWITCHPROFILE RGXFWIF_CTXSWITCH_PROFILE_MEDIUM_EN
@@ -62,6 +62,8 @@
 #define PVRSRV_APPHINT_HWPERFFWBUFSIZEINKB 2048
 #define PVRSRV_APPHINT_HWPERFHOSTBUFSIZEINKB 2048
 #define PVRSRV_APPHINT_HWPERFHOSTTHREADTIMEOUTINMS 50
+#define PVRSRV_APPHINT_TFBCCOMPRESSIONCONTROLGROUP 0
+#define PVRSRV_APPHINT_TFBCCOMPRESSIONCONTROLSCHEME 0
 #define PVRSRV_APPHINT_JONESDISABLEMASK 0
 #define PVRSRV_APPHINT_NEWFILTERINGMODE 1
 #define PVRSRV_APPHINT_TRUNCATEMODE 0
 #define PVRSRV_APPHINT_PHYSMEMTESTPASSES APPHNT_PHYSMEMTEST_ENABLE
 #define PVRSRV_APPHINT_TESTSLRINTERVAL 0
 #define PVRSRV_APPHINT_RISCVDMITEST 0
+#define PVRSRV_APPHINT_VALIDATESOCUSCTIMERS 0
 #define SOC_TIMER_FREQ 20
 #define PDVFS_COM_HOST 1
 #define PDVFS_COM_AP 2
 #define SUPPORT_USC_BREAKPOINT
 #define PVRSRV_ENABLE_GPU_MEMORY_INFO
 #define SUPPORT_TBI_INTERFACE
+#define SUPPORT_AGP
 #define RGXFW_SAFETY_WATCHDOG_PERIOD_IN_US 1000000
 #define PVR_ANNOTATION_MAX_LEN 96
+#define PVRSRV_DEVICE_INIT_MODE PVRSRV_LINUX_DEV_INIT_ON_CONNECT
+#define DEBUG_BRIDGE_KM
 #define SUPPORT_DI_BRG_IMPL
 #define PVR_LINUX_PHYSMEM_MAX_POOL_PAGES 10240
 #define PVR_LINUX_PHYSMEM_MAX_EXCESS_POOL_PAGES 20480
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_3D 16
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_KICKSYNC 13
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_TDM 14
+#define PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_RDM 13
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_TQ3D 17
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_TQ2D 17
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_CDM 15
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_3D 17
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_KICKSYNC 13
 #define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_TDM 17
+#define PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_RDM 15
 #define SUPPORT_BUFFER_SYNC 1
index e7a9859..87a01b5 100644 (file)
@@ -1,3 +1,4 @@
+override PVRSRV_DIR := services
 override HOST_PRIMARY_ARCH := host_x86_64
 override HOST_32BIT_ARCH := host_i386
 override HOST_FORCE_32BIT := -m32
@@ -10,23 +11,24 @@ override PVR_ARCH := rogue
 override METAG_VERSION_NEEDED := 2.8.1.0.3
 override MIPS_VERSION_NEEDED := 2014.07-1
 override RISCV_VERSION_NEEDED := 1.0.1
-override PVRSRV_MODULE_BASEDIR := /lib/modules/5.15.0-g76f0b2179c6d-dirty/extra/
-override KERNEL_COMPONENTS := srvkm
-override KERNEL_CROSS_COMPILE := riscv64-unknown-linux-gnu-
-override WINDOW_SYSTEM := lws-generic
-override SUPPORT_VK_PLATFORMS := "null wayland x11"
+override KERNELDIR := /home/lisl/freelight-u-sdk/soft_3rdpart/IMG_GPU/linux/../../../work/linux
+override KERNEL_ID := 5.15.0-00006-g35a89f4886a9-dirty
+override PVRSRV_MODULE_BASEDIR := /lib/modules/5.15.0-00006-g35a89f4886a9-dirty/extra/
+override KERNEL_COMPONENTS := srvkm drm_starfive
+override KERNEL_CROSS_COMPILE := riscv64-linux-
+override WINDOW_SYSTEM := nulldrmws
 override PVRSRV_MODNAME := pvrsrvkm
-override PVRSYNC_MODNAME := pvr_sync
 override PVR_BUILD_DIR := sf_7110
-override PVR_BUILD_TYPE := release
+override PVR_BUILD_TYPE := debug
 override SUPPORT_RGX := 1
 override DISPLAY_CONTROLLER := drm_starfive
 override PVR_SYSTEM := sf_7110
 override PVR_LOADER :=
-override BUILD := release
+override BUILD := debug
 override SORT_BRIDGE_STRUCTS := 1
 override PVR_SERVICES_DEBUG := 1
-override SUPPORT_PHYSMEM_TEST := 1
+override RGX_BNC := 36.V.54.182
+override SUPPORT_MIPS_64K_PAGE_SIZE :=
 override RGX_NUM_OS_SUPPORTED := 1
 override VMM_TYPE := stub
 override SUPPORT_POWMON_COMPONENT := 1
@@ -48,3 +50,4 @@ override SUPPORT_DI_BRG_IMPL := 1
 override SUPPORT_NATIVE_FENCE_SYNC := 1
 override SUPPORT_DMA_FENCE := 1
 override SUPPORT_BUFFER_SYNC := 1
+override DEFINE_X86_FEATURE_LA57 := 1
index 5952ae7..1dec13f 100644 (file)
@@ -61,9 +61,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpQueue(IMG_HANDLE hBridge,
                                             IMG_DEVMEM_OFFSET_T * puiOffset,
                                             IMG_DEVMEM_SIZE_T * puiSize,
                                             PVRSRV_CACHE_OP * piuCacheOp,
-                                            IMG_UINT32 ui32OpTimeline,
-                                            IMG_UINT32 ui32CurrentFenceSeqNum,
-                                            IMG_UINT32 * pui32NextFenceSeqNum);
+                                            IMG_UINT32 ui32OpTimeline);
 
 IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpExec(IMG_HANDLE hBridge,
                                            IMG_HANDLE hPMR,
@@ -76,8 +74,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpLog(IMG_HANDLE hBridge,
                                           IMG_UINT64 ui64Address,
                                           IMG_DEVMEM_OFFSET_T uiOffset,
                                           IMG_DEVMEM_SIZE_T uiSize,
-                                          IMG_INT64 i64QueuedTimeUs,
-                                          IMG_INT64 i64ExecuteTimeUs,
-                                          IMG_INT32 i32NumRBF, PVRSRV_CACHE_OP iuCacheOp);
+                                          IMG_INT64 i64StartTime,
+                                          IMG_INT64 i64EndTime, PVRSRV_CACHE_OP iuCacheOp);
 
 #endif /* CLIENT_CACHE_BRIDGE_H */
index 9f7634c..9691bae 100644 (file)
@@ -58,9 +58,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpQueue(IMG_HANDLE hBridge,
                                             IMG_DEVMEM_OFFSET_T * puiOffset,
                                             IMG_DEVMEM_SIZE_T * puiSize,
                                             PVRSRV_CACHE_OP * piuCacheOp,
-                                            IMG_UINT32 ui32OpTimeline,
-                                            IMG_UINT32 ui32CurrentFenceSeqNum,
-                                            IMG_UINT32 * pui32NextFenceSeqNum)
+                                            IMG_UINT32 ui32OpTimeline)
 {
        PVRSRV_ERROR eError;
        PMR **psPMRInt;
@@ -70,11 +68,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpQueue(IMG_HANDLE hBridge,
        eError =
            CacheOpQueue(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
                         ui32NumCacheOps,
-                        psPMRInt,
-                        pui64Address,
-                        puiOffset,
-                        puiSize,
-                        piuCacheOp, ui32OpTimeline, ui32CurrentFenceSeqNum, pui32NextFenceSeqNum);
+                        psPMRInt, pui64Address, puiOffset, puiSize, piuCacheOp, ui32OpTimeline);
 
        return eError;
 }
@@ -101,9 +95,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpLog(IMG_HANDLE hBridge,
                                           IMG_UINT64 ui64Address,
                                           IMG_DEVMEM_OFFSET_T uiOffset,
                                           IMG_DEVMEM_SIZE_T uiSize,
-                                          IMG_INT64 i64QueuedTimeUs,
-                                          IMG_INT64 i64ExecuteTimeUs,
-                                          IMG_INT32 i32NumRBF, PVRSRV_CACHE_OP iuCacheOp)
+                                          IMG_INT64 i64StartTime,
+                                          IMG_INT64 i64EndTime, PVRSRV_CACHE_OP iuCacheOp)
 {
        PVRSRV_ERROR eError;
        PMR *psPMRInt;
@@ -113,8 +106,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgeCacheOpLog(IMG_HANDLE hBridge,
 
        eError =
            CacheOpLog(psPMRInt,
-                      ui64Address,
-                      uiOffset, uiSize, i64QueuedTimeUs, i64ExecuteTimeUs, i32NumRBF, iuCacheOp);
+                      ui64Address, uiOffset, uiSize, i64StartTime, i64EndTime, iuCacheOp);
 
        return eError;
 }
index e8532f6..cc84875 100644 (file)
@@ -71,7 +71,6 @@ typedef struct PVRSRV_BRIDGE_IN_CACHEOPQUEUE_TAG
        IMG_DEVMEM_OFFSET_T *puiOffset;
        IMG_DEVMEM_SIZE_T *puiSize;
        IMG_HANDLE *phPMR;
-       IMG_UINT32 ui32CurrentFenceSeqNum;
        IMG_UINT32 ui32NumCacheOps;
        IMG_UINT32 ui32OpTimeline;
 } __packed PVRSRV_BRIDGE_IN_CACHEOPQUEUE;
@@ -80,7 +79,6 @@ typedef struct PVRSRV_BRIDGE_IN_CACHEOPQUEUE_TAG
 typedef struct PVRSRV_BRIDGE_OUT_CACHEOPQUEUE_TAG
 {
        PVRSRV_ERROR eError;
-       IMG_UINT32 ui32NextFenceSeqNum;
 } __packed PVRSRV_BRIDGE_OUT_CACHEOPQUEUE;
 
 /*******************************************
@@ -110,13 +108,12 @@ typedef struct PVRSRV_BRIDGE_OUT_CACHEOPEXEC_TAG
 /* Bridge in structure for CacheOpLog */
 typedef struct PVRSRV_BRIDGE_IN_CACHEOPLOG_TAG
 {
-       IMG_INT64 i64ExecuteTimeUs;
-       IMG_INT64 i64QueuedTimeUs;
+       IMG_INT64 i64EndTime;
+       IMG_INT64 i64StartTime;
        IMG_UINT64 ui64Address;
        IMG_DEVMEM_OFFSET_T uiOffset;
        IMG_DEVMEM_SIZE_T uiSize;
        IMG_HANDLE hPMR;
-       IMG_INT32 i32NumRBF;
        PVRSRV_CACHE_OP iuCacheOp;
 } __packed PVRSRV_BRIDGE_IN_CACHEOPLOG;
 
index bdc61a3..18509ba 100644 (file)
@@ -65,6 +65,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
+static_assert(CACHE_BATCH_MAX <= IMG_UINT32_MAX,
+             "CACHE_BATCH_MAX must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
                         IMG_UINT8 * psCacheOpQueueIN_UI8,
@@ -88,13 +91,14 @@ PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *)) +
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE)) +
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_UINT64)) +
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T)) +
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T)) +
-           (psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *)) +
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_UINT64)) +
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_OFFSET_T)) +
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_DEVMEM_SIZE_T)) +
+           ((IMG_UINT64) psCacheOpQueueIN->ui32NumCacheOps * sizeof(PVRSRV_CACHE_OP)) + 0;
 
        if (unlikely(psCacheOpQueueIN->ui32NumCacheOps > CACHE_BATCH_MAX))
        {
@@ -102,6 +106,14 @@ PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
                goto CacheOpQueue_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psCacheOpQueueOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto CacheOpQueue_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -122,7 +134,7 @@ PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -135,6 +147,7 @@ PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
        if (psCacheOpQueueIN->ui32NumCacheOps != 0)
        {
                psPMRInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psPMRInt, 0, psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *));
                ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(PMR *);
                hPMRInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psCacheOpQueueIN->ui32NumCacheOps * sizeof(IMG_HANDLE);
@@ -256,12 +269,7 @@ PVRSRVBridgeCacheOpQueue(IMG_UINT32 ui32DispatchTableEntry,
                         psCacheOpQueueIN->ui32NumCacheOps,
                         psPMRInt,
                         ui64AddressInt,
-                        uiOffsetInt,
-                        uiSizeInt,
-                        iuCacheOpInt,
-                        psCacheOpQueueIN->ui32OpTimeline,
-                        psCacheOpQueueIN->ui32CurrentFenceSeqNum,
-                        &psCacheOpQueueOUT->ui32NextFenceSeqNum);
+                        uiOffsetInt, uiSizeInt, iuCacheOpInt, psCacheOpQueueIN->ui32OpTimeline);
 
 CacheOpQueue_exit:
 
@@ -276,7 +284,7 @@ CacheOpQueue_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hPMRInt2[i])
+                       if (psPMRInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hPMRInt2[i],
@@ -288,7 +296,10 @@ CacheOpQueue_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psCacheOpQueueOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -386,9 +397,8 @@ PVRSRVBridgeCacheOpLog(IMG_UINT32 ui32DispatchTableEntry,
                       psCacheOpLogIN->ui64Address,
                       psCacheOpLogIN->uiOffset,
                       psCacheOpLogIN->uiSize,
-                      psCacheOpLogIN->i64QueuedTimeUs,
-                      psCacheOpLogIN->i64ExecuteTimeUs,
-                      psCacheOpLogIN->i32NumRBF, psCacheOpLogIN->iuCacheOp);
+                      psCacheOpLogIN->i64StartTime,
+                      psCacheOpLogIN->i64EndTime, psCacheOpLogIN->iuCacheOp);
 
 CacheOpLog_exit:
 
@@ -412,7 +422,7 @@ CacheOpLog_exit:
  */
 
 PVRSRV_ERROR InitCACHEBridge(void);
-PVRSRV_ERROR DeinitCACHEBridge(void);
+void DeinitCACHEBridge(void);
 
 /*
  * Register all CACHE functions with services
@@ -435,7 +445,7 @@ PVRSRV_ERROR InitCACHEBridge(void)
 /*
  * Unregister all cache functions with services
  */
-PVRSRV_ERROR DeinitCACHEBridge(void)
+void DeinitCACHEBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPQUEUE);
@@ -444,5 +454,4 @@ PVRSRV_ERROR DeinitCACHEBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_CACHE, PVRSRV_BRIDGE_CACHE_CACHEOPLOG);
 
-       return PVRSRV_OK;
 }
index e662067..b95f858 100644 (file)
@@ -199,10 +199,11 @@ PVRSRVBridgeDevmemIntUnexportCtx(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDevmemIntUnexportCtxOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDevmemIntUnexportCtxIN->hContextExport,
-                                           PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDevmemIntUnexportCtxIN->hContextExport,
+                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX_EXPORT);
        if (unlikely((psDevmemIntUnexportCtxOUT->eError != PVRSRV_OK) &&
+                    (psDevmemIntUnexportCtxOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psDevmemIntUnexportCtxOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -325,7 +326,7 @@ DevmemIntAcquireRemoteCtx_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(psConnection->psHandleBase);
 
-                       eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+                       eError = PVRSRVDestroyHandleUnlocked(psConnection->psHandleBase,
                                                             (IMG_HANDLE)
                                                             psDevmemIntAcquireRemoteCtxOUT->
                                                             hContext,
@@ -363,7 +364,7 @@ DevmemIntAcquireRemoteCtx_exit:
 
 #if !defined(EXCLUDE_CMM_BRIDGE)
 PVRSRV_ERROR InitCMMBridge(void);
-PVRSRV_ERROR DeinitCMMBridge(void);
+void DeinitCMMBridge(void);
 
 /*
  * Register all CMM functions with services
@@ -386,7 +387,7 @@ PVRSRV_ERROR InitCMMBridge(void)
 /*
  * Unregister all cmm functions with services
  */
-PVRSRV_ERROR DeinitCMMBridge(void)
+void DeinitCMMBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_CMM, PVRSRV_BRIDGE_CMM_DEVMEMINTEXPORTCTX);
@@ -395,7 +396,6 @@ PVRSRV_ERROR DeinitCMMBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_CMM, PVRSRV_BRIDGE_CMM_DEVMEMINTACQUIREREMOTECTX);
 
-       return PVRSRV_OK;
 }
 #else /* EXCLUDE_CMM_BRIDGE */
 /* This bridge is conditional on EXCLUDE_CMM_BRIDGE - when defined,
@@ -404,7 +404,6 @@ PVRSRV_ERROR DeinitCMMBridge(void)
 #define InitCMMBridge() \
        PVRSRV_OK
 
-#define DeinitCMMBridge() \
-       PVRSRV_OK
+#define DeinitCMMBridge()
 
 #endif /* EXCLUDE_CMM_BRIDGE */
index 409856b..acbb464 100644 (file)
@@ -118,10 +118,10 @@ IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryMapVRange(IMG_HANDLE hBridge,
                                                          IMG_UINT32 * pui32AllocationIndexOut)
 {
        PVRSRV_ERROR eError;
-       PVR_UNREFERENCED_PARAMETER(hBridge);
 
        eError =
-           DevicememHistoryMapVRangeKM(sBaseDevVAddr,
+           DevicememHistoryMapVRangeKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                       sBaseDevVAddr,
                                        ui32ui32StartPage,
                                        ui32NumPages,
                                        uiAllocSize,
@@ -143,10 +143,10 @@ IMG_INTERNAL PVRSRV_ERROR BridgeDevicememHistoryUnmapVRange(IMG_HANDLE hBridge,
                                                            IMG_UINT32 * pui32AllocationIndexOut)
 {
        PVRSRV_ERROR eError;
-       PVR_UNREFERENCED_PARAMETER(hBridge);
 
        eError =
-           DevicememHistoryUnmapVRangeKM(sBaseDevVAddr,
+           DevicememHistoryUnmapVRangeKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                         sBaseDevVAddr,
                                          ui32ui32StartPage,
                                          ui32NumPages,
                                          uiAllocSize,
index c1ff6a1..db440d0 100644 (file)
@@ -67,6 +67,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevicememHistoryMap(IMG_UINT32 ui32DispatchTableEntry,
                                IMG_UINT8 * psDevicememHistoryMapIN_UI8,
@@ -90,7 +93,16 @@ PVRSRVBridgeDevicememHistoryMap(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevicememHistoryMapOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevicememHistoryMap_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -112,7 +124,7 @@ PVRSRVBridgeDevicememHistoryMap(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -182,7 +194,10 @@ DevicememHistoryMap_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevicememHistoryMapOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -194,6 +209,9 @@ DevicememHistoryMap_exit:
        return 0;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevicememHistoryUnmap(IMG_UINT32 ui32DispatchTableEntry,
                                  IMG_UINT8 * psDevicememHistoryUnmapIN_UI8,
@@ -217,7 +235,16 @@ PVRSRVBridgeDevicememHistoryUnmap(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevicememHistoryUnmapOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevicememHistoryUnmap_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -239,7 +266,7 @@ PVRSRVBridgeDevicememHistoryUnmap(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -309,7 +336,10 @@ DevicememHistoryUnmap_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevicememHistoryUnmapOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -321,6 +351,9 @@ DevicememHistoryUnmap_exit:
        return 0;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
                                      IMG_UINT8 * psDevicememHistoryMapVRangeIN_UI8,
@@ -342,9 +375,16 @@ PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevicememHistoryMapVRangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevicememHistoryMapVRange_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -366,7 +406,7 @@ PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -396,7 +436,8 @@ PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
        }
 
        psDevicememHistoryMapVRangeOUT->eError =
-           DevicememHistoryMapVRangeKM(psDevicememHistoryMapVRangeIN->sBaseDevVAddr,
+           DevicememHistoryMapVRangeKM(psConnection, OSGetDevNode(psConnection),
+                                       psDevicememHistoryMapVRangeIN->sBaseDevVAddr,
                                        psDevicememHistoryMapVRangeIN->ui32ui32StartPage,
                                        psDevicememHistoryMapVRangeIN->ui32NumPages,
                                        psDevicememHistoryMapVRangeIN->uiAllocSize,
@@ -408,7 +449,10 @@ PVRSRVBridgeDevicememHistoryMapVRange(IMG_UINT32 ui32DispatchTableEntry,
 DevicememHistoryMapVRange_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevicememHistoryMapVRangeOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -420,6 +464,9 @@ DevicememHistoryMapVRange_exit:
        return 0;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
                                        IMG_UINT8 * psDevicememHistoryUnmapVRangeIN_UI8,
@@ -441,9 +488,16 @@ PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) + 0;
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevicememHistoryUnmapVRangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevicememHistoryUnmapVRange_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -466,7 +520,7 @@ PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -497,7 +551,8 @@ PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
        }
 
        psDevicememHistoryUnmapVRangeOUT->eError =
-           DevicememHistoryUnmapVRangeKM(psDevicememHistoryUnmapVRangeIN->sBaseDevVAddr,
+           DevicememHistoryUnmapVRangeKM(psConnection, OSGetDevNode(psConnection),
+                                         psDevicememHistoryUnmapVRangeIN->sBaseDevVAddr,
                                          psDevicememHistoryUnmapVRangeIN->ui32ui32StartPage,
                                          psDevicememHistoryUnmapVRangeIN->ui32NumPages,
                                          psDevicememHistoryUnmapVRangeIN->uiAllocSize,
@@ -510,7 +565,10 @@ PVRSRVBridgeDevicememHistoryUnmapVRange(IMG_UINT32 ui32DispatchTableEntry,
 DevicememHistoryUnmapVRange_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevicememHistoryUnmapVRangeOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -522,6 +580,9 @@ DevicememHistoryUnmapVRange_exit:
        return 0;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevicememHistorySparseChange(IMG_UINT32 ui32DispatchTableEntry,
                                         IMG_UINT8 * psDevicememHistorySparseChangeIN_UI8,
@@ -547,10 +608,21 @@ PVRSRVBridgeDevicememHistorySparseChange(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) +
-           (psDevicememHistorySparseChangeIN->ui32AllocPageCount * sizeof(IMG_UINT32)) +
-           (psDevicememHistorySparseChangeIN->ui32FreePageCount * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) DEVMEM_ANNOTATION_MAX_LEN * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psDevicememHistorySparseChangeIN->ui32AllocPageCount *
+            sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psDevicememHistorySparseChangeIN->ui32FreePageCount *
+            sizeof(IMG_UINT32)) + 0;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevicememHistorySparseChangeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevicememHistorySparseChange_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -573,7 +645,7 @@ PVRSRVBridgeDevicememHistorySparseChange(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -694,7 +766,10 @@ DevicememHistorySparseChange_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevicememHistorySparseChangeOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -713,7 +788,7 @@ DevicememHistorySparseChange_exit:
 static POS_LOCK pDEVICEMEMHISTORYBridgeLock;
 
 PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void);
-PVRSRV_ERROR DeinitDEVICEMEMHISTORYBridge(void);
+void DeinitDEVICEMEMHISTORYBridge(void);
 
 /*
  * Register all DEVICEMEMHISTORY functions with services
@@ -749,9 +824,9 @@ PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void)
 /*
  * Unregister all devicememhistory functions with services
  */
-PVRSRV_ERROR DeinitDEVICEMEMHISTORYBridge(void)
+void DeinitDEVICEMEMHISTORYBridge(void)
 {
-       PVR_LOG_RETURN_IF_ERROR(OSLockDestroy(pDEVICEMEMHISTORYBridgeLock), "OSLockDestroy");
+       OSLockDestroy(pDEVICEMEMHISTORYBridgeLock);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
                                PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYMAP);
@@ -768,5 +843,4 @@ PVRSRV_ERROR DeinitDEVICEMEMHISTORYBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DEVICEMEMHISTORY,
                                PVRSRV_BRIDGE_DEVICEMEMHISTORY_DEVICEMEMHISTORYSPARSECHANGE);
 
-       return PVRSRV_OK;
 }
index f4fd94b..8591006 100644 (file)
@@ -122,10 +122,10 @@ typedef struct PVRSRV_BRIDGE_OUT_DIREADENTRY_TAG
 /* Bridge in structure for DIWriteEntry */
 typedef struct PVRSRV_BRIDGE_IN_DIWRITEENTRY_TAG
 {
-       IMG_UINT64 ui64ValueSize;
        IMG_HANDLE hContext;
        const IMG_CHAR *puiEntryPath;
        const IMG_CHAR *puiValue;
+       IMG_UINT32 ui32ValueSize;
 } __packed PVRSRV_BRIDGE_IN_DIWRITEENTRY;
 
 /* Bridge out structure for DIWriteEntry */
index ab353eb..49a97a0 100644 (file)
@@ -91,12 +91,22 @@ PVRSRVBridgeDICreateContext(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) + 0;
 
        PVR_UNREFERENCED_PARAMETER(psDICreateContextIN);
 
        psDICreateContextOUT->puiStreamName = psDICreateContextIN->puiStreamName;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDICreateContextOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DICreateContext_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -117,7 +127,7 @@ PVRSRVBridgeDICreateContext(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -184,7 +194,10 @@ DICreateContext_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDICreateContextOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -210,10 +223,11 @@ PVRSRVBridgeDIDestroyContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDIDestroyContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDIDestroyContextIN->hContext,
-                                           PVRSRV_HANDLE_TYPE_DI_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDIDestroyContextIN->hContext,
+                                             PVRSRV_HANDLE_TYPE_DI_CONTEXT);
        if (unlikely((psDIDestroyContextOUT->eError != PVRSRV_OK) &&
+                    (psDIDestroyContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psDIDestroyContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -230,6 +244,9 @@ DIDestroyContext_exit:
        return 0;
 }
 
+static_assert(DI_IMPL_BRG_PATH_LEN <= IMG_UINT32_MAX,
+             "DI_IMPL_BRG_PATH_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDIReadEntry(IMG_UINT32 ui32DispatchTableEntry,
                        IMG_UINT8 * psDIReadEntryIN_UI8,
@@ -250,7 +267,16 @@ PVRSRVBridgeDIReadEntry(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (DI_IMPL_BRG_PATH_LEN * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) DI_IMPL_BRG_PATH_LEN * sizeof(IMG_CHAR)) + 0;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDIReadEntryOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DIReadEntry_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -272,7 +298,7 @@ PVRSRVBridgeDIReadEntry(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -336,7 +362,10 @@ DIReadEntry_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDIReadEntryOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -348,6 +377,11 @@ DIReadEntry_exit:
        return 0;
 }
 
+static_assert(DI_IMPL_BRG_PATH_LEN <= IMG_UINT32_MAX,
+             "DI_IMPL_BRG_PATH_LEN must not be larger than IMG_UINT32_MAX");
+static_assert(DI_IMPL_BRG_PATH_LEN <= IMG_UINT32_MAX,
+             "DI_IMPL_BRG_PATH_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDIWriteEntry(IMG_UINT32 ui32DispatchTableEntry,
                         IMG_UINT8 * psDIWriteEntryIN_UI8,
@@ -369,16 +403,25 @@ PVRSRVBridgeDIWriteEntry(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (DI_IMPL_BRG_PATH_LEN * sizeof(IMG_CHAR)) +
-           (psDIWriteEntryIN->ui64ValueSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) DI_IMPL_BRG_PATH_LEN * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psDIWriteEntryIN->ui32ValueSize * sizeof(IMG_CHAR)) + 0;
 
-       if (unlikely(psDIWriteEntryIN->ui64ValueSize > DI_IMPL_BRG_PATH_LEN))
+       if (unlikely(psDIWriteEntryIN->ui32ValueSize > DI_IMPL_BRG_PATH_LEN))
        {
                psDIWriteEntryOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
                goto DIWriteEntry_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDIWriteEntryOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DIWriteEntry_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -399,7 +442,7 @@ PVRSRVBridgeDIWriteEntry(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -427,24 +470,24 @@ PVRSRVBridgeDIWriteEntry(IMG_UINT32 ui32DispatchTableEntry,
                }
                ((IMG_CHAR *) uiEntryPathInt)[(DI_IMPL_BRG_PATH_LEN * sizeof(IMG_CHAR)) - 1] = '\0';
        }
-       if (psDIWriteEntryIN->ui64ValueSize != 0)
+       if (psDIWriteEntryIN->ui32ValueSize != 0)
        {
                uiValueInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
-               ui32NextOffset += psDIWriteEntryIN->ui64ValueSize * sizeof(IMG_CHAR);
+               ui32NextOffset += psDIWriteEntryIN->ui32ValueSize * sizeof(IMG_CHAR);
        }
 
        /* Copy the data over */
-       if (psDIWriteEntryIN->ui64ValueSize * sizeof(IMG_CHAR) > 0)
+       if (psDIWriteEntryIN->ui32ValueSize * sizeof(IMG_CHAR) > 0)
        {
                if (OSCopyFromUser
                    (NULL, uiValueInt, (const void __user *)psDIWriteEntryIN->puiValue,
-                    psDIWriteEntryIN->ui64ValueSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
+                    psDIWriteEntryIN->ui32ValueSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
                {
                        psDIWriteEntryOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
                        goto DIWriteEntry_exit;
                }
-               ((IMG_CHAR *) uiValueInt)[(psDIWriteEntryIN->ui64ValueSize * sizeof(IMG_CHAR)) -
+               ((IMG_CHAR *) uiValueInt)[(psDIWriteEntryIN->ui32ValueSize * sizeof(IMG_CHAR)) -
                                          1] = '\0';
        }
 
@@ -466,7 +509,7 @@ PVRSRVBridgeDIWriteEntry(IMG_UINT32 ui32DispatchTableEntry,
 
        psDIWriteEntryOUT->eError =
            DIWriteEntryKM(psContextInt,
-                          uiEntryPathInt, psDIWriteEntryIN->ui64ValueSize, uiValueInt);
+                          uiEntryPathInt, psDIWriteEntryIN->ui32ValueSize, uiValueInt);
 
 DIWriteEntry_exit:
 
@@ -483,7 +526,10 @@ DIWriteEntry_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDIWriteEntryOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -548,7 +594,7 @@ DIListAllEntries_exit:
  */
 
 PVRSRV_ERROR InitDIBridge(void);
-PVRSRV_ERROR DeinitDIBridge(void);
+void DeinitDIBridge(void);
 
 /*
  * Register all DI functions with services
@@ -577,7 +623,7 @@ PVRSRV_ERROR InitDIBridge(void)
 /*
  * Unregister all di functions with services
  */
-PVRSRV_ERROR DeinitDIBridge(void)
+void DeinitDIBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DI, PVRSRV_BRIDGE_DI_DICREATECONTEXT);
@@ -590,5 +636,4 @@ PVRSRV_ERROR DeinitDIBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DI, PVRSRV_BRIDGE_DI_DILISTALLENTRIES);
 
-       return PVRSRV_OK;
 }
index b6848d7..570be45 100644 (file)
@@ -65,6 +65,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
+static_assert(MAX_DMA_OPS <= IMG_UINT32_MAX, "MAX_DMA_OPS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDmaTransfer(IMG_UINT32 ui32DispatchTableEntry,
                        IMG_UINT8 * psDmaTransferIN_UI8,
@@ -87,12 +89,13 @@ PVRSRVBridgeDmaTransfer(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psDmaTransferIN->ui32NumDMAs * sizeof(PMR *)) +
-           (psDmaTransferIN->ui32NumDMAs * sizeof(IMG_HANDLE)) +
-           (psDmaTransferIN->ui32NumDMAs * sizeof(IMG_UINT64)) +
-           (psDmaTransferIN->ui32NumDMAs * sizeof(IMG_DEVMEM_OFFSET_T)) +
-           (psDmaTransferIN->ui32NumDMAs * sizeof(IMG_DEVMEM_SIZE_T)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psDmaTransferIN->ui32NumDMAs * sizeof(PMR *)) +
+           ((IMG_UINT64) psDmaTransferIN->ui32NumDMAs * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psDmaTransferIN->ui32NumDMAs * sizeof(IMG_UINT64)) +
+           ((IMG_UINT64) psDmaTransferIN->ui32NumDMAs * sizeof(IMG_DEVMEM_OFFSET_T)) +
+           ((IMG_UINT64) psDmaTransferIN->ui32NumDMAs * sizeof(IMG_DEVMEM_SIZE_T)) + 0;
 
        if (unlikely(psDmaTransferIN->ui32NumDMAs > MAX_DMA_OPS))
        {
@@ -100,6 +103,14 @@ PVRSRVBridgeDmaTransfer(IMG_UINT32 ui32DispatchTableEntry,
                goto DmaTransfer_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDmaTransferOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DmaTransfer_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -120,7 +131,7 @@ PVRSRVBridgeDmaTransfer(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -133,6 +144,7 @@ PVRSRVBridgeDmaTransfer(IMG_UINT32 ui32DispatchTableEntry,
        if (psDmaTransferIN->ui32NumDMAs != 0)
        {
                psPMRInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psPMRInt, 0, psDmaTransferIN->ui32NumDMAs * sizeof(PMR *));
                ui32NextOffset += psDmaTransferIN->ui32NumDMAs * sizeof(PMR *);
                hPMRInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psDmaTransferIN->ui32NumDMAs * sizeof(IMG_HANDLE);
@@ -251,7 +263,7 @@ DmaTransfer_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hPMRInt2[i])
+                       if (psPMRInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hPMRInt2[i],
@@ -263,7 +275,10 @@ DmaTransfer_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDmaTransferOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -298,8 +313,9 @@ PVRSRVBridgeDmaSparseMappingTable(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psDmaSparseMappingTableIN->ui32SizeInPages * sizeof(IMG_BOOL)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psDmaSparseMappingTableIN->ui32SizeInPages * sizeof(IMG_BOOL)) + 0;
 
        if (psDmaSparseMappingTableIN->ui32SizeInPages > 32)
        {
@@ -309,6 +325,14 @@ PVRSRVBridgeDmaSparseMappingTable(IMG_UINT32 ui32DispatchTableEntry,
 
        psDmaSparseMappingTableOUT->pbTable = psDmaSparseMappingTableIN->pbTable;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDmaSparseMappingTableOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DmaSparseMappingTable_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -329,7 +353,7 @@ PVRSRVBridgeDmaSparseMappingTable(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -365,6 +389,11 @@ PVRSRVBridgeDmaSparseMappingTable(IMG_UINT32 ui32DispatchTableEntry,
            DmaSparseMappingTable(psPMRInt,
                                  psDmaSparseMappingTableIN->uiOffset,
                                  psDmaSparseMappingTableIN->ui32SizeInPages, pbTableInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psDmaSparseMappingTableOUT->eError != PVRSRV_OK))
+       {
+               goto DmaSparseMappingTable_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((pbTableInt) && ((psDmaSparseMappingTableIN->ui32SizeInPages * sizeof(IMG_BOOL)) > 0))
@@ -396,7 +425,10 @@ DmaSparseMappingTable_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDmaSparseMappingTableOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -433,7 +465,7 @@ PVRSRVBridgeDmaDeviceParams(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitDMABridge(void);
-PVRSRV_ERROR DeinitDMABridge(void);
+void DeinitDMABridge(void);
 
 /*
  * Register all DMA functions with services
@@ -456,7 +488,7 @@ PVRSRV_ERROR InitDMABridge(void)
 /*
  * Unregister all dma functions with services
  */
-PVRSRV_ERROR DeinitDMABridge(void)
+void DeinitDMABridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMA, PVRSRV_BRIDGE_DMA_DMATRANSFER);
@@ -465,5 +497,4 @@ PVRSRV_ERROR DeinitDMABridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMA, PVRSRV_BRIDGE_DMA_DMADEVICEPARAMS);
 
-       return PVRSRV_OK;
 }
index 9bb059f..7547d9f 100644 (file)
@@ -55,9 +55,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define PVRSRV_BRIDGE_DMABUF_CMD_FIRST                 0
 #define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF                       PVRSRV_BRIDGE_DMABUF_CMD_FIRST+0
-#define PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF                       PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1
-#define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTSPARSEDMABUF                 PVRSRV_BRIDGE_DMABUF_CMD_FIRST+2
-#define PVRSRV_BRIDGE_DMABUF_CMD_LAST                  (PVRSRV_BRIDGE_DMABUF_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUFLOCKED                 PVRSRV_BRIDGE_DMABUF_CMD_FIRST+1
+#define PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF                       PVRSRV_BRIDGE_DMABUF_CMD_FIRST+2
+#define PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTSPARSEDMABUF                 PVRSRV_BRIDGE_DMABUF_CMD_FIRST+3
+#define PVRSRV_BRIDGE_DMABUF_CMD_LAST                  (PVRSRV_BRIDGE_DMABUF_CMD_FIRST+3)
 
 /*******************************************
             PhysmemImportDmaBuf
@@ -82,6 +83,28 @@ typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUF_TAG
 } __packed PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUF;
 
 /*******************************************
+            PhysmemImportDmaBufLocked
+ *******************************************/
+
+/* Bridge in structure for PhysmemImportDmaBufLocked */
+typedef struct PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUFLOCKED_TAG
+{
+       const IMG_CHAR *puiName;
+       IMG_INT ifd;
+       IMG_UINT32 ui32NameSize;
+       PVRSRV_MEMALLOCFLAGS_T uiFlags;
+} __packed PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUFLOCKED;
+
+/* Bridge out structure for PhysmemImportDmaBufLocked */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUFLOCKED_TAG
+{
+       IMG_DEVMEM_ALIGN_T uiAlign;
+       IMG_DEVMEM_SIZE_T uiSize;
+       IMG_HANDLE hPMRPtr;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUFLOCKED;
+
+/*******************************************
             PhysmemExportDmaBuf
  *******************************************/
 
index fba9290..07851de 100644 (file)
@@ -73,6 +73,9 @@ static PVRSRV_ERROR _PhysmemImportDmaBufpsPMRPtrIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePhysmemImportDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                                IMG_UINT8 * psPhysmemImportDmaBufIN_UI8,
@@ -95,7 +98,9 @@ PVRSRVBridgePhysmemImportDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psPhysmemImportDmaBufIN->ui32NameSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysmemImportDmaBufIN->ui32NameSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psPhysmemImportDmaBufIN->ui32NameSize > DEVMEM_ANNOTATION_MAX_LEN))
        {
@@ -103,6 +108,14 @@ PVRSRVBridgePhysmemImportDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                goto PhysmemImportDmaBuf_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysmemImportDmaBufOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysmemImportDmaBuf_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -123,7 +136,7 @@ PVRSRVBridgePhysmemImportDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -201,7 +214,174 @@ PhysmemImportDmaBuf_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysmemImportDmaBufOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static PVRSRV_ERROR _PhysmemImportDmaBufLockedpsPMRPtrIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = PMRUnrefUnlockPMR((PMR *) pvData);
+       return eError;
+}
+
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgePhysmemImportDmaBufLocked(IMG_UINT32 ui32DispatchTableEntry,
+                                     IMG_UINT8 * psPhysmemImportDmaBufLockedIN_UI8,
+                                     IMG_UINT8 * psPhysmemImportDmaBufLockedOUT_UI8,
+                                     CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUFLOCKED *psPhysmemImportDmaBufLockedIN =
+           (PVRSRV_BRIDGE_IN_PHYSMEMIMPORTDMABUFLOCKED *)
+           IMG_OFFSET_ADDR(psPhysmemImportDmaBufLockedIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUFLOCKED *psPhysmemImportDmaBufLockedOUT =
+           (PVRSRV_BRIDGE_OUT_PHYSMEMIMPORTDMABUFLOCKED *)
+           IMG_OFFSET_ADDR(psPhysmemImportDmaBufLockedOUT_UI8, 0);
+
+       IMG_CHAR *uiNameInt = NULL;
+       PMR *psPMRPtrInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysmemImportDmaBufLockedIN->ui32NameSize * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely(psPhysmemImportDmaBufLockedIN->ui32NameSize > DEVMEM_ANNOTATION_MAX_LEN))
+       {
+               psPhysmemImportDmaBufLockedOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto PhysmemImportDmaBufLocked_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysmemImportDmaBufLockedOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysmemImportDmaBufLocked_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psPhysmemImportDmaBufLockedIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psPhysmemImportDmaBufLockedIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psPhysmemImportDmaBufLockedOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto PhysmemImportDmaBufLocked_exit;
+                       }
+               }
+       }
+
+       if (psPhysmemImportDmaBufLockedIN->ui32NameSize != 0)
+       {
+               uiNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psPhysmemImportDmaBufLockedIN->ui32NameSize * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psPhysmemImportDmaBufLockedIN->ui32NameSize * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiNameInt, (const void __user *)psPhysmemImportDmaBufLockedIN->puiName,
+                    psPhysmemImportDmaBufLockedIN->ui32NameSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psPhysmemImportDmaBufLockedOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto PhysmemImportDmaBufLocked_exit;
+               }
+               ((IMG_CHAR *)
+                uiNameInt)[(psPhysmemImportDmaBufLockedIN->ui32NameSize * sizeof(IMG_CHAR)) - 1] =
+       '\0';
+       }
+
+       psPhysmemImportDmaBufLockedOUT->eError =
+           PhysmemImportDmaBufLocked(psConnection, OSGetDevNode(psConnection),
+                                     psPhysmemImportDmaBufLockedIN->ifd,
+                                     psPhysmemImportDmaBufLockedIN->uiFlags,
+                                     psPhysmemImportDmaBufLockedIN->ui32NameSize,
+                                     uiNameInt,
+                                     &psPMRPtrInt,
+                                     &psPhysmemImportDmaBufLockedOUT->uiSize,
+                                     &psPhysmemImportDmaBufLockedOUT->uiAlign);
+       /* Exit early if bridged call fails */
+       if (unlikely(psPhysmemImportDmaBufLockedOUT->eError != PVRSRV_OK))
+       {
+               goto PhysmemImportDmaBufLocked_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psHandleBase);
+
+       psPhysmemImportDmaBufLockedOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+                                     &psPhysmemImportDmaBufLockedOUT->hPMRPtr, (void *)psPMRPtrInt,
+                                     PVRSRV_HANDLE_TYPE_PHYSMEM_PMR,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _PhysmemImportDmaBufLockedpsPMRPtrIntRelease);
+       if (unlikely(psPhysmemImportDmaBufLockedOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psHandleBase);
+               goto PhysmemImportDmaBufLocked_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psHandleBase);
+
+PhysmemImportDmaBufLocked_exit:
+
+       if (psPhysmemImportDmaBufLockedOUT->eError != PVRSRV_OK)
+       {
+               if (psPMRPtrInt)
+               {
+                       LockHandle(KERNEL_HANDLE_BASE);
+                       PMRUnrefUnlockPMR(psPMRPtrInt);
+                       UnlockHandle(KERNEL_HANDLE_BASE);
+               }
+       }
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysmemImportDmaBufLockedOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -273,6 +453,11 @@ static PVRSRV_ERROR _PhysmemImportSparseDmaBufpsPMRPtrIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(PMR_MAX_SUPPORTED_PAGE_COUNT <= IMG_UINT32_MAX,
+             "PMR_MAX_SUPPORTED_PAGE_COUNT must not be larger than IMG_UINT32_MAX");
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePhysmemImportSparseDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                                      IMG_UINT8 * psPhysmemImportSparseDmaBufIN_UI8,
@@ -296,9 +481,10 @@ PVRSRVBridgePhysmemImportSparseDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
-           (psPhysmemImportSparseDmaBufIN->ui32NameSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psPhysmemImportSparseDmaBufIN->ui32NameSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely
            (psPhysmemImportSparseDmaBufIN->ui32NumPhysChunks > PMR_MAX_SUPPORTED_PAGE_COUNT))
@@ -313,6 +499,14 @@ PVRSRVBridgePhysmemImportSparseDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                goto PhysmemImportSparseDmaBuf_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysmemImportSparseDmaBufOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysmemImportSparseDmaBuf_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -333,7 +527,7 @@ PVRSRVBridgePhysmemImportSparseDmaBuf(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -438,7 +632,10 @@ PhysmemImportSparseDmaBuf_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysmemImportSparseDmaBufOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -455,7 +652,7 @@ PhysmemImportSparseDmaBuf_exit:
  */
 
 PVRSRV_ERROR InitDMABUFBridge(void);
-PVRSRV_ERROR DeinitDMABUFBridge(void);
+void DeinitDMABUFBridge(void);
 
 /*
  * Register all DMABUF functions with services
@@ -466,6 +663,9 @@ PVRSRV_ERROR InitDMABUFBridge(void)
        SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF,
                              PVRSRVBridgePhysmemImportDmaBuf, NULL);
 
+       SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUFLOCKED,
+                             PVRSRVBridgePhysmemImportDmaBufLocked, NULL);
+
        SetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF,
                              PVRSRVBridgePhysmemExportDmaBuf, NULL);
 
@@ -478,15 +678,17 @@ PVRSRV_ERROR InitDMABUFBridge(void)
 /*
  * Unregister all dmabuf functions with services
  */
-PVRSRV_ERROR DeinitDMABUFBridge(void)
+void DeinitDMABUFBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUF);
 
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF,
+                               PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTDMABUFLOCKED);
+
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF, PVRSRV_BRIDGE_DMABUF_PHYSMEMEXPORTDMABUF);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_DMABUF,
                                PVRSRV_BRIDGE_DMABUF_PHYSMEMIMPORTSPARSEDMABUF);
 
-       return PVRSRV_OK;
 }
index 8a4f5c0..dd81d91 100644 (file)
@@ -69,6 +69,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
+static_assert(HTB_FLAG_NUM_EL <= IMG_UINT32_MAX,
+             "HTB_FLAG_NUM_EL must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
                       IMG_UINT8 * psHTBControlIN_UI8,
@@ -87,7 +90,9 @@ PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psHTBControlIN->ui32NumGroups * sizeof(IMG_UINT32)) + 0;
 
        if (unlikely(psHTBControlIN->ui32NumGroups > HTB_FLAG_NUM_EL))
        {
@@ -97,6 +102,14 @@ PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psHTBControlOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto HTBControl_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -117,7 +130,7 @@ PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -158,7 +171,10 @@ PVRSRVBridgeHTBControl(IMG_UINT32 ui32DispatchTableEntry,
 HTBControl_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psHTBControlOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -170,6 +186,9 @@ HTBControl_exit:
        return 0;
 }
 
+static_assert(HTB_LOG_MAX_PARAMS <= IMG_UINT32_MAX,
+             "HTB_LOG_MAX_PARAMS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
                   IMG_UINT8 * psHTBLogIN_UI8,
@@ -188,7 +207,8 @@ PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) psHTBLogIN->ui32NumArgs * sizeof(IMG_UINT32)) + 0;
 
        if (unlikely(psHTBLogIN->ui32NumArgs > HTB_LOG_MAX_PARAMS))
        {
@@ -198,6 +218,14 @@ PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psHTBLogOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto HTBLog_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -218,7 +246,7 @@ PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -256,7 +284,10 @@ PVRSRVBridgeHTBLog(IMG_UINT32 ui32DispatchTableEntry,
 HTBLog_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psHTBLogOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -278,7 +309,7 @@ static POS_LOCK pHTBUFFERBridgeLock;
 
 #if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 PVRSRV_ERROR InitHTBUFFERBridge(void);
-PVRSRV_ERROR DeinitHTBUFFERBridge(void);
+void DeinitHTBUFFERBridge(void);
 
 /*
  * Register all HTBUFFER functions with services
@@ -299,15 +330,14 @@ PVRSRV_ERROR InitHTBUFFERBridge(void)
 /*
  * Unregister all htbuffer functions with services
  */
-PVRSRV_ERROR DeinitHTBUFFERBridge(void)
+void DeinitHTBUFFERBridge(void)
 {
-       PVR_LOG_RETURN_IF_ERROR(OSLockDestroy(pHTBUFFERBridgeLock), "OSLockDestroy");
+       OSLockDestroy(pHTBUFFERBridgeLock);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_HTBUFFER, PVRSRV_BRIDGE_HTBUFFER_HTBCONTROL);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_HTBUFFER, PVRSRV_BRIDGE_HTBUFFER_HTBLOG);
 
-       return PVRSRV_OK;
 }
 #else /* EXCLUDE_HTBUFFER_BRIDGE */
 /* This bridge is conditional on EXCLUDE_HTBUFFER_BRIDGE - when defined,
@@ -316,7 +346,6 @@ PVRSRV_ERROR DeinitHTBUFFERBridge(void)
 #define InitHTBUFFERBridge() \
        PVRSRV_OK
 
-#define DeinitHTBUFFERBridge() \
-       PVRSRV_OK
+#define DeinitHTBUFFERBridge()
 
 #endif /* EXCLUDE_HTBUFFER_BRIDGE */
index 9c87828..ce172ea 100644 (file)
@@ -99,7 +99,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
                                                       const IMG_CHAR * puiAnnotation,
                                                       IMG_PID ui32PID,
                                                       IMG_HANDLE * phPMRPtr,
-                                                      IMG_UINT32 ui32PDumpFlags);
+                                                      IMG_UINT32 ui32PDumpFlags,
+                                                      PVRSRV_MEMALLOCFLAGS_T * puiOutFlags);
 
 IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedLockedPMR(IMG_HANDLE hBridge,
                                                             IMG_DEVMEM_SIZE_T uiSize,
@@ -113,7 +114,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedLockedPMR(IMG_HANDLE hBridge,
                                                             const IMG_CHAR * puiAnnotation,
                                                             IMG_PID ui32PID,
                                                             IMG_HANDLE * phPMRPtr,
-                                                            IMG_UINT32 ui32PDumpFlags);
+                                                            IMG_UINT32 ui32PDumpFlags,
+                                                            PVRSRV_MEMALLOCFLAGS_T * puiOutFlags);
 
 IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntPin(IMG_HANDLE hBridge, IMG_HANDLE hPMR);
 
@@ -224,12 +226,23 @@ IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapDetails(IMG_HANDLE hBridge,
                                                   IMG_UINT32 * pui32Log2ImportAlignmentOut);
 
 IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntRegisterPFNotifyKM(IMG_HANDLE hBridge,
-                                                           IMG_HANDLE hDevmemCtx,
+                                                           IMG_HANDLE hDevm,
                                                            IMG_UINT32 ui32PID, IMG_BOOL bRegister);
 
-IMG_INTERNAL PVRSRV_ERROR BridgeGetMaxDevMemSize(IMG_HANDLE hBridge,
-                                                IMG_DEVMEM_SIZE_T * puiLMASize,
-                                                IMG_DEVMEM_SIZE_T * puiUMASize);
+IMG_INTERNAL PVRSRV_ERROR BridgeGetMaxPhysHeapCount(IMG_HANDLE hBridge,
+                                                   IMG_UINT32 * pui32PhysHeapCount);
+
+IMG_INTERNAL PVRSRV_ERROR BridgePhysHeapGetMemInfo(IMG_HANDLE hBridge,
+                                                  IMG_UINT32 ui32PhysHeapCount,
+                                                  PVRSRV_PHYS_HEAP * peaPhysHeapID,
+                                                  PHYS_HEAP_MEM_STATS * pasapPhysHeapMemStats);
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetDefaultPhysicalHeap(IMG_HANDLE hBridge,
+                                                      PVRSRV_PHYS_HEAP * peHeap);
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetHeapPhysMemUsage(IMG_HANDLE hBridge,
+                                                   IMG_UINT32 ui32PhysHeapCount,
+                                                   PHYS_HEAP_MEM_STATS * pasapPhysHeapMemStats);
 
 IMG_INTERNAL PVRSRV_ERROR BridgeDevmemGetFaultAddress(IMG_HANDLE hBridge,
                                                      IMG_HANDLE hDevmemCtx,
@@ -238,4 +251,15 @@ IMG_INTERNAL PVRSRV_ERROR BridgeDevmemGetFaultAddress(IMG_HANDLE hBridge,
 IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVUpdateOOMStats(IMG_HANDLE hBridge,
                                                     IMG_UINT32 ui32ui32StatType, IMG_PID ui32pid);
 
+IMG_INTERNAL PVRSRV_ERROR BridgePhysHeapGetMemInfoPkd(IMG_HANDLE hBridge,
+                                                     IMG_UINT32 ui32PhysHeapCount,
+                                                     PVRSRV_PHYS_HEAP * peaPhysHeapID,
+                                                     PHYS_HEAP_MEM_STATS_PKD *
+                                                     psapPhysHeapMemStats);
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetHeapPhysMemUsagePkd(IMG_HANDLE hBridge,
+                                                      IMG_UINT32 ui32PhysHeapCount,
+                                                      PHYS_HEAP_MEM_STATS_PKD *
+                                                      psapPhysHeapMemStats);
+
 #endif /* CLIENT_MM_BRIDGE_H */
index 2834253..958706b 100644 (file)
@@ -48,8 +48,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* Module specific includes */
 #include "pvrsrv_memallocflags.h"
+#include "pvrsrv_memalloc_physheap.h"
 #include "devicemem_typedefs.h"
 
+#include "pvrsrv_memalloc_physheap.h"
 #include "devicemem.h"
 #include "devicemem_server.h"
 #include "pmr.h"
@@ -212,7 +214,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
                                                       const IMG_CHAR * puiAnnotation,
                                                       IMG_PID ui32PID,
                                                       IMG_HANDLE * phPMRPtr,
-                                                      IMG_UINT32 ui32PDumpFlags)
+                                                      IMG_UINT32 ui32PDumpFlags,
+                                                      PVRSRV_MEMALLOCFLAGS_T * puiOutFlags)
 {
        PVRSRV_ERROR eError;
        PMR *psPMRPtrInt = NULL;
@@ -227,7 +230,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedPMR(IMG_HANDLE hBridge,
                                          ui32Log2PageSize,
                                          uiFlags,
                                          ui32AnnotationLength,
-                                         puiAnnotation, ui32PID, &psPMRPtrInt, ui32PDumpFlags);
+                                         puiAnnotation,
+                                         ui32PID, &psPMRPtrInt, ui32PDumpFlags, puiOutFlags);
 
        *phPMRPtr = psPMRPtrInt;
        return eError;
@@ -245,7 +249,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedLockedPMR(IMG_HANDLE hBridge,
                                                             const IMG_CHAR * puiAnnotation,
                                                             IMG_PID ui32PID,
                                                             IMG_HANDLE * phPMRPtr,
-                                                            IMG_UINT32 ui32PDumpFlags)
+                                                            IMG_UINT32 ui32PDumpFlags,
+                                                            PVRSRV_MEMALLOCFLAGS_T * puiOutFlags)
 {
        PVRSRV_ERROR eError;
        PMR *psPMRPtrInt = NULL;
@@ -260,7 +265,8 @@ IMG_INTERNAL PVRSRV_ERROR BridgePhysmemNewRamBackedLockedPMR(IMG_HANDLE hBridge,
                                         ui32Log2PageSize,
                                         uiFlags,
                                         ui32AnnotationLength,
-                                        puiAnnotation, ui32PID, &psPMRPtrInt, ui32PDumpFlags);
+                                        puiAnnotation,
+                                        ui32PID, &psPMRPtrInt, ui32PDumpFlags, puiOutFlags);
 
        *phPMRPtr = psPMRPtrInt;
        return eError;
@@ -669,29 +675,66 @@ IMG_INTERNAL PVRSRV_ERROR BridgeHeapCfgHeapDetails(IMG_HANDLE hBridge,
 }
 
 IMG_INTERNAL PVRSRV_ERROR BridgeDevmemIntRegisterPFNotifyKM(IMG_HANDLE hBridge,
-                                                           IMG_HANDLE hDevmemCtx,
+                                                           IMG_HANDLE hDevm,
                                                            IMG_UINT32 ui32PID, IMG_BOOL bRegister)
 {
        PVRSRV_ERROR eError;
-       DEVMEMINT_CTX *psDevmemCtxInt;
+       DEVMEMINT_CTX *psDevmInt;
        PVR_UNREFERENCED_PARAMETER(hBridge);
 
-       psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
+       psDevmInt = (DEVMEMINT_CTX *) hDevm;
+
+       eError = DevmemIntRegisterPFNotifyKM(psDevmInt, ui32PID, bRegister);
+
+       return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetMaxPhysHeapCount(IMG_HANDLE hBridge,
+                                                   IMG_UINT32 * pui32PhysHeapCount)
+{
+       PVRSRV_ERROR eError;
+
+       eError =
+           PVRSRVGetMaxPhysHeapCountKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                       pui32PhysHeapCount);
+
+       return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR BridgePhysHeapGetMemInfo(IMG_HANDLE hBridge,
+                                                  IMG_UINT32 ui32PhysHeapCount,
+                                                  PVRSRV_PHYS_HEAP * peaPhysHeapID,
+                                                  PHYS_HEAP_MEM_STATS * pasapPhysHeapMemStats)
+{
+       PVRSRV_ERROR eError;
+
+       eError =
+           PVRSRVPhysHeapGetMemInfoKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                      ui32PhysHeapCount, peaPhysHeapID, pasapPhysHeapMemStats);
+
+       return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetDefaultPhysicalHeap(IMG_HANDLE hBridge,
+                                                      PVRSRV_PHYS_HEAP * peHeap)
+{
+       PVRSRV_ERROR eError;
 
-       eError = DevmemIntRegisterPFNotifyKM(psDevmemCtxInt, ui32PID, bRegister);
+       eError =
+           PVRSRVGetDefaultPhysicalHeapKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge), peHeap);
 
        return eError;
 }
 
-IMG_INTERNAL PVRSRV_ERROR BridgeGetMaxDevMemSize(IMG_HANDLE hBridge,
-                                                IMG_DEVMEM_SIZE_T * puiLMASize,
-                                                IMG_DEVMEM_SIZE_T * puiUMASize)
+IMG_INTERNAL PVRSRV_ERROR BridgeGetHeapPhysMemUsage(IMG_HANDLE hBridge,
+                                                   IMG_UINT32 ui32PhysHeapCount,
+                                                   PHYS_HEAP_MEM_STATS * pasapPhysHeapMemStats)
 {
        PVRSRV_ERROR eError;
 
        eError =
-           PVRSRVGetMaxDevMemSizeKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
-                                    puiLMASize, puiUMASize);
+           PVRSRVGetHeapPhysMemUsageKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                       ui32PhysHeapCount, pasapPhysHeapMemStats);
 
        return eError;
 }
@@ -730,3 +773,32 @@ IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVUpdateOOMStats(IMG_HANDLE hBridge,
        return PVRSRV_ERROR_NOT_IMPLEMENTED;
 #endif
 }
+
+IMG_INTERNAL PVRSRV_ERROR BridgePhysHeapGetMemInfoPkd(IMG_HANDLE hBridge,
+                                                     IMG_UINT32 ui32PhysHeapCount,
+                                                     PVRSRV_PHYS_HEAP * peaPhysHeapID,
+                                                     PHYS_HEAP_MEM_STATS_PKD *
+                                                     psapPhysHeapMemStats)
+{
+       PVRSRV_ERROR eError;
+
+       eError =
+           PVRSRVPhysHeapGetMemInfoPkdKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                         ui32PhysHeapCount, peaPhysHeapID, psapPhysHeapMemStats);
+
+       return eError;
+}
+
+IMG_INTERNAL PVRSRV_ERROR BridgeGetHeapPhysMemUsagePkd(IMG_HANDLE hBridge,
+                                                      IMG_UINT32 ui32PhysHeapCount,
+                                                      PHYS_HEAP_MEM_STATS_PKD *
+                                                      psapPhysHeapMemStats)
+{
+       PVRSRV_ERROR eError;
+
+       eError =
+           PVRSRVGetHeapPhysMemUsagePkdKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                          ui32PhysHeapCount, psapPhysHeapMemStats);
+
+       return eError;
+}
index ef84d4b..bbb419b 100644 (file)
@@ -52,6 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv_error.h"
 
 #include "pvrsrv_memallocflags.h"
+#include "pvrsrv_memalloc_physheap.h"
 #include "devicemem_typedefs.h"
 
 #define PVRSRV_BRIDGE_MM_CMD_FIRST                     0
@@ -89,10 +90,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PVRSRV_BRIDGE_MM_HEAPCFGHEAPCONFIGNAME                 PVRSRV_BRIDGE_MM_CMD_FIRST+31
 #define PVRSRV_BRIDGE_MM_HEAPCFGHEAPDETAILS                    PVRSRV_BRIDGE_MM_CMD_FIRST+32
 #define PVRSRV_BRIDGE_MM_DEVMEMINTREGISTERPFNOTIFYKM                   PVRSRV_BRIDGE_MM_CMD_FIRST+33
-#define PVRSRV_BRIDGE_MM_GETMAXDEVMEMSIZE                      PVRSRV_BRIDGE_MM_CMD_FIRST+34
-#define PVRSRV_BRIDGE_MM_DEVMEMGETFAULTADDRESS                 PVRSRV_BRIDGE_MM_CMD_FIRST+35
-#define PVRSRV_BRIDGE_MM_PVRSRVUPDATEOOMSTATS                  PVRSRV_BRIDGE_MM_CMD_FIRST+36
-#define PVRSRV_BRIDGE_MM_CMD_LAST                      (PVRSRV_BRIDGE_MM_CMD_FIRST+36)
+#define PVRSRV_BRIDGE_MM_GETMAXPHYSHEAPCOUNT                   PVRSRV_BRIDGE_MM_CMD_FIRST+34
+#define PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFO                    PVRSRV_BRIDGE_MM_CMD_FIRST+35
+#define PVRSRV_BRIDGE_MM_GETDEFAULTPHYSICALHEAP                        PVRSRV_BRIDGE_MM_CMD_FIRST+36
+#define PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGE                   PVRSRV_BRIDGE_MM_CMD_FIRST+37
+#define PVRSRV_BRIDGE_MM_DEVMEMGETFAULTADDRESS                 PVRSRV_BRIDGE_MM_CMD_FIRST+38
+#define PVRSRV_BRIDGE_MM_PVRSRVUPDATEOOMSTATS                  PVRSRV_BRIDGE_MM_CMD_FIRST+39
+#define PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFOPKD                 PVRSRV_BRIDGE_MM_CMD_FIRST+40
+#define PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGEPKD                        PVRSRV_BRIDGE_MM_CMD_FIRST+41
+#define PVRSRV_BRIDGE_MM_CMD_LAST                      (PVRSRV_BRIDGE_MM_CMD_FIRST+41)
 
 /*******************************************
             PMRExportPMR
@@ -276,6 +282,7 @@ typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDPMR_TAG
 {
        IMG_HANDLE hPMRPtr;
        PVRSRV_ERROR eError;
+       PVRSRV_MEMALLOCFLAGS_T uiOutFlags;
 } __packed PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDPMR;
 
 /*******************************************
@@ -303,6 +310,7 @@ typedef struct PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDLOCKEDPMR_TAG
 {
        IMG_HANDLE hPMRPtr;
        PVRSRV_ERROR eError;
+       PVRSRV_MEMALLOCFLAGS_T uiOutFlags;
 } __packed PVRSRV_BRIDGE_OUT_PHYSMEMNEWRAMBACKEDLOCKEDPMR;
 
 /*******************************************
@@ -715,7 +723,7 @@ typedef struct PVRSRV_BRIDGE_OUT_HEAPCFGHEAPDETAILS_TAG
 /* Bridge in structure for DevmemIntRegisterPFNotifyKM */
 typedef struct PVRSRV_BRIDGE_IN_DEVMEMINTREGISTERPFNOTIFYKM_TAG
 {
-       IMG_HANDLE hDevmemCtx;
+       IMG_HANDLE hDevm;
        IMG_BOOL bRegister;
        IMG_UINT32 ui32PID;
 } __packed PVRSRV_BRIDGE_IN_DEVMEMINTREGISTERPFNOTIFYKM;
@@ -727,22 +735,75 @@ typedef struct PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM_TAG
 } __packed PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM;
 
 /*******************************************
-            GetMaxDevMemSize
+            GetMaxPhysHeapCount
  *******************************************/
 
-/* Bridge in structure for GetMaxDevMemSize */
-typedef struct PVRSRV_BRIDGE_IN_GETMAXDEVMEMSIZE_TAG
+/* Bridge in structure for GetMaxPhysHeapCount */
+typedef struct PVRSRV_BRIDGE_IN_GETMAXPHYSHEAPCOUNT_TAG
 {
        IMG_UINT32 ui32EmptyStructPlaceholder;
-} __packed PVRSRV_BRIDGE_IN_GETMAXDEVMEMSIZE;
+} __packed PVRSRV_BRIDGE_IN_GETMAXPHYSHEAPCOUNT;
+
+/* Bridge out structure for GetMaxPhysHeapCount */
+typedef struct PVRSRV_BRIDGE_OUT_GETMAXPHYSHEAPCOUNT_TAG
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32PhysHeapCount;
+} __packed PVRSRV_BRIDGE_OUT_GETMAXPHYSHEAPCOUNT;
+
+/*******************************************
+            PhysHeapGetMemInfo
+ *******************************************/
+
+/* Bridge in structure for PhysHeapGetMemInfo */
+typedef struct PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFO_TAG
+{
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStats;
+       PVRSRV_PHYS_HEAP *peaPhysHeapID;
+       IMG_UINT32 ui32PhysHeapCount;
+} __packed PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFO;
+
+/* Bridge out structure for PhysHeapGetMemInfo */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFO_TAG
+{
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStats;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFO;
+
+/*******************************************
+            GetDefaultPhysicalHeap
+ *******************************************/
+
+/* Bridge in structure for GetDefaultPhysicalHeap */
+typedef struct PVRSRV_BRIDGE_IN_GETDEFAULTPHYSICALHEAP_TAG
+{
+       IMG_UINT32 ui32EmptyStructPlaceholder;
+} __packed PVRSRV_BRIDGE_IN_GETDEFAULTPHYSICALHEAP;
+
+/* Bridge out structure for GetDefaultPhysicalHeap */
+typedef struct PVRSRV_BRIDGE_OUT_GETDEFAULTPHYSICALHEAP_TAG
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_PHYS_HEAP eHeap;
+} __packed PVRSRV_BRIDGE_OUT_GETDEFAULTPHYSICALHEAP;
 
-/* Bridge out structure for GetMaxDevMemSize */
-typedef struct PVRSRV_BRIDGE_OUT_GETMAXDEVMEMSIZE_TAG
+/*******************************************
+            GetHeapPhysMemUsage
+ *******************************************/
+
+/* Bridge in structure for GetHeapPhysMemUsage */
+typedef struct PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGE_TAG
 {
-       IMG_DEVMEM_SIZE_T uiLMASize;
-       IMG_DEVMEM_SIZE_T uiUMASize;
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStats;
+       IMG_UINT32 ui32PhysHeapCount;
+} __packed PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGE;
+
+/* Bridge out structure for GetHeapPhysMemUsage */
+typedef struct PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGE_TAG
+{
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStats;
        PVRSRV_ERROR eError;
-} __packed PVRSRV_BRIDGE_OUT_GETMAXDEVMEMSIZE;
+} __packed PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGE;
 
 /*******************************************
             DevmemGetFaultAddress
@@ -778,4 +839,41 @@ typedef struct PVRSRV_BRIDGE_OUT_PVRSRVUPDATEOOMSTATS_TAG
        PVRSRV_ERROR eError;
 } __packed PVRSRV_BRIDGE_OUT_PVRSRVUPDATEOOMSTATS;
 
+/*******************************************
+            PhysHeapGetMemInfoPkd
+ *******************************************/
+
+/* Bridge in structure for PhysHeapGetMemInfoPkd */
+typedef struct PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFOPKD_TAG
+{
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStats;
+       PVRSRV_PHYS_HEAP *peaPhysHeapID;
+       IMG_UINT32 ui32PhysHeapCount;
+} __packed PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFOPKD;
+
+/* Bridge out structure for PhysHeapGetMemInfoPkd */
+typedef struct PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFOPKD_TAG
+{
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStats;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFOPKD;
+
+/*******************************************
+            GetHeapPhysMemUsagePkd
+ *******************************************/
+
+/* Bridge in structure for GetHeapPhysMemUsagePkd */
+typedef struct PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGEPKD_TAG
+{
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStats;
+       IMG_UINT32 ui32PhysHeapCount;
+} __packed PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGEPKD;
+
+/* Bridge out structure for GetHeapPhysMemUsagePkd */
+typedef struct PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGEPKD_TAG
+{
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStats;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGEPKD;
+
 #endif /* COMMON_MM_BRIDGE_H */
index 5e5b400..7375eb6 100644 (file)
@@ -45,6 +45,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "img_defs.h"
 
+#include "pvrsrv_memalloc_physheap.h"
 #include "devicemem.h"
 #include "devicemem_server.h"
 #include "pmr.h"
@@ -200,7 +201,7 @@ PMRExportPMR_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(KERNEL_HANDLE_BASE);
 
-                       eError = PVRSRVReleaseHandleUnlocked(KERNEL_HANDLE_BASE,
+                       eError = PVRSRVDestroyHandleUnlocked(KERNEL_HANDLE_BASE,
                                                             (IMG_HANDLE) psPMRExportPMROUT->
                                                             hPMRExport,
                                                             PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
@@ -225,7 +226,7 @@ PMRExportPMR_exit:
                        LockHandle(psConnection->psProcessHandleBase->psHandleBase);
 
                        eError =
-                           PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->
+                           PVRSRVDestroyHandleUnlocked(psConnection->psProcessHandleBase->
                                                        psHandleBase, hPMRExportInt,
                                                        PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
                        if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
@@ -306,9 +307,10 @@ PVRSRVBridgePMRUnexportPMR(IMG_UINT32 ui32DispatchTableEntry,
        PVR_ASSERT(psPMRUnexportPMROUT->eError == PVRSRV_OK);
 
        psPMRUnexportPMROUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psProcessHandleBase->psHandleBase,
-                                           hPMRExportInt, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             hPMRExportInt, PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
        if (unlikely((psPMRUnexportPMROUT->eError != PVRSRV_OK) &&
+                    (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -323,10 +325,11 @@ PVRSRVBridgePMRUnexportPMR(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(KERNEL_HANDLE_BASE);
 
        psPMRUnexportPMROUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(KERNEL_HANDLE_BASE,
-                                           (IMG_HANDLE) psPMRUnexportPMRIN->hPMRExport,
-                                           PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
+           PVRSRVDestroyHandleStagedUnlocked(KERNEL_HANDLE_BASE,
+                                             (IMG_HANDLE) psPMRUnexportPMRIN->hPMRExport,
+                                             PVRSRV_HANDLE_TYPE_PHYSMEM_PMR_EXPORT);
        if (unlikely((psPMRUnexportPMROUT->eError != PVRSRV_OK) &&
+                    (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psPMRUnexportPMROUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -502,10 +505,11 @@ PVRSRVBridgePMRUnmakeLocalImportHandle(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psProcessHandleBase->psHandleBase);
 
        psPMRUnmakeLocalImportHandleOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psProcessHandleBase->psHandleBase,
-                                           (IMG_HANDLE) psPMRUnmakeLocalImportHandleIN->hExtMem,
-                                           PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             (IMG_HANDLE) psPMRUnmakeLocalImportHandleIN->hExtMem,
+                                             PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
        if (unlikely((psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_OK) &&
+                    (psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psPMRUnmakeLocalImportHandleOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -726,10 +730,11 @@ PVRSRVBridgePMRUnrefPMR(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psPMRUnrefPMROUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psPMRUnrefPMRIN->hPMR,
-                                           PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psPMRUnrefPMRIN->hPMR,
+                                             PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
        if (unlikely((psPMRUnrefPMROUT->eError != PVRSRV_OK) &&
+                    (psPMRUnrefPMROUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psPMRUnrefPMROUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -761,10 +766,11 @@ PVRSRVBridgePMRUnrefUnlockPMR(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psPMRUnrefUnlockPMROUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psPMRUnrefUnlockPMRIN->hPMR,
-                                           PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psPMRUnrefUnlockPMRIN->hPMR,
+                                             PVRSRV_HANDLE_TYPE_PHYSMEM_PMR);
        if (unlikely((psPMRUnrefUnlockPMROUT->eError != PVRSRV_OK) &&
+                    (psPMRUnrefUnlockPMROUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psPMRUnrefUnlockPMROUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -788,6 +794,11 @@ static PVRSRV_ERROR _PhysmemNewRamBackedPMRpsPMRPtrIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(PMR_MAX_SUPPORTED_PAGE_COUNT <= IMG_UINT32_MAX,
+             "PMR_MAX_SUPPORTED_PAGE_COUNT must not be larger than IMG_UINT32_MAX");
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
                                   IMG_UINT8 * psPhysmemNewRamBackedPMRIN_UI8,
@@ -811,9 +822,10 @@ PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
-           (psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psPhysmemNewRamBackedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psPhysmemNewRamBackedPMRIN->ui32NumPhysChunks > PMR_MAX_SUPPORTED_PAGE_COUNT))
        {
@@ -827,6 +839,14 @@ PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
                goto PhysmemNewRamBackedPMR_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysmemNewRamBackedPMROUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysmemNewRamBackedPMR_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -847,7 +867,7 @@ PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -916,7 +936,9 @@ PVRSRVBridgePhysmemNewRamBackedPMR(IMG_UINT32 ui32DispatchTableEntry,
                                   psPhysmemNewRamBackedPMRIN->ui32AnnotationLength,
                                   uiAnnotationInt,
                                   psPhysmemNewRamBackedPMRIN->ui32PID,
-                                  &psPMRPtrInt, psPhysmemNewRamBackedPMRIN->ui32PDumpFlags);
+                                  &psPMRPtrInt,
+                                  psPhysmemNewRamBackedPMRIN->ui32PDumpFlags,
+                                  &psPhysmemNewRamBackedPMROUT->uiOutFlags);
        /* Exit early if bridged call fails */
        if (unlikely(psPhysmemNewRamBackedPMROUT->eError != PVRSRV_OK))
        {
@@ -956,7 +978,10 @@ PhysmemNewRamBackedPMR_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysmemNewRamBackedPMROUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -975,6 +1000,11 @@ static PVRSRV_ERROR _PhysmemNewRamBackedLockedPMRpsPMRPtrIntRelease(void *pvData
        return eError;
 }
 
+static_assert(PMR_MAX_SUPPORTED_PAGE_COUNT <= IMG_UINT32_MAX,
+             "PMR_MAX_SUPPORTED_PAGE_COUNT must not be larger than IMG_UINT32_MAX");
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
                                         IMG_UINT8 * psPhysmemNewRamBackedLockedPMRIN_UI8,
@@ -998,9 +1028,12 @@ PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks * sizeof(IMG_UINT32)) +
-           (psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks *
+            sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psPhysmemNewRamBackedLockedPMRIN->ui32AnnotationLength *
+            sizeof(IMG_CHAR)) + 0;
 
        if (unlikely
            (psPhysmemNewRamBackedLockedPMRIN->ui32NumVirtChunks > PMR_MAX_SUPPORTED_PAGE_COUNT))
@@ -1016,6 +1049,14 @@ PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
                goto PhysmemNewRamBackedLockedPMR_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysmemNewRamBackedLockedPMROUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysmemNewRamBackedLockedPMR_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -1037,7 +1078,7 @@ PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -1108,7 +1149,8 @@ PVRSRVBridgePhysmemNewRamBackedLockedPMR(IMG_UINT32 ui32DispatchTableEntry,
                                         uiAnnotationInt,
                                         psPhysmemNewRamBackedLockedPMRIN->ui32PID,
                                         &psPMRPtrInt,
-                                        psPhysmemNewRamBackedLockedPMRIN->ui32PDumpFlags);
+                                        psPhysmemNewRamBackedLockedPMRIN->ui32PDumpFlags,
+                                        &psPhysmemNewRamBackedLockedPMROUT->uiOutFlags);
        /* Exit early if bridged call fails */
        if (unlikely(psPhysmemNewRamBackedLockedPMROUT->eError != PVRSRV_OK))
        {
@@ -1147,7 +1189,10 @@ PhysmemNewRamBackedLockedPMR_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysmemNewRamBackedLockedPMROUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -1478,7 +1523,7 @@ DevmemIntCtxCreate_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(psConnection->psHandleBase);
 
-                       eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+                       eError = PVRSRVDestroyHandleUnlocked(psConnection->psHandleBase,
                                                             (IMG_HANDLE) psDevmemIntCtxCreateOUT->
                                                             hDevMemServerContext,
                                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
@@ -1524,11 +1569,13 @@ PVRSRVBridgeDevmemIntCtxDestroy(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDevmemIntCtxDestroyOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDevmemIntCtxDestroyIN->
-                                           hDevmemServerContext, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDevmemIntCtxDestroyIN->
+                                             hDevmemServerContext,
+                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
        if (unlikely
            ((psDevmemIntCtxDestroyOUT->eError != PVRSRV_OK)
+            && (psDevmemIntCtxDestroyOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psDevmemIntCtxDestroyOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1659,10 +1706,11 @@ PVRSRVBridgeDevmemIntHeapDestroy(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDevmemIntHeapDestroyOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDevmemIntHeapDestroyIN->hDevmemHeap,
-                                           PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDevmemIntHeapDestroyIN->hDevmemHeap,
+                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_HEAP);
        if (unlikely((psDevmemIntHeapDestroyOUT->eError != PVRSRV_OK) &&
+                    (psDevmemIntHeapDestroyOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psDevmemIntHeapDestroyOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1828,10 +1876,11 @@ PVRSRVBridgeDevmemIntUnmapPMR(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDevmemIntUnmapPMROUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDevmemIntUnmapPMRIN->hMapping,
-                                           PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDevmemIntUnmapPMRIN->hMapping,
+                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_MAPPING);
        if (unlikely((psDevmemIntUnmapPMROUT->eError != PVRSRV_OK) &&
+                    (psDevmemIntUnmapPMROUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psDevmemIntUnmapPMROUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1961,11 +2010,14 @@ PVRSRVBridgeDevmemIntUnreserveRange(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psDevmemIntUnreserveRangeOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psDevmemIntUnreserveRangeIN->hReservation,
-                                           PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
-       if (unlikely((psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK) &&
-                    (psDevmemIntUnreserveRangeOUT->eError != PVRSRV_ERROR_RETRY)))
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psDevmemIntUnreserveRangeIN->
+                                             hReservation,
+                                             PVRSRV_HANDLE_TYPE_DEVMEMINT_RESERVATION);
+       if (unlikely
+           ((psDevmemIntUnreserveRangeOUT->eError != PVRSRV_OK)
+            && (psDevmemIntUnreserveRangeOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+            && (psDevmemIntUnreserveRangeOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: %s",
@@ -1982,6 +2034,11 @@ DevmemIntUnreserveRange_exit:
        return 0;
 }
 
+static_assert(PMR_MAX_SUPPORTED_PAGE_COUNT <= IMG_UINT32_MAX,
+             "PMR_MAX_SUPPORTED_PAGE_COUNT must not be larger than IMG_UINT32_MAX");
+static_assert(PMR_MAX_SUPPORTED_PAGE_COUNT <= IMG_UINT32_MAX,
+             "PMR_MAX_SUPPORTED_PAGE_COUNT must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeChangeSparseMem(IMG_UINT32 ui32DispatchTableEntry,
                            IMG_UINT8 * psChangeSparseMemIN_UI8,
@@ -2005,9 +2062,10 @@ PVRSRVBridgeChangeSparseMem(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32)) +
-           (psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psChangeSparseMemIN->ui32AllocPageCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psChangeSparseMemIN->ui32FreePageCount * sizeof(IMG_UINT32)) + 0;
 
        if (unlikely(psChangeSparseMemIN->ui32AllocPageCount > PMR_MAX_SUPPORTED_PAGE_COUNT))
        {
@@ -2021,6 +2079,14 @@ PVRSRVBridgeChangeSparseMem(IMG_UINT32 ui32DispatchTableEntry,
                goto ChangeSparseMem_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psChangeSparseMemOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto ChangeSparseMem_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -2041,7 +2107,7 @@ PVRSRVBridgeChangeSparseMem(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -2153,7 +2219,10 @@ ChangeSparseMem_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psChangeSparseMemOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -2529,8 +2598,10 @@ PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz * sizeof(IMG_CHAR)) +
+           0;
 
        if (psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz > DEVMEM_HEAPNAME_MAXLENGTH)
        {
@@ -2541,6 +2612,14 @@ PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
        psHeapCfgHeapConfigNameOUT->puiHeapConfigName =
            psHeapCfgHeapConfigNameIN->puiHeapConfigName;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psHeapCfgHeapConfigNameOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto HeapCfgHeapConfigName_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -2561,7 +2640,7 @@ PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -2584,6 +2663,11 @@ PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
                                  psHeapCfgHeapConfigNameIN->ui32HeapConfigIndex,
                                  psHeapCfgHeapConfigNameIN->ui32HeapConfigNameBufSz,
                                  puiHeapConfigNameInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psHeapCfgHeapConfigNameOUT->eError != PVRSRV_OK))
+       {
+               goto HeapCfgHeapConfigName_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((puiHeapConfigNameInt) &&
@@ -2605,7 +2689,10 @@ PVRSRVBridgeHeapCfgHeapConfigName(IMG_UINT32 ui32DispatchTableEntry,
 HeapCfgHeapConfigName_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psHeapCfgHeapConfigNameOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -2637,8 +2724,9 @@ PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psHeapCfgHeapDetailsIN->ui32HeapNameBufSz * sizeof(IMG_CHAR)) + 0;
 
        if (psHeapCfgHeapDetailsIN->ui32HeapNameBufSz > DEVMEM_HEAPNAME_MAXLENGTH)
        {
@@ -2648,6 +2736,14 @@ PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
 
        psHeapCfgHeapDetailsOUT->puiHeapNameOut = psHeapCfgHeapDetailsIN->puiHeapNameOut;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psHeapCfgHeapDetailsOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto HeapCfgHeapDetails_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -2668,7 +2764,7 @@ PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -2695,6 +2791,11 @@ PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
                               &psHeapCfgHeapDetailsOUT->uiReservedRegionLength,
                               &psHeapCfgHeapDetailsOUT->ui32Log2DataPageSizeOut,
                               &psHeapCfgHeapDetailsOUT->ui32Log2ImportAlignmentOut);
+       /* Exit early if bridged call fails */
+       if (unlikely(psHeapCfgHeapDetailsOUT->eError != PVRSRV_OK))
+       {
+               goto HeapCfgHeapDetails_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((puiHeapNameOutInt) &&
@@ -2715,7 +2816,10 @@ PVRSRVBridgeHeapCfgHeapDetails(IMG_UINT32 ui32DispatchTableEntry,
 HeapCfgHeapDetails_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psHeapCfgHeapDetailsOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -2740,8 +2844,8 @@ PVRSRVBridgeDevmemIntRegisterPFNotifyKM(IMG_UINT32 ui32DispatchTableEntry,
            (PVRSRV_BRIDGE_OUT_DEVMEMINTREGISTERPFNOTIFYKM *)
            IMG_OFFSET_ADDR(psDevmemIntRegisterPFNotifyKMOUT_UI8, 0);
 
-       IMG_HANDLE hDevmemCtx = psDevmemIntRegisterPFNotifyKMIN->hDevmemCtx;
-       DEVMEMINT_CTX *psDevmemCtxInt = NULL;
+       IMG_HANDLE hDevm = psDevmemIntRegisterPFNotifyKMIN->hDevm;
+       DEVMEMINT_CTX *psDevmInt = NULL;
 
        /* Lock over handle lookup. */
        LockHandle(psConnection->psHandleBase);
@@ -2749,8 +2853,8 @@ PVRSRVBridgeDevmemIntRegisterPFNotifyKM(IMG_UINT32 ui32DispatchTableEntry,
        /* Look up the address from the handle */
        psDevmemIntRegisterPFNotifyKMOUT->eError =
            PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
-                                      (void **)&psDevmemCtxInt,
-                                      hDevmemCtx, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX, IMG_TRUE);
+                                      (void **)&psDevmInt,
+                                      hDevm, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX, IMG_TRUE);
        if (unlikely(psDevmemIntRegisterPFNotifyKMOUT->eError != PVRSRV_OK))
        {
                UnlockHandle(psConnection->psHandleBase);
@@ -2760,7 +2864,7 @@ PVRSRVBridgeDevmemIntRegisterPFNotifyKM(IMG_UINT32 ui32DispatchTableEntry,
        UnlockHandle(psConnection->psHandleBase);
 
        psDevmemIntRegisterPFNotifyKMOUT->eError =
-           DevmemIntRegisterPFNotifyKM(psDevmemCtxInt,
+           DevmemIntRegisterPFNotifyKM(psDevmInt,
                                        psDevmemIntRegisterPFNotifyKMIN->ui32PID,
                                        psDevmemIntRegisterPFNotifyKMIN->bRegister);
 
@@ -2770,10 +2874,10 @@ DevmemIntRegisterPFNotifyKM_exit:
        LockHandle(psConnection->psHandleBase);
 
        /* Unreference the previously looked up handle */
-       if (psDevmemCtxInt)
+       if (psDevmInt)
        {
                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
-                                           hDevmemCtx, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
+                                           hDevm, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
        }
        /* Release now we have cleaned up look up handles. */
        UnlockHandle(psConnection->psHandleBase);
@@ -2782,21 +2886,323 @@ DevmemIntRegisterPFNotifyKM_exit:
 }
 
 static IMG_INT
-PVRSRVBridgeGetMaxDevMemSize(IMG_UINT32 ui32DispatchTableEntry,
-                            IMG_UINT8 * psGetMaxDevMemSizeIN_UI8,
-                            IMG_UINT8 * psGetMaxDevMemSizeOUT_UI8, CONNECTION_DATA * psConnection)
+PVRSRVBridgeGetMaxPhysHeapCount(IMG_UINT32 ui32DispatchTableEntry,
+                               IMG_UINT8 * psGetMaxPhysHeapCountIN_UI8,
+                               IMG_UINT8 * psGetMaxPhysHeapCountOUT_UI8,
+                               CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_GETMAXPHYSHEAPCOUNT *psGetMaxPhysHeapCountIN =
+           (PVRSRV_BRIDGE_IN_GETMAXPHYSHEAPCOUNT *) IMG_OFFSET_ADDR(psGetMaxPhysHeapCountIN_UI8,
+                                                                    0);
+       PVRSRV_BRIDGE_OUT_GETMAXPHYSHEAPCOUNT *psGetMaxPhysHeapCountOUT =
+           (PVRSRV_BRIDGE_OUT_GETMAXPHYSHEAPCOUNT *) IMG_OFFSET_ADDR(psGetMaxPhysHeapCountOUT_UI8,
+                                                                     0);
+
+       PVR_UNREFERENCED_PARAMETER(psGetMaxPhysHeapCountIN);
+
+       psGetMaxPhysHeapCountOUT->eError =
+           PVRSRVGetMaxPhysHeapCountKM(psConnection, OSGetDevNode(psConnection),
+                                       &psGetMaxPhysHeapCountOUT->ui32PhysHeapCount);
+
+       return 0;
+}
+
+static_assert(PVRSRV_PHYS_HEAP_LAST <= IMG_UINT32_MAX,
+             "PVRSRV_PHYS_HEAP_LAST must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgePhysHeapGetMemInfo(IMG_UINT32 ui32DispatchTableEntry,
+                              IMG_UINT8 * psPhysHeapGetMemInfoIN_UI8,
+                              IMG_UINT8 * psPhysHeapGetMemInfoOUT_UI8,
+                              CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFO *psPhysHeapGetMemInfoIN =
+           (PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFO *) IMG_OFFSET_ADDR(psPhysHeapGetMemInfoIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFO *psPhysHeapGetMemInfoOUT =
+           (PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFO *) IMG_OFFSET_ADDR(psPhysHeapGetMemInfoOUT_UI8,
+                                                                    0);
+
+       PVRSRV_PHYS_HEAP *eaPhysHeapIDInt = NULL;
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStatsInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP)) +
+           ((IMG_UINT64) psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS)) +
+           0;
+
+       if (unlikely(psPhysHeapGetMemInfoIN->ui32PhysHeapCount > PVRSRV_PHYS_HEAP_LAST))
+       {
+               psPhysHeapGetMemInfoOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto PhysHeapGetMemInfo_exit;
+       }
+
+       psPhysHeapGetMemInfoOUT->pasapPhysHeapMemStats =
+           psPhysHeapGetMemInfoIN->pasapPhysHeapMemStats;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysHeapGetMemInfoOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysHeapGetMemInfo_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psPhysHeapGetMemInfoIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psPhysHeapGetMemInfoIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psPhysHeapGetMemInfoOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto PhysHeapGetMemInfo_exit;
+                       }
+               }
+       }
+
+       if (psPhysHeapGetMemInfoIN->ui32PhysHeapCount != 0)
+       {
+               eaPhysHeapIDInt =
+                   (PVRSRV_PHYS_HEAP *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP);
+       }
+
+       /* Copy the data over */
+       if (psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, eaPhysHeapIDInt,
+                    (const void __user *)psPhysHeapGetMemInfoIN->peaPhysHeapID,
+                    psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP)) !=
+                   PVRSRV_OK)
+               {
+                       psPhysHeapGetMemInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto PhysHeapGetMemInfo_exit;
+               }
+       }
+       if (psPhysHeapGetMemInfoIN->ui32PhysHeapCount != 0)
+       {
+               pasapPhysHeapMemStatsInt =
+                   (PHYS_HEAP_MEM_STATS *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS);
+       }
+
+       psPhysHeapGetMemInfoOUT->eError =
+           PVRSRVPhysHeapGetMemInfoKM(psConnection, OSGetDevNode(psConnection),
+                                      psPhysHeapGetMemInfoIN->ui32PhysHeapCount,
+                                      eaPhysHeapIDInt, pasapPhysHeapMemStatsInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psPhysHeapGetMemInfoOUT->eError != PVRSRV_OK))
+       {
+               goto PhysHeapGetMemInfo_exit;
+       }
+
+       /* If dest ptr is non-null and we have data to copy */
+       if ((pasapPhysHeapMemStatsInt) &&
+           ((psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS)) > 0))
+       {
+               if (unlikely
+                   (OSCopyToUser
+                    (NULL, (void __user *)psPhysHeapGetMemInfoOUT->pasapPhysHeapMemStats,
+                     pasapPhysHeapMemStatsInt,
+                     (psPhysHeapGetMemInfoIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS))) !=
+                    PVRSRV_OK))
+               {
+                       psPhysHeapGetMemInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto PhysHeapGetMemInfo_exit;
+               }
+       }
+
+PhysHeapGetMemInfo_exit:
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysHeapGetMemInfoOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeGetDefaultPhysicalHeap(IMG_UINT32 ui32DispatchTableEntry,
+                                  IMG_UINT8 * psGetDefaultPhysicalHeapIN_UI8,
+                                  IMG_UINT8 * psGetDefaultPhysicalHeapOUT_UI8,
+                                  CONNECTION_DATA * psConnection)
 {
-       PVRSRV_BRIDGE_IN_GETMAXDEVMEMSIZE *psGetMaxDevMemSizeIN =
-           (PVRSRV_BRIDGE_IN_GETMAXDEVMEMSIZE *) IMG_OFFSET_ADDR(psGetMaxDevMemSizeIN_UI8, 0);
-       PVRSRV_BRIDGE_OUT_GETMAXDEVMEMSIZE *psGetMaxDevMemSizeOUT =
-           (PVRSRV_BRIDGE_OUT_GETMAXDEVMEMSIZE *) IMG_OFFSET_ADDR(psGetMaxDevMemSizeOUT_UI8, 0);
+       PVRSRV_BRIDGE_IN_GETDEFAULTPHYSICALHEAP *psGetDefaultPhysicalHeapIN =
+           (PVRSRV_BRIDGE_IN_GETDEFAULTPHYSICALHEAP *)
+           IMG_OFFSET_ADDR(psGetDefaultPhysicalHeapIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_GETDEFAULTPHYSICALHEAP *psGetDefaultPhysicalHeapOUT =
+           (PVRSRV_BRIDGE_OUT_GETDEFAULTPHYSICALHEAP *)
+           IMG_OFFSET_ADDR(psGetDefaultPhysicalHeapOUT_UI8, 0);
+
+       PVR_UNREFERENCED_PARAMETER(psGetDefaultPhysicalHeapIN);
+
+       psGetDefaultPhysicalHeapOUT->eError =
+           PVRSRVGetDefaultPhysicalHeapKM(psConnection, OSGetDevNode(psConnection),
+                                          &psGetDefaultPhysicalHeapOUT->eHeap);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeGetHeapPhysMemUsage(IMG_UINT32 ui32DispatchTableEntry,
+                               IMG_UINT8 * psGetHeapPhysMemUsageIN_UI8,
+                               IMG_UINT8 * psGetHeapPhysMemUsageOUT_UI8,
+                               CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGE *psGetHeapPhysMemUsageIN =
+           (PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGE *) IMG_OFFSET_ADDR(psGetHeapPhysMemUsageIN_UI8,
+                                                                    0);
+       PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGE *psGetHeapPhysMemUsageOUT =
+           (PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGE *) IMG_OFFSET_ADDR(psGetHeapPhysMemUsageOUT_UI8,
+                                                                     0);
+
+       PHYS_HEAP_MEM_STATS *pasapPhysHeapMemStatsInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psGetHeapPhysMemUsageIN->ui32PhysHeapCount *
+            sizeof(PHYS_HEAP_MEM_STATS)) + 0;
+
+       if (psGetHeapPhysMemUsageIN->ui32PhysHeapCount > PVRSRV_PHYS_HEAP_LAST)
+       {
+               psGetHeapPhysMemUsageOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto GetHeapPhysMemUsage_exit;
+       }
+
+       psGetHeapPhysMemUsageOUT->pasapPhysHeapMemStats =
+           psGetHeapPhysMemUsageIN->pasapPhysHeapMemStats;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psGetHeapPhysMemUsageOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto GetHeapPhysMemUsage_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psGetHeapPhysMemUsageIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psGetHeapPhysMemUsageIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psGetHeapPhysMemUsageOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto GetHeapPhysMemUsage_exit;
+                       }
+               }
+       }
+
+       if (psGetHeapPhysMemUsageIN->ui32PhysHeapCount != 0)
+       {
+               pasapPhysHeapMemStatsInt =
+                   (PHYS_HEAP_MEM_STATS *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psGetHeapPhysMemUsageIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS);
+       }
 
-       PVR_UNREFERENCED_PARAMETER(psGetMaxDevMemSizeIN);
+       psGetHeapPhysMemUsageOUT->eError =
+           PVRSRVGetHeapPhysMemUsageKM(psConnection, OSGetDevNode(psConnection),
+                                       psGetHeapPhysMemUsageIN->ui32PhysHeapCount,
+                                       pasapPhysHeapMemStatsInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psGetHeapPhysMemUsageOUT->eError != PVRSRV_OK))
+       {
+               goto GetHeapPhysMemUsage_exit;
+       }
 
-       psGetMaxDevMemSizeOUT->eError =
-           PVRSRVGetMaxDevMemSizeKM(psConnection, OSGetDevNode(psConnection),
-                                    &psGetMaxDevMemSizeOUT->uiLMASize,
-                                    &psGetMaxDevMemSizeOUT->uiUMASize);
+       /* If dest ptr is non-null and we have data to copy */
+       if ((pasapPhysHeapMemStatsInt) &&
+           ((psGetHeapPhysMemUsageIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS)) > 0))
+       {
+               if (unlikely
+                   (OSCopyToUser
+                    (NULL, (void __user *)psGetHeapPhysMemUsageOUT->pasapPhysHeapMemStats,
+                     pasapPhysHeapMemStatsInt,
+                     (psGetHeapPhysMemUsageIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS))) !=
+                    PVRSRV_OK))
+               {
+                       psGetHeapPhysMemUsageOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto GetHeapPhysMemUsage_exit;
+               }
+       }
+
+GetHeapPhysMemUsage_exit:
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psGetHeapPhysMemUsageOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
 
        return 0;
 }
@@ -2882,12 +3288,291 @@ PVRSRVBridgePVRSRVUpdateOOMStats(IMG_UINT32 ui32DispatchTableEntry,
 #define PVRSRVBridgePVRSRVUpdateOOMStats NULL
 #endif
 
+static_assert(PVRSRV_PHYS_HEAP_LAST <= IMG_UINT32_MAX,
+             "PVRSRV_PHYS_HEAP_LAST must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgePhysHeapGetMemInfoPkd(IMG_UINT32 ui32DispatchTableEntry,
+                                 IMG_UINT8 * psPhysHeapGetMemInfoPkdIN_UI8,
+                                 IMG_UINT8 * psPhysHeapGetMemInfoPkdOUT_UI8,
+                                 CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFOPKD *psPhysHeapGetMemInfoPkdIN =
+           (PVRSRV_BRIDGE_IN_PHYSHEAPGETMEMINFOPKD *)
+           IMG_OFFSET_ADDR(psPhysHeapGetMemInfoPkdIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFOPKD *psPhysHeapGetMemInfoPkdOUT =
+           (PVRSRV_BRIDGE_OUT_PHYSHEAPGETMEMINFOPKD *)
+           IMG_OFFSET_ADDR(psPhysHeapGetMemInfoPkdOUT_UI8, 0);
+
+       PVRSRV_PHYS_HEAP *eaPhysHeapIDInt = NULL;
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStatsInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP)) +
+           ((IMG_UINT64) psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount *
+            sizeof(PHYS_HEAP_MEM_STATS_PKD)) + 0;
+
+       if (unlikely(psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount > PVRSRV_PHYS_HEAP_LAST))
+       {
+               psPhysHeapGetMemInfoPkdOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto PhysHeapGetMemInfoPkd_exit;
+       }
+
+       psPhysHeapGetMemInfoPkdOUT->psapPhysHeapMemStats =
+           psPhysHeapGetMemInfoPkdIN->psapPhysHeapMemStats;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPhysHeapGetMemInfoPkdOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PhysHeapGetMemInfoPkd_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psPhysHeapGetMemInfoPkdIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psPhysHeapGetMemInfoPkdIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psPhysHeapGetMemInfoPkdOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto PhysHeapGetMemInfoPkd_exit;
+                       }
+               }
+       }
+
+       if (psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount != 0)
+       {
+               eaPhysHeapIDInt =
+                   (PVRSRV_PHYS_HEAP *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP);
+       }
+
+       /* Copy the data over */
+       if (psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, eaPhysHeapIDInt,
+                    (const void __user *)psPhysHeapGetMemInfoPkdIN->peaPhysHeapID,
+                    psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PVRSRV_PHYS_HEAP)) !=
+                   PVRSRV_OK)
+               {
+                       psPhysHeapGetMemInfoPkdOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto PhysHeapGetMemInfoPkd_exit;
+               }
+       }
+       if (psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount != 0)
+       {
+               psapPhysHeapMemStatsInt =
+                   (PHYS_HEAP_MEM_STATS_PKD *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS_PKD);
+       }
+
+       psPhysHeapGetMemInfoPkdOUT->eError =
+           PVRSRVPhysHeapGetMemInfoPkdKM(psConnection, OSGetDevNode(psConnection),
+                                         psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount,
+                                         eaPhysHeapIDInt, psapPhysHeapMemStatsInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psPhysHeapGetMemInfoPkdOUT->eError != PVRSRV_OK))
+       {
+               goto PhysHeapGetMemInfoPkd_exit;
+       }
+
+       /* If dest ptr is non-null and we have data to copy */
+       if ((psapPhysHeapMemStatsInt) &&
+           ((psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS_PKD)) > 0))
+       {
+               if (unlikely
+                   (OSCopyToUser
+                    (NULL, (void __user *)psPhysHeapGetMemInfoPkdOUT->psapPhysHeapMemStats,
+                     psapPhysHeapMemStatsInt,
+                     (psPhysHeapGetMemInfoPkdIN->ui32PhysHeapCount *
+                      sizeof(PHYS_HEAP_MEM_STATS_PKD))) != PVRSRV_OK))
+               {
+                       psPhysHeapGetMemInfoPkdOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto PhysHeapGetMemInfoPkd_exit;
+               }
+       }
+
+PhysHeapGetMemInfoPkd_exit:
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPhysHeapGetMemInfoPkdOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeGetHeapPhysMemUsagePkd(IMG_UINT32 ui32DispatchTableEntry,
+                                  IMG_UINT8 * psGetHeapPhysMemUsagePkdIN_UI8,
+                                  IMG_UINT8 * psGetHeapPhysMemUsagePkdOUT_UI8,
+                                  CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGEPKD *psGetHeapPhysMemUsagePkdIN =
+           (PVRSRV_BRIDGE_IN_GETHEAPPHYSMEMUSAGEPKD *)
+           IMG_OFFSET_ADDR(psGetHeapPhysMemUsagePkdIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGEPKD *psGetHeapPhysMemUsagePkdOUT =
+           (PVRSRV_BRIDGE_OUT_GETHEAPPHYSMEMUSAGEPKD *)
+           IMG_OFFSET_ADDR(psGetHeapPhysMemUsagePkdOUT_UI8, 0);
+
+       PHYS_HEAP_MEM_STATS_PKD *psapPhysHeapMemStatsInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount *
+            sizeof(PHYS_HEAP_MEM_STATS_PKD)) + 0;
+
+       if (psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount > PVRSRV_PHYS_HEAP_LAST)
+       {
+               psGetHeapPhysMemUsagePkdOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto GetHeapPhysMemUsagePkd_exit;
+       }
+
+       psGetHeapPhysMemUsagePkdOUT->psapPhysHeapMemStats =
+           psGetHeapPhysMemUsagePkdIN->psapPhysHeapMemStats;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psGetHeapPhysMemUsagePkdOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto GetHeapPhysMemUsagePkd_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psGetHeapPhysMemUsagePkdIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psGetHeapPhysMemUsagePkdIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psGetHeapPhysMemUsagePkdOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto GetHeapPhysMemUsagePkd_exit;
+                       }
+               }
+       }
+
+       if (psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount != 0)
+       {
+               psapPhysHeapMemStatsInt =
+                   (PHYS_HEAP_MEM_STATS_PKD *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS_PKD);
+       }
+
+       psGetHeapPhysMemUsagePkdOUT->eError =
+           PVRSRVGetHeapPhysMemUsagePkdKM(psConnection, OSGetDevNode(psConnection),
+                                          psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount,
+                                          psapPhysHeapMemStatsInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psGetHeapPhysMemUsagePkdOUT->eError != PVRSRV_OK))
+       {
+               goto GetHeapPhysMemUsagePkd_exit;
+       }
+
+       /* If dest ptr is non-null and we have data to copy */
+       if ((psapPhysHeapMemStatsInt) &&
+           ((psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount * sizeof(PHYS_HEAP_MEM_STATS_PKD)) > 0))
+       {
+               if (unlikely
+                   (OSCopyToUser
+                    (NULL, (void __user *)psGetHeapPhysMemUsagePkdOUT->psapPhysHeapMemStats,
+                     psapPhysHeapMemStatsInt,
+                     (psGetHeapPhysMemUsagePkdIN->ui32PhysHeapCount *
+                      sizeof(PHYS_HEAP_MEM_STATS_PKD))) != PVRSRV_OK))
+               {
+                       psGetHeapPhysMemUsagePkdOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto GetHeapPhysMemUsagePkd_exit;
+               }
+       }
+
+GetHeapPhysMemUsagePkd_exit:
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psGetHeapPhysMemUsagePkdOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
 /* ***************************************************************************
  * Server bridge dispatch related glue
  */
 
 PVRSRV_ERROR InitMMBridge(void);
-PVRSRV_ERROR DeinitMMBridge(void);
+void DeinitMMBridge(void);
 
 /*
  * Register all MM functions with services
@@ -2997,8 +3682,17 @@ PVRSRV_ERROR InitMMBridge(void)
        SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMINTREGISTERPFNOTIFYKM,
                              PVRSRVBridgeDevmemIntRegisterPFNotifyKM, NULL);
 
-       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETMAXDEVMEMSIZE,
-                             PVRSRVBridgeGetMaxDevMemSize, NULL);
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETMAXPHYSHEAPCOUNT,
+                             PVRSRVBridgeGetMaxPhysHeapCount, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFO,
+                             PVRSRVBridgePhysHeapGetMemInfo, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETDEFAULTPHYSICALHEAP,
+                             PVRSRVBridgeGetDefaultPhysicalHeap, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGE,
+                             PVRSRVBridgeGetHeapPhysMemUsage, NULL);
 
        SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMGETFAULTADDRESS,
                              PVRSRVBridgeDevmemGetFaultAddress, NULL);
@@ -3006,13 +3700,19 @@ PVRSRV_ERROR InitMMBridge(void)
        SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PVRSRVUPDATEOOMSTATS,
                              PVRSRVBridgePVRSRVUpdateOOMStats, NULL);
 
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFOPKD,
+                             PVRSRVBridgePhysHeapGetMemInfoPkd, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGEPKD,
+                             PVRSRVBridgeGetHeapPhysMemUsagePkd, NULL);
+
        return PVRSRV_OK;
 }
 
 /*
  * Unregister all mm functions with services
  */
-PVRSRV_ERROR DeinitMMBridge(void)
+void DeinitMMBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PMREXPORTPMR);
@@ -3083,11 +3783,20 @@ PVRSRV_ERROR DeinitMMBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMINTREGISTERPFNOTIFYKM);
 
-       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETMAXDEVMEMSIZE);
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETMAXPHYSHEAPCOUNT);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFO);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETDEFAULTPHYSICALHEAP);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGE);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_DEVMEMGETFAULTADDRESS);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PVRSRVUPDATEOOMSTATS);
 
-       return PVRSRV_OK;
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_PHYSHEAPGETMEMINFOPKD);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_MM, PVRSRV_BRIDGE_MM_GETHEAPPHYSMEMUSAGEPKD);
+
 }
index 825bd13..2bf967b 100644 (file)
@@ -54,19 +54,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "common_pdump_bridge.h"
 
-IMG_INTERNAL PVRSRV_ERROR BridgeDevmemPDumpBitmap(IMG_HANDLE hBridge,
-                                                 IMG_CHAR * puiFileName,
-                                                 IMG_UINT32 ui32FileOffset,
-                                                 IMG_UINT32 ui32Width,
-                                                 IMG_UINT32 ui32Height,
-                                                 IMG_UINT32 ui32StrideInBytes,
-                                                 IMG_DEV_VIRTADDR sDevBaseAddr,
-                                                 IMG_HANDLE hDevmemCtx,
-                                                 IMG_UINT32 ui32Size,
-                                                 PDUMP_PIXEL_FORMAT ePixelFormat,
-                                                 IMG_UINT32 ui32AddrMode,
-                                                 IMG_UINT32 ui32PDumpFlags);
-
 IMG_INTERNAL PVRSRV_ERROR BridgePDumpImageDescriptor(IMG_HANDLE hBridge,
                                                     IMG_HANDLE hDevmemCtx,
                                                     IMG_UINT32 ui32StringSize,
@@ -87,6 +74,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgePDumpImageDescriptor(IMG_HANDLE hBridge,
                                                     IMG_UINT32 ui32PDumpFlags);
 
 IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpComment(IMG_HANDLE hBridge,
+                                                  IMG_UINT32 ui32CommentSize,
                                                   IMG_CHAR * puiComment, IMG_UINT32 ui32Flags);
 
 IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpSetFrame(IMG_HANDLE hBridge, IMG_UINT32 ui32Frame);
index 8336cc5..7c012db 100644 (file)
@@ -54,38 +54,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "devicemem_server.h"
 #include "pdump_km.h"
 
-IMG_INTERNAL PVRSRV_ERROR BridgeDevmemPDumpBitmap(IMG_HANDLE hBridge,
-                                                 IMG_CHAR * puiFileName,
-                                                 IMG_UINT32 ui32FileOffset,
-                                                 IMG_UINT32 ui32Width,
-                                                 IMG_UINT32 ui32Height,
-                                                 IMG_UINT32 ui32StrideInBytes,
-                                                 IMG_DEV_VIRTADDR sDevBaseAddr,
-                                                 IMG_HANDLE hDevmemCtx,
-                                                 IMG_UINT32 ui32Size,
-                                                 PDUMP_PIXEL_FORMAT ePixelFormat,
-                                                 IMG_UINT32 ui32AddrMode,
-                                                 IMG_UINT32 ui32PDumpFlags)
-{
-       PVRSRV_ERROR eError;
-       DEVMEMINT_CTX *psDevmemCtxInt;
-
-       psDevmemCtxInt = (DEVMEMINT_CTX *) hDevmemCtx;
-
-       eError =
-           DevmemIntPDumpBitmap(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
-                                puiFileName,
-                                ui32FileOffset,
-                                ui32Width,
-                                ui32Height,
-                                ui32StrideInBytes,
-                                sDevBaseAddr,
-                                psDevmemCtxInt,
-                                ui32Size, ePixelFormat, ui32AddrMode, ui32PDumpFlags);
-
-       return eError;
-}
-
 IMG_INTERNAL PVRSRV_ERROR BridgePDumpImageDescriptor(IMG_HANDLE hBridge,
                                                     IMG_HANDLE hDevmemCtx,
                                                     IMG_UINT32 ui32StringSize,
@@ -132,12 +100,14 @@ IMG_INTERNAL PVRSRV_ERROR BridgePDumpImageDescriptor(IMG_HANDLE hBridge,
 }
 
 IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpComment(IMG_HANDLE hBridge,
+                                                  IMG_UINT32 ui32CommentSize,
                                                   IMG_CHAR * puiComment, IMG_UINT32 ui32Flags)
 {
        PVRSRV_ERROR eError;
-       PVR_UNREFERENCED_PARAMETER(hBridge);
 
-       eError = PDumpCommentKM(puiComment, ui32Flags);
+       eError =
+           PDumpCommentKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                          ui32CommentSize, puiComment, ui32Flags);
 
        return eError;
 }
index a647cce..eb6ab94 100644 (file)
@@ -56,38 +56,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <powervr/buffer_attribs.h>
 
 #define PVRSRV_BRIDGE_PDUMP_CMD_FIRST                  0
-#define PVRSRV_BRIDGE_PDUMP_DEVMEMPDUMPBITMAP                  PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0
-#define PVRSRV_BRIDGE_PDUMP_PDUMPIMAGEDESCRIPTOR                       PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1
-#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT                 PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2
-#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETFRAME                        PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3
-#define PVRSRV_BRIDGE_PDUMP_PDUMPDATADESCRIPTOR                        PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4
-#define PVRSRV_BRIDGE_PDUMP_CMD_LAST                   (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
-
-/*******************************************
-            DevmemPDumpBitmap
- *******************************************/
-
-/* Bridge in structure for DevmemPDumpBitmap */
-typedef struct PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP_TAG
-{
-       IMG_DEV_VIRTADDR sDevBaseAddr;
-       IMG_HANDLE hDevmemCtx;
-       IMG_CHAR *puiFileName;
-       PDUMP_PIXEL_FORMAT ePixelFormat;
-       IMG_UINT32 ui32AddrMode;
-       IMG_UINT32 ui32FileOffset;
-       IMG_UINT32 ui32Height;
-       IMG_UINT32 ui32PDumpFlags;
-       IMG_UINT32 ui32Size;
-       IMG_UINT32 ui32StrideInBytes;
-       IMG_UINT32 ui32Width;
-} __packed PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP;
-
-/* Bridge out structure for DevmemPDumpBitmap */
-typedef struct PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP_TAG
-{
-       PVRSRV_ERROR eError;
-} __packed PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP;
+#define PVRSRV_BRIDGE_PDUMP_PDUMPIMAGEDESCRIPTOR                       PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT                 PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1
+#define PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPSETFRAME                        PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2
+#define PVRSRV_BRIDGE_PDUMP_PDUMPDATADESCRIPTOR                        PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST                   (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
 
 /*******************************************
             PDumpImageDescriptor
@@ -129,6 +102,7 @@ typedef struct PVRSRV_BRIDGE_OUT_PDUMPIMAGEDESCRIPTOR_TAG
 typedef struct PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT_TAG
 {
        IMG_CHAR *puiComment;
+       IMG_UINT32 ui32CommentSize;
        IMG_UINT32 ui32Flags;
 } __packed PVRSRV_BRIDGE_IN_PVRSRVPDUMPCOMMENT;
 
index 5161ac2..862343f 100644 (file)
@@ -66,135 +66,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
-static IMG_INT
-PVRSRVBridgeDevmemPDumpBitmap(IMG_UINT32 ui32DispatchTableEntry,
-                             IMG_UINT8 * psDevmemPDumpBitmapIN_UI8,
-                             IMG_UINT8 * psDevmemPDumpBitmapOUT_UI8,
-                             CONNECTION_DATA * psConnection)
-{
-       PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP *psDevmemPDumpBitmapIN =
-           (PVRSRV_BRIDGE_IN_DEVMEMPDUMPBITMAP *) IMG_OFFSET_ADDR(psDevmemPDumpBitmapIN_UI8, 0);
-       PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP *psDevmemPDumpBitmapOUT =
-           (PVRSRV_BRIDGE_OUT_DEVMEMPDUMPBITMAP *) IMG_OFFSET_ADDR(psDevmemPDumpBitmapOUT_UI8, 0);
-
-       IMG_CHAR *uiFileNameInt = NULL;
-       IMG_HANDLE hDevmemCtx = psDevmemPDumpBitmapIN->hDevmemCtx;
-       DEVMEMINT_CTX *psDevmemCtxInt = NULL;
-
-       IMG_UINT32 ui32NextOffset = 0;
-       IMG_BYTE *pArrayArgsBuffer = NULL;
-#if !defined(INTEGRITY_OS)
-       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
-#endif
-
-       IMG_UINT32 ui32BufferSize = (PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) + 0;
-
-       if (ui32BufferSize != 0)
-       {
-#if !defined(INTEGRITY_OS)
-               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
-               IMG_UINT32 ui32InBufferOffset =
-                   PVR_ALIGN(sizeof(*psDevmemPDumpBitmapIN), sizeof(unsigned long));
-               IMG_UINT32 ui32InBufferExcessSize =
-                   ui32InBufferOffset >=
-                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
-
-               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
-               if (bHaveEnoughSpace)
-               {
-                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psDevmemPDumpBitmapIN;
-
-                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
-               }
-               else
-#endif
-               {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
-
-                       if (!pArrayArgsBuffer)
-                       {
-                               psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-                               goto DevmemPDumpBitmap_exit;
-                       }
-               }
-       }
-
-       {
-               uiFileNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
-               ui32NextOffset += PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR);
-       }
-
-       /* Copy the data over */
-       if (PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR) > 0)
-       {
-               if (OSCopyFromUser
-                   (NULL, uiFileNameInt, (const void __user *)psDevmemPDumpBitmapIN->puiFileName,
-                    PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK)
-               {
-                       psDevmemPDumpBitmapOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
-
-                       goto DevmemPDumpBitmap_exit;
-               }
-               ((IMG_CHAR *) uiFileNameInt)[(PVRSRV_PDUMP_MAX_FILENAME_SIZE * sizeof(IMG_CHAR)) -
-                                            1] = '\0';
-       }
-
-       /* Lock over handle lookup. */
-       LockHandle(psConnection->psHandleBase);
-
-       /* Look up the address from the handle */
-       psDevmemPDumpBitmapOUT->eError =
-           PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
-                                      (void **)&psDevmemCtxInt,
-                                      hDevmemCtx, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX, IMG_TRUE);
-       if (unlikely(psDevmemPDumpBitmapOUT->eError != PVRSRV_OK))
-       {
-               UnlockHandle(psConnection->psHandleBase);
-               goto DevmemPDumpBitmap_exit;
-       }
-       /* Release now we have looked up handles. */
-       UnlockHandle(psConnection->psHandleBase);
-
-       psDevmemPDumpBitmapOUT->eError =
-           DevmemIntPDumpBitmap(psConnection, OSGetDevNode(psConnection),
-                                uiFileNameInt,
-                                psDevmemPDumpBitmapIN->ui32FileOffset,
-                                psDevmemPDumpBitmapIN->ui32Width,
-                                psDevmemPDumpBitmapIN->ui32Height,
-                                psDevmemPDumpBitmapIN->ui32StrideInBytes,
-                                psDevmemPDumpBitmapIN->sDevBaseAddr,
-                                psDevmemCtxInt,
-                                psDevmemPDumpBitmapIN->ui32Size,
-                                psDevmemPDumpBitmapIN->ePixelFormat,
-                                psDevmemPDumpBitmapIN->ui32AddrMode,
-                                psDevmemPDumpBitmapIN->ui32PDumpFlags);
-
-DevmemPDumpBitmap_exit:
-
-       /* Lock over handle lookup cleanup. */
-       LockHandle(psConnection->psHandleBase);
-
-       /* Unreference the previously looked up handle */
-       if (psDevmemCtxInt)
-       {
-               PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
-                                           hDevmemCtx, PVRSRV_HANDLE_TYPE_DEVMEMINT_CTX);
-       }
-       /* Release now we have cleaned up look up handles. */
-       UnlockHandle(psConnection->psHandleBase);
-
-       /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
-
-#if defined(INTEGRITY_OS)
-       if (pArrayArgsBuffer)
-#else
-       if (!bHaveEnoughSpace && pArrayArgsBuffer)
-#endif
-               OSFreeMemNoStats(pArrayArgsBuffer);
-
-       return 0;
-}
+static_assert(PVRSRV_PDUMP_MAX_FILENAME_SIZE <= IMG_UINT32_MAX,
+             "PVRSRV_PDUMP_MAX_FILENAME_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(4 <= IMG_UINT32_MAX, "4 must not be larger than IMG_UINT32_MAX");
 
 static IMG_INT
 PVRSRVBridgePDumpImageDescriptor(IMG_UINT32 ui32DispatchTableEntry,
@@ -220,9 +94,10 @@ PVRSRVBridgePDumpImageDescriptor(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPDumpImageDescriptorIN->ui32StringSize * sizeof(IMG_CHAR)) +
-           (4 * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPDumpImageDescriptorIN->ui32StringSize * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) 4 * sizeof(IMG_UINT32)) + 0;
 
        if (unlikely(psPDumpImageDescriptorIN->ui32StringSize > PVRSRV_PDUMP_MAX_FILENAME_SIZE))
        {
@@ -230,6 +105,14 @@ PVRSRVBridgePDumpImageDescriptor(IMG_UINT32 ui32DispatchTableEntry,
                goto PDumpImageDescriptor_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPDumpImageDescriptorOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PDumpImageDescriptor_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -250,7 +133,7 @@ PVRSRVBridgePDumpImageDescriptor(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -354,7 +237,10 @@ PDumpImageDescriptor_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPDumpImageDescriptorOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -366,6 +252,9 @@ PDumpImageDescriptor_exit:
        return 0;
 }
 
+static_assert(PVRSRV_PDUMP_MAX_COMMENT_SIZE <= IMG_UINT32_MAX,
+             "PVRSRV_PDUMP_MAX_COMMENT_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32DispatchTableEntry,
                               IMG_UINT8 * psPVRSRVPDumpCommentIN_UI8,
@@ -386,9 +275,23 @@ PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPVRSRVPDumpCommentIN->ui32CommentSize * sizeof(IMG_CHAR)) + 0;
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
+       if (unlikely(psPVRSRVPDumpCommentIN->ui32CommentSize > PVRSRV_PDUMP_MAX_COMMENT_SIZE))
+       {
+               psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto PVRSRVPDumpComment_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PVRSRVPDumpComment_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -410,7 +313,7 @@ PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -420,33 +323,40 @@ PVRSRVBridgePVRSRVPDumpComment(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
+       if (psPVRSRVPDumpCommentIN->ui32CommentSize != 0)
        {
                uiCommentInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
-               ui32NextOffset += PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR);
+               ui32NextOffset += psPVRSRVPDumpCommentIN->ui32CommentSize * sizeof(IMG_CHAR);
        }
 
        /* Copy the data over */
-       if (PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR) > 0)
+       if (psPVRSRVPDumpCommentIN->ui32CommentSize * sizeof(IMG_CHAR) > 0)
        {
                if (OSCopyFromUser
                    (NULL, uiCommentInt, (const void __user *)psPVRSRVPDumpCommentIN->puiComment,
-                    PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) != PVRSRV_OK)
+                    psPVRSRVPDumpCommentIN->ui32CommentSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
                {
                        psPVRSRVPDumpCommentOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
                        goto PVRSRVPDumpComment_exit;
                }
-               ((IMG_CHAR *) uiCommentInt)[(PVRSRV_PDUMP_MAX_COMMENT_SIZE * sizeof(IMG_CHAR)) -
-                                           1] = '\0';
+               ((IMG_CHAR *)
+                uiCommentInt)[(psPVRSRVPDumpCommentIN->ui32CommentSize * sizeof(IMG_CHAR)) - 1] =
+       '\0';
        }
 
        psPVRSRVPDumpCommentOUT->eError =
-           PDumpCommentKM(uiCommentInt, psPVRSRVPDumpCommentIN->ui32Flags);
+           PDumpCommentKM(psConnection, OSGetDevNode(psConnection),
+                          psPVRSRVPDumpCommentIN->ui32CommentSize,
+                          uiCommentInt, psPVRSRVPDumpCommentIN->ui32Flags);
 
 PVRSRVPDumpComment_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPVRSRVPDumpCommentOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -478,6 +388,9 @@ PVRSRVBridgePVRSRVPDumpSetFrame(IMG_UINT32 ui32DispatchTableEntry,
        return 0;
 }
 
+static_assert(PVRSRV_PDUMP_MAX_FILENAME_SIZE <= IMG_UINT32_MAX,
+             "PVRSRV_PDUMP_MAX_FILENAME_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePDumpDataDescriptor(IMG_UINT32 ui32DispatchTableEntry,
                                IMG_UINT8 * psPDumpDataDescriptorIN_UI8,
@@ -501,8 +414,9 @@ PVRSRVBridgePDumpDataDescriptor(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPDumpDataDescriptorIN->ui32StringSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPDumpDataDescriptorIN->ui32StringSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psPDumpDataDescriptorIN->ui32StringSize > PVRSRV_PDUMP_MAX_FILENAME_SIZE))
        {
@@ -510,6 +424,14 @@ PVRSRVBridgePDumpDataDescriptor(IMG_UINT32 ui32DispatchTableEntry,
                goto PDumpDataDescriptor_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPDumpDataDescriptorOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PDumpDataDescriptor_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -530,7 +452,7 @@ PVRSRVBridgePDumpDataDescriptor(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -605,7 +527,10 @@ PDumpDataDescriptor_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPDumpDataDescriptorOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -622,7 +547,7 @@ PDumpDataDescriptor_exit:
  */
 
 PVRSRV_ERROR InitPDUMPBridge(void);
-PVRSRV_ERROR DeinitPDUMPBridge(void);
+void DeinitPDUMPBridge(void);
 
 /*
  * Register all PDUMP functions with services
@@ -630,9 +555,6 @@ PVRSRV_ERROR DeinitPDUMPBridge(void);
 PVRSRV_ERROR InitPDUMPBridge(void)
 {
 
-       SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_DEVMEMPDUMPBITMAP,
-                             PVRSRVBridgeDevmemPDumpBitmap, NULL);
-
        SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_PDUMPIMAGEDESCRIPTOR,
                              PVRSRVBridgePDumpImageDescriptor, NULL);
 
@@ -651,11 +573,9 @@ PVRSRV_ERROR InitPDUMPBridge(void)
 /*
  * Unregister all pdump functions with services
  */
-PVRSRV_ERROR DeinitPDUMPBridge(void)
+void DeinitPDUMPBridge(void)
 {
 
-       UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_DEVMEMPDUMPBITMAP);
-
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_PDUMPIMAGEDESCRIPTOR);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_PVRSRVPDUMPCOMMENT);
@@ -664,5 +584,4 @@ PVRSRV_ERROR DeinitPDUMPBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP, PVRSRV_BRIDGE_PDUMP_PDUMPDATADESCRIPTOR);
 
-       return PVRSRV_OK;
 }
index 4f17645..7ba9298 100644 (file)
@@ -77,10 +77,10 @@ IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpSetDefaultCaptureParams(IMG_HANDLE hB
                                                                   IMG_UINT32 ui32MaxParamFileSize)
 {
        PVRSRV_ERROR eError;
-       PVR_UNREFERENCED_PARAMETER(hBridge);
 
        eError =
-           PDumpSetDefaultCaptureParamsKM(ui32Mode,
+           PDumpSetDefaultCaptureParamsKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge),
+                                          ui32Mode,
                                           ui32Start, ui32End, ui32Interval, ui32MaxParamFileSize);
 
        return eError;
@@ -100,8 +100,7 @@ IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpIsLastCaptureFrame(IMG_HANDLE hBridge
 IMG_INTERNAL PVRSRV_ERROR BridgePVRSRVPDumpForceCaptureStop(IMG_HANDLE hBridge)
 {
        PVRSRV_ERROR eError;
-       PVR_UNREFERENCED_PARAMETER(hBridge);
 
-       eError = PDumpForceCaptureStopKM();
+       eError = PDumpForceCaptureStopKM(NULL, (PVRSRV_DEVICE_NODE *) ((void *)hBridge));
        return eError;
 }
index e530153..4edc0fc 100644 (file)
@@ -127,10 +127,9 @@ PVRSRVBridgePVRSRVPDumpSetDefaultCaptureParams(IMG_UINT32 ui32DispatchTableEntry
            (PVRSRV_BRIDGE_OUT_PVRSRVPDUMPSETDEFAULTCAPTUREPARAMS *)
            IMG_OFFSET_ADDR(psPVRSRVPDumpSetDefaultCaptureParamsOUT_UI8, 0);
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
-
        psPVRSRVPDumpSetDefaultCaptureParamsOUT->eError =
-           PDumpSetDefaultCaptureParamsKM(psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Mode,
+           PDumpSetDefaultCaptureParamsKM(psConnection, OSGetDevNode(psConnection),
+                                          psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Mode,
                                           psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Start,
                                           psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32End,
                                           psPVRSRVPDumpSetDefaultCaptureParamsIN->ui32Interval,
@@ -175,10 +174,10 @@ PVRSRVBridgePVRSRVPDumpForceCaptureStop(IMG_UINT32 ui32DispatchTableEntry,
            (PVRSRV_BRIDGE_OUT_PVRSRVPDUMPFORCECAPTURESTOP *)
            IMG_OFFSET_ADDR(psPVRSRVPDumpForceCaptureStopOUT_UI8, 0);
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
        PVR_UNREFERENCED_PARAMETER(psPVRSRVPDumpForceCaptureStopIN);
 
-       psPVRSRVPDumpForceCaptureStopOUT->eError = PDumpForceCaptureStopKM();
+       psPVRSRVPDumpForceCaptureStopOUT->eError =
+           PDumpForceCaptureStopKM(psConnection, OSGetDevNode(psConnection));
 
        return 0;
 }
@@ -190,7 +189,7 @@ PVRSRVBridgePVRSRVPDumpForceCaptureStop(IMG_UINT32 ui32DispatchTableEntry,
 static POS_LOCK pPDUMPCTRLBridgeLock;
 
 PVRSRV_ERROR InitPDUMPCTRLBridge(void);
-PVRSRV_ERROR DeinitPDUMPCTRLBridge(void);
+void DeinitPDUMPCTRLBridge(void);
 
 /*
  * Register all PDUMPCTRL functions with services
@@ -223,9 +222,9 @@ PVRSRV_ERROR InitPDUMPCTRLBridge(void)
 /*
  * Unregister all pdumpctrl functions with services
  */
-PVRSRV_ERROR DeinitPDUMPCTRLBridge(void)
+void DeinitPDUMPCTRLBridge(void)
 {
-       PVR_LOG_RETURN_IF_ERROR(OSLockDestroy(pPDUMPCTRLBridgeLock), "OSLockDestroy");
+       OSLockDestroy(pPDUMPCTRLBridgeLock);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPCTRL,
                                PVRSRV_BRIDGE_PDUMPCTRL_PVRSRVPDUMPGETSTATE);
@@ -242,5 +241,4 @@ PVRSRV_ERROR DeinitPDUMPCTRLBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPCTRL,
                                PVRSRV_BRIDGE_PDUMPCTRL_PVRSRVPDUMPFORCECAPTURESTOP);
 
-       return PVRSRV_OK;
 }
index b59d48c..5feeab7 100644 (file)
@@ -230,6 +230,9 @@ PMRPDumpLoadMemValue64_exit:
        return 0;
 }
 
+static_assert(PVRSRV_PDUMP_MAX_FILENAME_SIZE <= IMG_UINT32_MAX,
+             "PVRSRV_PDUMP_MAX_FILENAME_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32DispatchTableEntry,
                               IMG_UINT8 * psPMRPDumpSaveToFileIN_UI8,
@@ -252,7 +255,9 @@ PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPMRPDumpSaveToFileIN->ui32ArraySize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psPMRPDumpSaveToFileIN->ui32ArraySize > PVRSRV_PDUMP_MAX_FILENAME_SIZE))
        {
@@ -260,6 +265,14 @@ PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32DispatchTableEntry,
                goto PMRPDumpSaveToFile_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPMRPDumpSaveToFileOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PMRPDumpSaveToFile_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -280,7 +293,7 @@ PVRSRVBridgePMRPDumpSaveToFile(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -350,7 +363,10 @@ PMRPDumpSaveToFile_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPMRPDumpSaveToFileOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -386,9 +402,10 @@ PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)) +
-           (psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psPMRPDumpSymbolicAddrIN->ui32SymbolicAddrLen * sizeof(IMG_CHAR)) + 0;
 
        if (psPMRPDumpSymbolicAddrIN->ui32MemspaceNameLen > PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH)
        {
@@ -405,6 +422,14 @@ PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32DispatchTableEntry,
        psPMRPDumpSymbolicAddrOUT->puiMemspaceName = psPMRPDumpSymbolicAddrIN->puiMemspaceName;
        psPMRPDumpSymbolicAddrOUT->puiSymbolicAddr = psPMRPDumpSymbolicAddrIN->puiSymbolicAddr;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psPMRPDumpSymbolicAddrOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto PMRPDumpSymbolicAddr_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -425,7 +450,7 @@ PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -472,6 +497,11 @@ PVRSRVBridgePMRPDumpSymbolicAddr(IMG_UINT32 ui32DispatchTableEntry,
                                  puiSymbolicAddrInt,
                                  &psPMRPDumpSymbolicAddrOUT->uiNewOffset,
                                  &psPMRPDumpSymbolicAddrOUT->uiNextSymName);
+       /* Exit early if bridged call fails */
+       if (unlikely(psPMRPDumpSymbolicAddrOUT->eError != PVRSRV_OK))
+       {
+               goto PMRPDumpSymbolicAddr_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((puiMemspaceNameInt) &&
@@ -522,7 +552,10 @@ PMRPDumpSymbolicAddr_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psPMRPDumpSymbolicAddrOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -692,6 +725,9 @@ PMRPDumpCBP_exit:
        return 0;
 }
 
+static_assert(PVRSRV_PDUMP_MAX_FILENAME_SIZE <= IMG_UINT32_MAX,
+             "PVRSRV_PDUMP_MAX_FILENAME_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32DispatchTableEntry,
                                            IMG_UINT8 * psDevmemIntPDumpSaveToFileVirtualIN_UI8,
@@ -715,8 +751,10 @@ PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize * sizeof(IMG_CHAR)) +
+           0;
 
        if (unlikely
            (psDevmemIntPDumpSaveToFileVirtualIN->ui32ArraySize > PVRSRV_PDUMP_MAX_FILENAME_SIZE))
@@ -726,6 +764,14 @@ PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32DispatchTableEntry,
                goto DevmemIntPDumpSaveToFileVirtual_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psDevmemIntPDumpSaveToFileVirtualOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto DevmemIntPDumpSaveToFileVirtual_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -747,7 +793,7 @@ PVRSRVBridgeDevmemIntPDumpSaveToFileVirtual(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -824,7 +870,10 @@ DevmemIntPDumpSaveToFileVirtual_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psDevmemIntPDumpSaveToFileVirtualOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -841,7 +890,7 @@ DevmemIntPDumpSaveToFileVirtual_exit:
  */
 
 PVRSRV_ERROR InitPDUMPMMBridge(void);
-PVRSRV_ERROR DeinitPDUMPMMBridge(void);
+void DeinitPDUMPMMBridge(void);
 
 /*
  * Register all PDUMPMM functions with services
@@ -883,7 +932,7 @@ PVRSRV_ERROR InitPDUMPMMBridge(void)
 /*
  * Unregister all pdumpmm functions with services
  */
-PVRSRV_ERROR DeinitPDUMPMMBridge(void)
+void DeinitPDUMPMMBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM, PVRSRV_BRIDGE_PDUMPMM_PMRPDUMPLOADMEM);
@@ -907,5 +956,4 @@ PVRSRV_ERROR DeinitPDUMPMMBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PDUMPMM,
                                PVRSRV_BRIDGE_PDUMPMM_DEVMEMINTPDUMPSAVETOFILEVIRTUAL);
 
-       return PVRSRV_OK;
 }
index 0cd6372..e25137c 100644 (file)
@@ -72,6 +72,9 @@ static PVRSRV_ERROR _TLOpenStreampsSDIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(PRVSRVTL_MAX_STREAM_NAME_SIZE <= IMG_UINT32_MAX,
+             "PRVSRVTL_MAX_STREAM_NAME_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeTLOpenStream(IMG_UINT32 ui32DispatchTableEntry,
                         IMG_UINT8 * psTLOpenStreamIN_UI8,
@@ -92,10 +95,20 @@ PVRSRVBridgeTLOpenStream(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) + 0;
 
        psTLOpenStreamOUT->hSD = NULL;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psTLOpenStreamOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto TLOpenStream_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -116,7 +129,7 @@ PVRSRVBridgeTLOpenStream(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -196,7 +209,7 @@ TLOpenStream_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(psConnection->psHandleBase);
 
-                       eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+                       eError = PVRSRVDestroyHandleUnlocked(psConnection->psHandleBase,
                                                             (IMG_HANDLE) psTLOpenStreamOUT->hSD,
                                                             PVRSRV_HANDLE_TYPE_PVR_TL_SD);
                        if (unlikely((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY)))
@@ -222,7 +235,10 @@ TLOpenStream_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psTLOpenStreamOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -248,10 +264,11 @@ PVRSRVBridgeTLCloseStream(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psTLCloseStreamOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psTLCloseStreamIN->hSD,
-                                           PVRSRV_HANDLE_TYPE_PVR_TL_SD);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psTLCloseStreamIN->hSD,
+                                             PVRSRV_HANDLE_TYPE_PVR_TL_SD);
        if (unlikely((psTLCloseStreamOUT->eError != PVRSRV_OK) &&
+                    (psTLCloseStreamOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psTLCloseStreamOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -370,6 +387,9 @@ TLReleaseData_exit:
        return 0;
 }
 
+static_assert(PRVSRVTL_MAX_STREAM_NAME_SIZE <= IMG_UINT32_MAX,
+             "PRVSRVTL_MAX_STREAM_NAME_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
                              IMG_UINT8 * psTLDiscoverStreamsIN_UI8,
@@ -390,9 +410,10 @@ PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) +
-           (psTLDiscoverStreamsIN->ui32Size * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) PRVSRVTL_MAX_STREAM_NAME_SIZE * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psTLDiscoverStreamsIN->ui32Size * sizeof(IMG_CHAR)) + 0;
 
        if (psTLDiscoverStreamsIN->ui32Size > PVRSRVTL_MAX_DISCOVERABLE_STREAMS_BUFFER)
        {
@@ -404,6 +425,14 @@ PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
 
        psTLDiscoverStreamsOUT->puiStreams = psTLDiscoverStreamsIN->puiStreams;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psTLDiscoverStreamsOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto TLDiscoverStreams_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -424,7 +453,7 @@ PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -464,6 +493,11 @@ PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
            TLServerDiscoverStreamsKM(uiNamePatternInt,
                                      psTLDiscoverStreamsIN->ui32Size,
                                      puiStreamsInt, &psTLDiscoverStreamsOUT->ui32NumFound);
+       /* Exit early if bridged call fails */
+       if (unlikely(psTLDiscoverStreamsOUT->eError != PVRSRV_OK))
+       {
+               goto TLDiscoverStreams_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((puiStreamsInt) && ((psTLDiscoverStreamsIN->ui32Size * sizeof(IMG_CHAR)) > 0))
@@ -482,7 +516,10 @@ PVRSRVBridgeTLDiscoverStreams(IMG_UINT32 ui32DispatchTableEntry,
 TLDiscoverStreams_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psTLDiscoverStreamsOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -596,6 +633,9 @@ TLCommitStream_exit:
        return 0;
 }
 
+static_assert(PVRSRVTL_MAX_PACKET_SIZE <= IMG_UINT32_MAX,
+             "PVRSRVTL_MAX_PACKET_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeTLWriteData(IMG_UINT32 ui32DispatchTableEntry,
                        IMG_UINT8 * psTLWriteDataIN_UI8,
@@ -616,7 +656,8 @@ PVRSRVBridgeTLWriteData(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize = ((IMG_UINT64) psTLWriteDataIN->ui32Size * sizeof(IMG_BYTE)) + 0;
 
        if (unlikely(psTLWriteDataIN->ui32Size > PVRSRVTL_MAX_PACKET_SIZE))
        {
@@ -624,6 +665,14 @@ PVRSRVBridgeTLWriteData(IMG_UINT32 ui32DispatchTableEntry,
                goto TLWriteData_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psTLWriteDataOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto TLWriteData_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -644,7 +693,7 @@ PVRSRVBridgeTLWriteData(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -707,7 +756,10 @@ TLWriteData_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psTLWriteDataOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -724,7 +776,7 @@ TLWriteData_exit:
  */
 
 PVRSRV_ERROR InitPVRTLBridge(void);
-PVRSRV_ERROR DeinitPVRTLBridge(void);
+void DeinitPVRTLBridge(void);
 
 /*
  * Register all PVRTL functions with services
@@ -762,7 +814,7 @@ PVRSRV_ERROR InitPVRTLBridge(void)
 /*
  * Unregister all pvrtl functions with services
  */
-PVRSRV_ERROR DeinitPVRTLBridge(void)
+void DeinitPVRTLBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLOPENSTREAM);
@@ -781,5 +833,4 @@ PVRSRV_ERROR DeinitPVRTLBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_PVRTL, PVRSRV_BRIDGE_PVRTL_TLWRITEDATA);
 
-       return PVRSRV_OK;
 }
index 29a1bcd..bb7d012 100644 (file)
@@ -305,7 +305,7 @@ PVRSRVBridgeRGXOverallocateBPRegisters(IMG_UINT32 ui32DispatchTableEntry,
 
 #if !defined(EXCLUDE_RGXBREAKPOINT_BRIDGE)
 PVRSRV_ERROR InitRGXBREAKPOINTBridge(void);
-PVRSRV_ERROR DeinitRGXBREAKPOINTBridge(void);
+void DeinitRGXBREAKPOINTBridge(void);
 
 /*
  * Register all RGXBREAKPOINT functions with services
@@ -339,7 +339,7 @@ PVRSRV_ERROR InitRGXBREAKPOINTBridge(void)
 /*
  * Unregister all rgxbreakpoint functions with services
  */
-PVRSRV_ERROR DeinitRGXBREAKPOINTBridge(void)
+void DeinitRGXBREAKPOINTBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXBREAKPOINT,
@@ -357,7 +357,6 @@ PVRSRV_ERROR DeinitRGXBREAKPOINTBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXBREAKPOINT,
                                PVRSRV_BRIDGE_RGXBREAKPOINT_RGXOVERALLOCATEBPREGISTERS);
 
-       return PVRSRV_OK;
 }
 #else /* EXCLUDE_RGXBREAKPOINT_BRIDGE */
 /* This bridge is conditional on EXCLUDE_RGXBREAKPOINT_BRIDGE - when defined,
@@ -366,7 +365,6 @@ PVRSRV_ERROR DeinitRGXBREAKPOINTBridge(void)
 #define InitRGXBREAKPOINTBridge() \
        PVRSRV_OK
 
-#define DeinitRGXBREAKPOINTBridge() \
-       PVRSRV_OK
+#define DeinitRGXBREAKPOINTBridge()
 
 #endif /* EXCLUDE_RGXBREAKPOINT_BRIDGE */
index dc6ed7d..396bd3f 100644 (file)
@@ -174,7 +174,6 @@ typedef struct PVRSRV_BRIDGE_IN_RGXKICKCDM2_TAG
        IMG_HANDLE *phSyncPMRs;
        PVRSRV_FENCE hCheckFenceFd;
        PVRSRV_TIMELINE hUpdateTimeline;
-       IMG_UINT32 ui32ClientCacheOpSeqNum;
        IMG_UINT32 ui32ClientUpdateCount;
        IMG_UINT32 ui32CmdSize;
        IMG_UINT32 ui32ExtJobRef;
index 11ede73..9b97e78 100644 (file)
@@ -74,6 +74,11 @@ static PVRSRV_ERROR _RGXCreateComputeContextpsComputeContextIntRelease(void *pvD
        return eError;
 }
 
+static_assert(RGXFWIF_RF_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_RF_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_STATIC_COMPUTECONTEXT_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_STATIC_COMPUTECONTEXT_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32DispatchTableEntry,
                                    IMG_UINT8 * psRGXCreateComputeContextIN_UI8,
@@ -99,9 +104,11 @@ PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
-           (psRGXCreateComputeContextIN->ui32StaticComputeContextStateSize * sizeof(IMG_BYTE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXCreateComputeContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXCreateComputeContextIN->ui32StaticComputeContextStateSize *
+            sizeof(IMG_BYTE)) + 0;
 
        if (unlikely(psRGXCreateComputeContextIN->ui32FrameworkCmdize > RGXFWIF_RF_CMD_SIZE))
        {
@@ -131,6 +138,14 @@ PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXCreateComputeContextOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXCreateComputeContext_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -151,7 +166,7 @@ PVRSRVBridgeRGXCreateComputeContext(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -287,7 +302,10 @@ RGXCreateComputeContext_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXCreateComputeContextOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -330,12 +348,13 @@ PVRSRVBridgeRGXDestroyComputeContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyComputeContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyComputeContextIN->
-                                           hComputeContext,
-                                           PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyComputeContextIN->
+                                             hComputeContext,
+                                             PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT);
        if (unlikely
            ((psRGXDestroyComputeContextOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyComputeContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psRGXDestroyComputeContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -560,6 +579,15 @@ RGXNotifyComputeWriteOffsetUpdate_exit:
        return 0;
 }
 
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
                        IMG_UINT8 * psRGXKickCDM2IN_UI8,
@@ -588,16 +616,17 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
-           (psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
-           (psRGXKickCDM2IN->ui32CmdSize * sizeof(IMG_BYTE)) +
-           (psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
-           (psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(PMR *)) +
-           (psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32CmdSize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(PMR *)) +
+           ((IMG_UINT64) psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
 
        if (unlikely(psRGXKickCDM2IN->ui32ClientUpdateCount > PVRSRV_MAX_SYNCS))
        {
@@ -631,6 +660,14 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXKickCDM2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXKickCDM2_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -651,7 +688,7 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -665,6 +702,9 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psClientUpdateUFOSyncPrimBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psClientUpdateUFOSyncPrimBlockInt, 0,
+                              psRGXKickCDM2IN->ui32ClientUpdateCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXKickCDM2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
                hClientUpdateUFOSyncPrimBlockInt2 =
@@ -788,6 +828,7 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
        if (psRGXKickCDM2IN->ui32SyncPMRCount != 0)
        {
                psSyncPMRsInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psSyncPMRsInt, 0, psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(PMR *));
                ui32NextOffset += psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(PMR *);
                hSyncPMRsInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psRGXKickCDM2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
@@ -865,7 +906,6 @@ PVRSRVBridgeRGXKickCDM2(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXKickCDM2OUT->eError =
            PVRSRVRGXKickCDMKM(psComputeContextInt,
-                              psRGXKickCDM2IN->ui32ClientCacheOpSeqNum,
                               psRGXKickCDM2IN->ui32ClientUpdateCount,
                               psClientUpdateUFOSyncPrimBlockInt,
                               ui32ClientUpdateOffsetInt,
@@ -906,7 +946,7 @@ RGXKickCDM2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hClientUpdateUFOSyncPrimBlockInt2[i])
+                       if (psClientUpdateUFOSyncPrimBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hClientUpdateUFOSyncPrimBlockInt2[i],
@@ -923,7 +963,7 @@ RGXKickCDM2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hSyncPMRsInt2[i])
+                       if (psSyncPMRsInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hSyncPMRsInt2[i],
@@ -935,7 +975,10 @@ RGXKickCDM2_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXKickCDM2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -1061,7 +1104,7 @@ RGXGetLastDeviceError_exit:
  */
 
 PVRSRV_ERROR InitRGXCMPBridge(void);
-PVRSRV_ERROR DeinitRGXCMPBridge(void);
+void DeinitRGXCMPBridge(void);
 
 /*
  * Register all RGXCMP functions with services
@@ -1102,7 +1145,7 @@ PVRSRV_ERROR InitRGXCMPBridge(void)
 /*
  * Unregister all rgxcmp functions with services
  */
-PVRSRV_ERROR DeinitRGXCMPBridge(void)
+void DeinitRGXCMPBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP, PVRSRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT);
@@ -1125,5 +1168,4 @@ PVRSRV_ERROR DeinitRGXCMPBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXCMP, PVRSRV_BRIDGE_RGXCMP_RGXGETLASTDEVICEERROR);
 
-       return PVRSRV_OK;
 }
index 571bf1b..e66ce89 100644 (file)
@@ -235,7 +235,7 @@ PVRSRVBridgeRGXCurrentTime(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitRGXFWDBGBridge(void);
-PVRSRV_ERROR DeinitRGXFWDBGBridge(void);
+void DeinitRGXFWDBGBridge(void);
 
 /*
  * Register all RGXFWDBG functions with services
@@ -277,7 +277,7 @@ PVRSRV_ERROR InitRGXFWDBGBridge(void)
 /*
  * Unregister all rgxfwdbg functions with services
  */
-PVRSRV_ERROR DeinitRGXFWDBGBridge(void)
+void DeinitRGXFWDBGBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXFWDBG, PVRSRV_BRIDGE_RGXFWDBG_RGXFWDEBUGSETFWLOG);
@@ -302,5 +302,4 @@ PVRSRV_ERROR DeinitRGXFWDBGBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXFWDBG, PVRSRV_BRIDGE_RGXFWDBG_RGXCURRENTTIME);
 
-       return PVRSRV_OK;
 }
index 9e57dcc..08e80bb 100644 (file)
@@ -56,11 +56,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST                      0
 #define PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERF                  PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+0
-#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS                  PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+1
-#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONTROLHWPERFBLOCKS                 PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+2
-#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS                        PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+3
-#define PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS                   PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+4
-#define PVRSRV_BRIDGE_RGXHWPERF_CMD_LAST                       (PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS                   PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+1
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGMUXHWPERFCOUNTERS                     PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+2
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONTROLHWPERFBLOCKS                 PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+3
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS                        PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+4
+#define PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGUREHWPERFBLOCKS                       PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+5
+#define PVRSRV_BRIDGE_RGXHWPERF_CMD_LAST                       (PVRSRV_BRIDGE_RGXHWPERF_CMD_FIRST+5)
 
 /*******************************************
             RGXCtrlHWPerf
@@ -81,21 +82,38 @@ typedef struct PVRSRV_BRIDGE_OUT_RGXCTRLHWPERF_TAG
 } __packed PVRSRV_BRIDGE_OUT_RGXCTRLHWPERF;
 
 /*******************************************
-            RGXConfigEnableHWPerfCounters
+            RGXGetHWPerfBvncFeatureFlags
  *******************************************/
 
-/* Bridge in structure for RGXConfigEnableHWPerfCounters */
-typedef struct PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS_TAG
+/* Bridge in structure for RGXGetHWPerfBvncFeatureFlags */
+typedef struct PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS_TAG
 {
-       RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigs;
+       IMG_UINT32 ui32EmptyStructPlaceholder;
+} __packed PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS;
+
+/* Bridge out structure for RGXGetHWPerfBvncFeatureFlags */
+typedef struct PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS_TAG
+{
+       RGX_HWPERF_BVNC sBVNC;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS;
+
+/*******************************************
+            RGXConfigMuxHWPerfCounters
+ *******************************************/
+
+/* Bridge in structure for RGXConfigMuxHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_IN_RGXCONFIGMUXHWPERFCOUNTERS_TAG
+{
+       RGX_HWPERF_CONFIG_MUX_CNTBLK *psBlockConfigs;
        IMG_UINT32 ui32ArrayLen;
-} __packed PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS;
+} __packed PVRSRV_BRIDGE_IN_RGXCONFIGMUXHWPERFCOUNTERS;
 
-/* Bridge out structure for RGXConfigEnableHWPerfCounters */
-typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS_TAG
+/* Bridge out structure for RGXConfigMuxHWPerfCounters */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGMUXHWPERFCOUNTERS_TAG
 {
        PVRSRV_ERROR eError;
-} __packed PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS;
+} __packed PVRSRV_BRIDGE_OUT_RGXCONFIGMUXHWPERFCOUNTERS;
 
 /*******************************************
             RGXControlHWPerfBlocks
@@ -134,20 +152,21 @@ typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGCUSTOMCOUNTERS_TAG
 } __packed PVRSRV_BRIDGE_OUT_RGXCONFIGCUSTOMCOUNTERS;
 
 /*******************************************
-            RGXGetHWPerfBvncFeatureFlags
+            RGXConfigureHWPerfBlocks
  *******************************************/
 
-/* Bridge in structure for RGXGetHWPerfBvncFeatureFlags */
-typedef struct PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS_TAG
+/* Bridge in structure for RGXConfigureHWPerfBlocks */
+typedef struct PVRSRV_BRIDGE_IN_RGXCONFIGUREHWPERFBLOCKS_TAG
 {
-       IMG_UINT32 ui32EmptyStructPlaceholder;
-} __packed PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS;
+       RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigs;
+       IMG_UINT32 ui32ArrayLen;
+       IMG_UINT32 ui32CtrlWord;
+} __packed PVRSRV_BRIDGE_IN_RGXCONFIGUREHWPERFBLOCKS;
 
-/* Bridge out structure for RGXGetHWPerfBvncFeatureFlags */
-typedef struct PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS_TAG
+/* Bridge out structure for RGXConfigureHWPerfBlocks */
+typedef struct PVRSRV_BRIDGE_OUT_RGXCONFIGUREHWPERFBLOCKS_TAG
 {
-       RGX_HWPERF_BVNC sBVNC;
        PVRSRV_ERROR eError;
-} __packed PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS;
+} __packed PVRSRV_BRIDGE_OUT_RGXCONFIGUREHWPERFBLOCKS;
 
 #endif /* COMMON_RGXHWPERF_BRIDGE_H */
index 34f0ef6..cc22ee3 100644 (file)
@@ -85,19 +85,44 @@ PVRSRVBridgeRGXCtrlHWPerf(IMG_UINT32 ui32DispatchTableEntry,
 }
 
 static IMG_INT
-PVRSRVBridgeRGXConfigEnableHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
-                                         IMG_UINT8 * psRGXConfigEnableHWPerfCountersIN_UI8,
-                                         IMG_UINT8 * psRGXConfigEnableHWPerfCountersOUT_UI8,
-                                         CONNECTION_DATA * psConnection)
+PVRSRVBridgeRGXGetHWPerfBvncFeatureFlags(IMG_UINT32 ui32DispatchTableEntry,
+                                        IMG_UINT8 * psRGXGetHWPerfBvncFeatureFlagsIN_UI8,
+                                        IMG_UINT8 * psRGXGetHWPerfBvncFeatureFlagsOUT_UI8,
+                                        CONNECTION_DATA * psConnection)
 {
-       PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS *psRGXConfigEnableHWPerfCountersIN =
-           (PVRSRV_BRIDGE_IN_RGXCONFIGENABLEHWPERFCOUNTERS *)
-           IMG_OFFSET_ADDR(psRGXConfigEnableHWPerfCountersIN_UI8, 0);
-       PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS *psRGXConfigEnableHWPerfCountersOUT =
-           (PVRSRV_BRIDGE_OUT_RGXCONFIGENABLEHWPERFCOUNTERS *)
-           IMG_OFFSET_ADDR(psRGXConfigEnableHWPerfCountersOUT_UI8, 0);
+       PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS *psRGXGetHWPerfBvncFeatureFlagsIN =
+           (PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS *)
+           IMG_OFFSET_ADDR(psRGXGetHWPerfBvncFeatureFlagsIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS *psRGXGetHWPerfBvncFeatureFlagsOUT =
+           (PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS *)
+           IMG_OFFSET_ADDR(psRGXGetHWPerfBvncFeatureFlagsOUT_UI8, 0);
 
-       RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigsInt = NULL;
+       PVR_UNREFERENCED_PARAMETER(psRGXGetHWPerfBvncFeatureFlagsIN);
+
+       psRGXGetHWPerfBvncFeatureFlagsOUT->eError =
+           PVRSRVRGXGetHWPerfBvncFeatureFlagsKM(psConnection, OSGetDevNode(psConnection),
+                                                &psRGXGetHWPerfBvncFeatureFlagsOUT->sBVNC);
+
+       return 0;
+}
+
+static_assert(RGXFWIF_HWPERF_CTRL_BLKS_MAX <= IMG_UINT32_MAX,
+             "RGXFWIF_HWPERF_CTRL_BLKS_MAX must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeRGXConfigMuxHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
+                                      IMG_UINT8 * psRGXConfigMuxHWPerfCountersIN_UI8,
+                                      IMG_UINT8 * psRGXConfigMuxHWPerfCountersOUT_UI8,
+                                      CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_RGXCONFIGMUXHWPERFCOUNTERS *psRGXConfigMuxHWPerfCountersIN =
+           (PVRSRV_BRIDGE_IN_RGXCONFIGMUXHWPERFCOUNTERS *)
+           IMG_OFFSET_ADDR(psRGXConfigMuxHWPerfCountersIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_RGXCONFIGMUXHWPERFCOUNTERS *psRGXConfigMuxHWPerfCountersOUT =
+           (PVRSRV_BRIDGE_OUT_RGXCONFIGMUXHWPERFCOUNTERS *)
+           IMG_OFFSET_ADDR(psRGXConfigMuxHWPerfCountersOUT_UI8, 0);
+
+       RGX_HWPERF_CONFIG_MUX_CNTBLK *psBlockConfigsInt = NULL;
 
        IMG_UINT32 ui32NextOffset = 0;
        IMG_BYTE *pArrayArgsBuffer = NULL;
@@ -105,23 +130,31 @@ PVRSRVBridgeRGXConfigEnableHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK)) +
-           0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen *
+            sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK)) + 0;
 
-       if (unlikely
-           (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen > RGXFWIF_HWPERF_CTRL_BLKS_MAX))
+       if (unlikely(psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen > RGXFWIF_HWPERF_CTRL_BLKS_MAX))
        {
-               psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
-               goto RGXConfigEnableHWPerfCounters_exit;
+               psRGXConfigMuxHWPerfCountersOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto RGXConfigMuxHWPerfCounters_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXConfigMuxHWPerfCountersOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXConfigMuxHWPerfCounters_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
                /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
                IMG_UINT32 ui32InBufferOffset =
-                   PVR_ALIGN(sizeof(*psRGXConfigEnableHWPerfCountersIN), sizeof(unsigned long));
+                   PVR_ALIGN(sizeof(*psRGXConfigMuxHWPerfCountersIN), sizeof(unsigned long));
                IMG_UINT32 ui32InBufferExcessSize =
                    ui32InBufferOffset >=
                    PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
@@ -130,57 +163,61 @@ PVRSRVBridgeRGXConfigEnableHWPerfCounters(IMG_UINT32 ui32DispatchTableEntry,
                if (bHaveEnoughSpace)
                {
                        IMG_BYTE *pInputBuffer =
-                           (IMG_BYTE *) (void *)psRGXConfigEnableHWPerfCountersIN;
+                           (IMG_BYTE *) (void *)psRGXConfigMuxHWPerfCountersIN;
 
                        pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
                }
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
-                               psRGXConfigEnableHWPerfCountersOUT->eError =
+                               psRGXConfigMuxHWPerfCountersOUT->eError =
                                    PVRSRV_ERROR_OUT_OF_MEMORY;
-                               goto RGXConfigEnableHWPerfCounters_exit;
+                               goto RGXConfigMuxHWPerfCounters_exit;
                        }
                }
        }
 
-       if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen != 0)
+       if (psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen != 0)
        {
                psBlockConfigsInt =
-                   (RGX_HWPERF_CONFIG_CNTBLK *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+                   (RGX_HWPERF_CONFIG_MUX_CNTBLK *) IMG_OFFSET_ADDR(pArrayArgsBuffer,
+                                                                    ui32NextOffset);
                ui32NextOffset +=
-                   psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen *
-                   sizeof(RGX_HWPERF_CONFIG_CNTBLK);
+                   psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen *
+                   sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK);
        }
 
        /* Copy the data over */
-       if (psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK) > 0)
+       if (psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK) > 0)
        {
                if (OSCopyFromUser
                    (NULL, psBlockConfigsInt,
-                    (const void __user *)psRGXConfigEnableHWPerfCountersIN->psBlockConfigs,
-                    psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen *
-                    sizeof(RGX_HWPERF_CONFIG_CNTBLK)) != PVRSRV_OK)
+                    (const void __user *)psRGXConfigMuxHWPerfCountersIN->psBlockConfigs,
+                    psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen *
+                    sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK)) != PVRSRV_OK)
                {
-                       psRGXConfigEnableHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+                       psRGXConfigMuxHWPerfCountersOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
-                       goto RGXConfigEnableHWPerfCounters_exit;
+                       goto RGXConfigMuxHWPerfCounters_exit;
                }
        }
 
-       psRGXConfigEnableHWPerfCountersOUT->eError =
-           PVRSRVRGXConfigEnableHWPerfCountersKM(psConnection, OSGetDevNode(psConnection),
-                                                 psRGXConfigEnableHWPerfCountersIN->ui32ArrayLen,
-                                                 psBlockConfigsInt);
+       psRGXConfigMuxHWPerfCountersOUT->eError =
+           PVRSRVRGXConfigMuxHWPerfCountersKM(psConnection, OSGetDevNode(psConnection),
+                                              psRGXConfigMuxHWPerfCountersIN->ui32ArrayLen,
+                                              psBlockConfigsInt);
 
-RGXConfigEnableHWPerfCounters_exit:
+RGXConfigMuxHWPerfCounters_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXConfigMuxHWPerfCountersOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -192,6 +229,9 @@ RGXConfigEnableHWPerfCounters_exit:
        return 0;
 }
 
+static_assert(RGXFWIF_HWPERF_CTRL_BLKS_MAX <= IMG_UINT32_MAX,
+             "RGXFWIF_HWPERF_CTRL_BLKS_MAX must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXControlHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
                                   IMG_UINT8 * psRGXControlHWPerfBlocksIN_UI8,
@@ -213,8 +253,9 @@ PVRSRVBridgeRGXControlHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXControlHWPerfBlocksIN->ui32ArrayLen * sizeof(IMG_UINT16)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXControlHWPerfBlocksIN->ui32ArrayLen * sizeof(IMG_UINT16)) + 0;
 
        if (unlikely(psRGXControlHWPerfBlocksIN->ui32ArrayLen > RGXFWIF_HWPERF_CTRL_BLKS_MAX))
        {
@@ -222,6 +263,14 @@ PVRSRVBridgeRGXControlHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXControlHWPerfBlocks_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXControlHWPerfBlocksOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXControlHWPerfBlocks_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -242,7 +291,7 @@ PVRSRVBridgeRGXControlHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -281,7 +330,10 @@ PVRSRVBridgeRGXControlHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
 RGXControlHWPerfBlocks_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXControlHWPerfBlocksOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -293,6 +345,9 @@ RGXControlHWPerfBlocks_exit:
        return 0;
 }
 
+static_assert(RGX_HWPERF_MAX_CUSTOM_CNTRS <= IMG_UINT32_MAX,
+             "RGX_HWPERF_MAX_CUSTOM_CNTRS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
                                    IMG_UINT8 * psRGXConfigCustomCountersIN_UI8,
@@ -314,8 +369,10 @@ PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXConfigCustomCountersIN->ui16NumCustomCounters * sizeof(IMG_UINT32)) +
+           0;
 
        if (unlikely
            (psRGXConfigCustomCountersIN->ui16NumCustomCounters > RGX_HWPERF_MAX_CUSTOM_CNTRS))
@@ -324,6 +381,14 @@ PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXConfigCustomCounters_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXConfigCustomCountersOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXConfigCustomCounters_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -344,7 +409,7 @@ PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -386,7 +451,10 @@ PVRSRVBridgeRGXConfigCustomCounters(IMG_UINT32 ui32DispatchTableEntry,
 RGXConfigCustomCounters_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXConfigCustomCountersOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -398,24 +466,122 @@ RGXConfigCustomCounters_exit:
        return 0;
 }
 
+static_assert(RGXFWIF_HWPERF_CTRL_BLKS_MAX <= IMG_UINT32_MAX,
+             "RGXFWIF_HWPERF_CTRL_BLKS_MAX must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
-PVRSRVBridgeRGXGetHWPerfBvncFeatureFlags(IMG_UINT32 ui32DispatchTableEntry,
-                                        IMG_UINT8 * psRGXGetHWPerfBvncFeatureFlagsIN_UI8,
-                                        IMG_UINT8 * psRGXGetHWPerfBvncFeatureFlagsOUT_UI8,
-                                        CONNECTION_DATA * psConnection)
+PVRSRVBridgeRGXConfigureHWPerfBlocks(IMG_UINT32 ui32DispatchTableEntry,
+                                    IMG_UINT8 * psRGXConfigureHWPerfBlocksIN_UI8,
+                                    IMG_UINT8 * psRGXConfigureHWPerfBlocksOUT_UI8,
+                                    CONNECTION_DATA * psConnection)
 {
-       PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS *psRGXGetHWPerfBvncFeatureFlagsIN =
-           (PVRSRV_BRIDGE_IN_RGXGETHWPERFBVNCFEATUREFLAGS *)
-           IMG_OFFSET_ADDR(psRGXGetHWPerfBvncFeatureFlagsIN_UI8, 0);
-       PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS *psRGXGetHWPerfBvncFeatureFlagsOUT =
-           (PVRSRV_BRIDGE_OUT_RGXGETHWPERFBVNCFEATUREFLAGS *)
-           IMG_OFFSET_ADDR(psRGXGetHWPerfBvncFeatureFlagsOUT_UI8, 0);
+       PVRSRV_BRIDGE_IN_RGXCONFIGUREHWPERFBLOCKS *psRGXConfigureHWPerfBlocksIN =
+           (PVRSRV_BRIDGE_IN_RGXCONFIGUREHWPERFBLOCKS *)
+           IMG_OFFSET_ADDR(psRGXConfigureHWPerfBlocksIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_RGXCONFIGUREHWPERFBLOCKS *psRGXConfigureHWPerfBlocksOUT =
+           (PVRSRV_BRIDGE_OUT_RGXCONFIGUREHWPERFBLOCKS *)
+           IMG_OFFSET_ADDR(psRGXConfigureHWPerfBlocksOUT_UI8, 0);
 
-       PVR_UNREFERENCED_PARAMETER(psRGXGetHWPerfBvncFeatureFlagsIN);
+       RGX_HWPERF_CONFIG_CNTBLK *psBlockConfigsInt = NULL;
 
-       psRGXGetHWPerfBvncFeatureFlagsOUT->eError =
-           PVRSRVRGXGetHWPerfBvncFeatureFlagsKM(psConnection, OSGetDevNode(psConnection),
-                                                &psRGXGetHWPerfBvncFeatureFlagsOUT->sBVNC);
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXConfigureHWPerfBlocksIN->ui32ArrayLen *
+            sizeof(RGX_HWPERF_CONFIG_CNTBLK)) + 0;
+
+       if (unlikely(psRGXConfigureHWPerfBlocksIN->ui32ArrayLen > RGXFWIF_HWPERF_CTRL_BLKS_MAX))
+       {
+               psRGXConfigureHWPerfBlocksOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto RGXConfigureHWPerfBlocks_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXConfigureHWPerfBlocksOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXConfigureHWPerfBlocks_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psRGXConfigureHWPerfBlocksIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psRGXConfigureHWPerfBlocksIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psRGXConfigureHWPerfBlocksOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto RGXConfigureHWPerfBlocks_exit;
+                       }
+               }
+       }
+
+       if (psRGXConfigureHWPerfBlocksIN->ui32ArrayLen != 0)
+       {
+               psBlockConfigsInt =
+                   (RGX_HWPERF_CONFIG_CNTBLK *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psRGXConfigureHWPerfBlocksIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK);
+       }
+
+       /* Copy the data over */
+       if (psRGXConfigureHWPerfBlocksIN->ui32ArrayLen * sizeof(RGX_HWPERF_CONFIG_CNTBLK) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, psBlockConfigsInt,
+                    (const void __user *)psRGXConfigureHWPerfBlocksIN->psBlockConfigs,
+                    psRGXConfigureHWPerfBlocksIN->ui32ArrayLen *
+                    sizeof(RGX_HWPERF_CONFIG_CNTBLK)) != PVRSRV_OK)
+               {
+                       psRGXConfigureHWPerfBlocksOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXConfigureHWPerfBlocks_exit;
+               }
+       }
+
+       psRGXConfigureHWPerfBlocksOUT->eError =
+           PVRSRVRGXConfigureHWPerfBlocksKM(psConnection, OSGetDevNode(psConnection),
+                                            psRGXConfigureHWPerfBlocksIN->ui32CtrlWord,
+                                            psRGXConfigureHWPerfBlocksIN->ui32ArrayLen,
+                                            psBlockConfigsInt);
+
+RGXConfigureHWPerfBlocks_exit:
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXConfigureHWPerfBlocksOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
 
        return 0;
 }
@@ -425,7 +591,7 @@ PVRSRVBridgeRGXGetHWPerfBvncFeatureFlags(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitRGXHWPERFBridge(void);
-PVRSRV_ERROR DeinitRGXHWPERFBridge(void);
+void DeinitRGXHWPERFBridge(void);
 
 /*
  * Register all RGXHWPERF functions with services
@@ -437,8 +603,12 @@ PVRSRV_ERROR InitRGXHWPERFBridge(void)
                              PVRSRVBridgeRGXCtrlHWPerf, NULL);
 
        SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
-                             PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS,
-                             PVRSRVBridgeRGXConfigEnableHWPerfCounters, NULL);
+                             PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS,
+                             PVRSRVBridgeRGXGetHWPerfBvncFeatureFlags, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
+                             PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGMUXHWPERFCOUNTERS,
+                             PVRSRVBridgeRGXConfigMuxHWPerfCounters, NULL);
 
        SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
                              PVRSRV_BRIDGE_RGXHWPERF_RGXCONTROLHWPERFBLOCKS,
@@ -449,8 +619,8 @@ PVRSRV_ERROR InitRGXHWPERFBridge(void)
                              PVRSRVBridgeRGXConfigCustomCounters, NULL);
 
        SetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
-                             PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS,
-                             PVRSRVBridgeRGXGetHWPerfBvncFeatureFlags, NULL);
+                             PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGUREHWPERFBLOCKS,
+                             PVRSRVBridgeRGXConfigureHWPerfBlocks, NULL);
 
        return PVRSRV_OK;
 }
@@ -458,13 +628,16 @@ PVRSRV_ERROR InitRGXHWPERFBridge(void)
 /*
  * Unregister all rgxhwperf functions with services
  */
-PVRSRV_ERROR DeinitRGXHWPERFBridge(void)
+void DeinitRGXHWPERFBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF, PVRSRV_BRIDGE_RGXHWPERF_RGXCTRLHWPERF);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
-                               PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGENABLEHWPERFCOUNTERS);
+                               PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
+                               PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGMUXHWPERFCOUNTERS);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
                                PVRSRV_BRIDGE_RGXHWPERF_RGXCONTROLHWPERFBLOCKS);
@@ -473,7 +646,6 @@ PVRSRV_ERROR DeinitRGXHWPERFBridge(void)
                                PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGCUSTOMCOUNTERS);
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXHWPERF,
-                               PVRSRV_BRIDGE_RGXHWPERF_RGXGETHWPERFBVNCFEATUREFLAGS);
+                               PVRSRV_BRIDGE_RGXHWPERF_RGXCONFIGUREHWPERFBLOCKS);
 
-       return PVRSRV_OK;
 }
index d0c1df3..afd882c 100644 (file)
@@ -110,7 +110,6 @@ typedef struct PVRSRV_BRIDGE_IN_RGXKICKSYNC2_TAG
        IMG_HANDLE *phUpdateUFODevVarBlock;
        PVRSRV_FENCE hCheckFenceFD;
        PVRSRV_TIMELINE hTimelineFenceFD;
-       IMG_UINT32 ui32ClientCacheOpSeqNum;
        IMG_UINT32 ui32ClientUpdateCount;
        IMG_UINT32 ui32ExtJobRef;
 } __packed PVRSRV_BRIDGE_IN_RGXKICKSYNC2;
index f9041f6..25f68f3 100644 (file)
@@ -179,12 +179,13 @@ PVRSRVBridgeRGXDestroyKickSyncContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyKickSyncContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyKickSyncContextIN->
-                                           hKickSyncContext,
-                                           PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyKickSyncContextIN->
+                                             hKickSyncContext,
+                                             PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT);
        if (unlikely
            ((psRGXDestroyKickSyncContextOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyKickSyncContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psRGXDestroyKickSyncContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -202,6 +203,11 @@ RGXDestroyKickSyncContext_exit:
        return 0;
 }
 
+static_assert(PVRSRV_MAX_DEV_VARS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_DEV_VARS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
                         IMG_UINT8 * psRGXKickSync2IN_UI8,
@@ -226,12 +232,14 @@ PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
-           (psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXKickSync2IN->ui32ClientUpdateCount *
+            sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psRGXKickSync2IN->ui32ClientUpdateCount > PVRSRV_MAX_DEV_VARS))
        {
@@ -239,6 +247,14 @@ PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXKickSync2_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXKickSync2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXKickSync2_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -259,7 +275,7 @@ PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -273,6 +289,9 @@ PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psUpdateUFODevVarBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psUpdateUFODevVarBlockInt, 0,
+                              psRGXKickSync2IN->ui32ClientUpdateCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXKickSync2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
                hUpdateUFODevVarBlockInt2 =
@@ -395,7 +414,6 @@ PVRSRVBridgeRGXKickSync2(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXKickSync2OUT->eError =
            PVRSRVRGXKickSyncKM(psKickSyncContextInt,
-                               psRGXKickSync2IN->ui32ClientCacheOpSeqNum,
                                psRGXKickSync2IN->ui32ClientUpdateCount,
                                psUpdateUFODevVarBlockInt,
                                ui32UpdateDevVarOffsetInt,
@@ -426,7 +444,7 @@ RGXKickSync2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hUpdateUFODevVarBlockInt2[i])
+                       if (psUpdateUFODevVarBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hUpdateUFODevVarBlockInt2[i],
@@ -438,7 +456,10 @@ RGXKickSync2_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXKickSync2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -512,7 +533,7 @@ RGXSetKickSyncContextProperty_exit:
  */
 
 PVRSRV_ERROR InitRGXKICKSYNCBridge(void);
-PVRSRV_ERROR DeinitRGXKICKSYNCBridge(void);
+void DeinitRGXKICKSYNCBridge(void);
 
 /*
  * Register all RGXKICKSYNC functions with services
@@ -541,7 +562,7 @@ PVRSRV_ERROR InitRGXKICKSYNCBridge(void)
 /*
  * Unregister all rgxkicksync functions with services
  */
-PVRSRV_ERROR DeinitRGXKICKSYNCBridge(void)
+void DeinitRGXKICKSYNCBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXKICKSYNC,
@@ -555,5 +576,4 @@ PVRSRV_ERROR DeinitRGXKICKSYNCBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXKICKSYNC,
                                PVRSRV_BRIDGE_RGXKICKSYNC_RGXSETKICKSYNCCONTEXTPROPERTY);
 
-       return PVRSRV_OK;
 }
index 3b710e2..e9a5d42 100644 (file)
@@ -194,7 +194,7 @@ PVRSRVBridgePDumpValCheckPostCommand(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitRGXPDUMPBridge(void);
-PVRSRV_ERROR DeinitRGXPDUMPBridge(void);
+void DeinitRGXPDUMPBridge(void);
 
 /*
  * Register all RGXPDUMP functions with services
@@ -229,7 +229,7 @@ PVRSRV_ERROR InitRGXPDUMPBridge(void)
 /*
  * Unregister all rgxpdump functions with services
  */
-PVRSRV_ERROR DeinitRGXPDUMPBridge(void)
+void DeinitRGXPDUMPBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXPDUMP, PVRSRV_BRIDGE_RGXPDUMP_PDUMPTRACEBUFFER);
@@ -249,5 +249,4 @@ PVRSRV_ERROR DeinitRGXPDUMPBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXPDUMP,
                                PVRSRV_BRIDGE_RGXPDUMP_PDUMPVALCHECKPOSTCOMMAND);
 
-       return PVRSRV_OK;
 }
index a04e082..4cdcb12 100644 (file)
@@ -174,7 +174,7 @@ PVRSRVBridgeRGXDisableRegConfig(IMG_UINT32 ui32DispatchTableEntry,
 
 #if !defined(EXCLUDE_RGXREGCONFIG_BRIDGE)
 PVRSRV_ERROR InitRGXREGCONFIGBridge(void);
-PVRSRV_ERROR DeinitRGXREGCONFIGBridge(void);
+void DeinitRGXREGCONFIGBridge(void);
 
 /*
  * Register all RGXREGCONFIG functions with services
@@ -208,7 +208,7 @@ PVRSRV_ERROR InitRGXREGCONFIGBridge(void)
 /*
  * Unregister all rgxregconfig functions with services
  */
-PVRSRV_ERROR DeinitRGXREGCONFIGBridge(void)
+void DeinitRGXREGCONFIGBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXREGCONFIG,
@@ -226,7 +226,6 @@ PVRSRV_ERROR DeinitRGXREGCONFIGBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXREGCONFIG,
                                PVRSRV_BRIDGE_RGXREGCONFIG_RGXDISABLEREGCONFIG);
 
-       return PVRSRV_OK;
 }
 #else /* EXCLUDE_RGXREGCONFIG_BRIDGE */
 /* This bridge is conditional on EXCLUDE_RGXREGCONFIG_BRIDGE - when defined,
@@ -235,7 +234,6 @@ PVRSRV_ERROR DeinitRGXREGCONFIGBridge(void)
 #define InitRGXREGCONFIGBridge() \
        PVRSRV_OK
 
-#define DeinitRGXREGCONFIGBridge() \
-       PVRSRV_OK
+#define DeinitRGXREGCONFIGBridge()
 
 #endif /* EXCLUDE_RGXREGCONFIG_BRIDGE */
diff --git a/drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/common_rgxsignals_bridge.h b/drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/common_rgxsignals_bridge.h
deleted file mode 100644 (file)
index 296e21b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
-@File
-@Title          Common bridge header for rgxsignals
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Declares common defines and structures used by both the client
-                and server side of the bridge for rgxsignals
-@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.
-*******************************************************************************/
-
-#ifndef COMMON_RGXSIGNALS_BRIDGE_H
-#define COMMON_RGXSIGNALS_BRIDGE_H
-
-#include <powervr/mem_types.h>
-
-#include "img_defs.h"
-#include "img_types.h"
-#include "pvrsrv_error.h"
-
-#include "rgx_bridge.h"
-
-#define PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST                     0
-#define PVRSRV_BRIDGE_RGXSIGNALS_RGXNOTIFYSIGNALUPDATE                 PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST+0
-#define PVRSRV_BRIDGE_RGXSIGNALS_CMD_LAST                      (PVRSRV_BRIDGE_RGXSIGNALS_CMD_FIRST+0)
-
-/*******************************************
-            RGXNotifySignalUpdate
- *******************************************/
-
-/* Bridge in structure for RGXNotifySignalUpdate */
-typedef struct PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE_TAG
-{
-       IMG_DEV_VIRTADDR sDevSignalAddress;
-       IMG_HANDLE hPrivData;
-} __packed PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE;
-
-/* Bridge out structure for RGXNotifySignalUpdate */
-typedef struct PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE_TAG
-{
-       PVRSRV_ERROR eError;
-} __packed PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE;
-
-#endif /* COMMON_RGXSIGNALS_BRIDGE_H */
diff --git a/drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/server_rgxsignals_bridge.c b/drivers/gpu/drm/img/img-rogue/generated/rogue/rgxsignals_bridge/server_rgxsignals_bridge.c
deleted file mode 100644 (file)
index 968e1a7..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*******************************************************************************
-@File
-@Title          Server bridge for rgxsignals
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    Implements the server side of the bridge for rgxsignals
-@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.
-*******************************************************************************/
-
-#include <linux/uaccess.h>
-
-#include "img_defs.h"
-
-#include "rgxsignals.h"
-
-#include "common_rgxsignals_bridge.h"
-
-#include "allocmem.h"
-#include "pvr_debug.h"
-#include "connection_server.h"
-#include "pvr_bridge.h"
-#if defined(SUPPORT_RGX)
-#include "rgx_bridge.h"
-#endif
-#include "srvcore.h"
-#include "handle.h"
-
-#include <linux/slab.h>
-
-#include "rgx_bvnc_defs_km.h"
-
-/* ***************************************************************************
- * Server-side bridge entry points
- */
-
-static IMG_INT
-PVRSRVBridgeRGXNotifySignalUpdate(IMG_UINT32 ui32DispatchTableEntry,
-                                 IMG_UINT8 * psRGXNotifySignalUpdateIN_UI8,
-                                 IMG_UINT8 * psRGXNotifySignalUpdateOUT_UI8,
-                                 CONNECTION_DATA * psConnection)
-{
-       PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE *psRGXNotifySignalUpdateIN =
-           (PVRSRV_BRIDGE_IN_RGXNOTIFYSIGNALUPDATE *)
-           IMG_OFFSET_ADDR(psRGXNotifySignalUpdateIN_UI8, 0);
-       PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE *psRGXNotifySignalUpdateOUT =
-           (PVRSRV_BRIDGE_OUT_RGXNOTIFYSIGNALUPDATE *)
-           IMG_OFFSET_ADDR(psRGXNotifySignalUpdateOUT_UI8, 0);
-
-       IMG_HANDLE hPrivData = psRGXNotifySignalUpdateIN->hPrivData;
-       IMG_HANDLE hPrivDataInt = NULL;
-
-       {
-               PVRSRV_DEVICE_NODE *psDeviceNode = OSGetDevNode(psConnection);
-
-               /* Check that device supports the required feature */
-               if ((psDeviceNode->pfnCheckDeviceFeature) &&
-                   !psDeviceNode->pfnCheckDeviceFeature(psDeviceNode,
-                                                        RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK))
-               {
-                       psRGXNotifySignalUpdateOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
-
-                       goto RGXNotifySignalUpdate_exit;
-               }
-       }
-
-       /* Lock over handle lookup. */
-       LockHandle(psConnection->psHandleBase);
-
-       /* Look up the address from the handle */
-       psRGXNotifySignalUpdateOUT->eError =
-           PVRSRVLookupHandleUnlocked(psConnection->psHandleBase,
-                                      (void **)&hPrivDataInt,
-                                      hPrivData, PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA, IMG_TRUE);
-       if (unlikely(psRGXNotifySignalUpdateOUT->eError != PVRSRV_OK))
-       {
-               UnlockHandle(psConnection->psHandleBase);
-               goto RGXNotifySignalUpdate_exit;
-       }
-       /* Release now we have looked up handles. */
-       UnlockHandle(psConnection->psHandleBase);
-
-       psRGXNotifySignalUpdateOUT->eError =
-           PVRSRVRGXNotifySignalUpdateKM(psConnection, OSGetDevNode(psConnection),
-                                         hPrivDataInt,
-                                         psRGXNotifySignalUpdateIN->sDevSignalAddress);
-
-RGXNotifySignalUpdate_exit:
-
-       /* Lock over handle lookup cleanup. */
-       LockHandle(psConnection->psHandleBase);
-
-       /* Unreference the previously looked up handle */
-       if (hPrivDataInt)
-       {
-               PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
-                                           hPrivData, PVRSRV_HANDLE_TYPE_DEV_PRIV_DATA);
-       }
-       /* Release now we have cleaned up look up handles. */
-       UnlockHandle(psConnection->psHandleBase);
-
-       return 0;
-}
-
-/* ***************************************************************************
- * Server bridge dispatch related glue
- */
-
-PVRSRV_ERROR InitRGXSIGNALSBridge(void);
-PVRSRV_ERROR DeinitRGXSIGNALSBridge(void);
-
-/*
- * Register all RGXSIGNALS functions with services
- */
-PVRSRV_ERROR InitRGXSIGNALSBridge(void)
-{
-
-       SetDispatchTableEntry(PVRSRV_BRIDGE_RGXSIGNALS,
-                             PVRSRV_BRIDGE_RGXSIGNALS_RGXNOTIFYSIGNALUPDATE,
-                             PVRSRVBridgeRGXNotifySignalUpdate, NULL);
-
-       return PVRSRV_OK;
-}
-
-/*
- * Unregister all rgxsignals functions with services
- */
-PVRSRV_ERROR DeinitRGXSIGNALSBridge(void)
-{
-
-       UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXSIGNALS,
-                               PVRSRV_BRIDGE_RGXSIGNALS_RGXNOTIFYSIGNALUPDATE);
-
-       return PVRSRV_OK;
-}
index 8fe76af..b5fedd7 100644 (file)
@@ -80,42 +80,39 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* Bridge in structure for RGXCreateHWRTDataSet */
 typedef struct PVRSRV_BRIDGE_IN_RGXCREATEHWRTDATASET_TAG
 {
-       IMG_DEV_VIRTADDR sPMMlistDevVAddr0;
-       IMG_DEV_VIRTADDR sPMMlistDevVAddr1;
-       IMG_DEV_VIRTADDR sTailPtrsDevVAddr;
-       IMG_DEV_VIRTADDR ssMacrotileArrayDevVAddr0;
-       IMG_DEV_VIRTADDR ssMacrotileArrayDevVAddr1;
-       IMG_DEV_VIRTADDR ssRTCDevVAddr;
-       IMG_DEV_VIRTADDR ssRgnHeaderDevVAddr0;
-       IMG_DEV_VIRTADDR ssRgnHeaderDevVAddr1;
-       IMG_DEV_VIRTADDR ssVHeapTableDevVAddr;
        IMG_UINT64 ui64FlippedMultiSampleCtl;
        IMG_UINT64 ui64MultiSampleCtl;
-       IMG_UINT64 ui64uiRgnHeaderSize;
+       IMG_DEV_VIRTADDR *psMacrotileArrayDevVAddr;
+       IMG_DEV_VIRTADDR *psPMMlistDevVAddr;
+       IMG_DEV_VIRTADDR *psRTCDevVAddr;
+       IMG_DEV_VIRTADDR *psRgnHeaderDevVAddr;
+       IMG_DEV_VIRTADDR *psTailPtrsDevVAddr;
+       IMG_DEV_VIRTADDR *psVHeapTableDevVAddr;
+       IMG_HANDLE *phKmHwRTDataSet;
        IMG_HANDLE *phapsFreeLists;
+       IMG_UINT32 ui32ISPMergeLowerX;
+       IMG_UINT32 ui32ISPMergeLowerY;
+       IMG_UINT32 ui32ISPMergeScaleX;
+       IMG_UINT32 ui32ISPMergeScaleY;
+       IMG_UINT32 ui32ISPMergeUpperX;
+       IMG_UINT32 ui32ISPMergeUpperY;
+       IMG_UINT32 ui32ISPMtileSize;
        IMG_UINT32 ui32MTileStride;
        IMG_UINT32 ui32PPPScreen;
+       IMG_UINT32 ui32RgnHeaderSize;
        IMG_UINT32 ui32TEAA;
        IMG_UINT32 ui32TEMTILE1;
        IMG_UINT32 ui32TEMTILE2;
        IMG_UINT32 ui32TEScreen;
        IMG_UINT32 ui32TPCSize;
        IMG_UINT32 ui32TPCStride;
-       IMG_UINT32 ui32ui32ISPMergeLowerX;
-       IMG_UINT32 ui32ui32ISPMergeLowerY;
-       IMG_UINT32 ui32ui32ISPMergeScaleX;
-       IMG_UINT32 ui32ui32ISPMergeScaleY;
-       IMG_UINT32 ui32ui32ISPMergeUpperX;
-       IMG_UINT32 ui32ui32ISPMergeUpperY;
-       IMG_UINT32 ui32ui32ISPMtileSize;
        IMG_UINT16 ui16MaxRTs;
 } __packed PVRSRV_BRIDGE_IN_RGXCREATEHWRTDATASET;
 
 /* Bridge out structure for RGXCreateHWRTDataSet */
 typedef struct PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATASET_TAG
 {
-       IMG_HANDLE hKmHwRTDataSet0;
-       IMG_HANDLE hKmHwRTDataSet1;
+       IMG_HANDLE *phKmHwRTDataSet;
        PVRSRV_ERROR eError;
 } __packed PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATASET;
 
@@ -264,6 +261,7 @@ typedef struct PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT_TAG
        IMG_UINT32 ui32PackedCCBSizeU8888;
        IMG_UINT32 ui32Priority;
        IMG_UINT32 ui32StaticRenderContextStateSize;
+       IMG_UINT32 ui32ui32CallStackDepth;
 } __packed PVRSRV_BRIDGE_IN_RGXCREATERENDERCONTEXT;
 
 /* Bridge out structure for RGXCreateRenderContext */
@@ -362,16 +360,15 @@ typedef struct PVRSRV_BRIDGE_IN_RGXKICKTA3D2_TAG
        IMG_UINT32 ui323DCmdSize;
        IMG_UINT32 ui323DPRCmdSize;
        IMG_UINT32 ui32Client3DUpdateCount;
-       IMG_UINT32 ui32ClientCacheOpSeqNum;
        IMG_UINT32 ui32ClientTAFenceCount;
        IMG_UINT32 ui32ClientTAUpdateCount;
        IMG_UINT32 ui32ExtJobRef;
-       IMG_UINT32 ui32FRFenceUFOSyncOffset;
-       IMG_UINT32 ui32FRFenceValue;
        IMG_UINT32 ui32NumberOfDrawCalls;
        IMG_UINT32 ui32NumberOfIndices;
        IMG_UINT32 ui32NumberOfMRTs;
        IMG_UINT32 ui32PDumpFlags;
+       IMG_UINT32 ui32PRFenceUFOSyncOffset;
+       IMG_UINT32 ui32PRFenceValue;
        IMG_UINT32 ui32RenderTargetSize;
        IMG_UINT32 ui32SyncPMRCount;
        IMG_UINT32 ui32TACmdSize;
index d192c53..44300ec 100644 (file)
@@ -65,19 +65,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Server-side bridge entry points
  */
 
-static PVRSRV_ERROR _RGXCreateHWRTDataSetpsKmHwRTDataSet0IntRelease(void *pvData)
+static PVRSRV_ERROR _RGXCreateHWRTDataSetpsKmHwRTDataSetIntRelease(void *pvData)
 {
        PVRSRV_ERROR eError;
        eError = RGXDestroyHWRTDataSet((RGX_KM_HW_RT_DATASET *) pvData);
        return eError;
 }
 
-static PVRSRV_ERROR _RGXCreateHWRTDataSetpsKmHwRTDataSet1IntRelease(void *pvData)
-{
-       PVRSRV_ERROR eError;
-       eError = RGXDestroyHWRTDataSet((RGX_KM_HW_RT_DATASET *) pvData);
-       return eError;
-}
+static_assert(RGXMKIF_NUM_GEOMDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_GEOMDATAS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_RTDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_RTDATAS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_RTDATA_FREELISTS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_RTDATA_FREELISTS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_GEOMDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_GEOMDATAS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_RTDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_RTDATAS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_RTDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_RTDATAS must not be larger than IMG_UINT32_MAX");
+static_assert(RGXMKIF_NUM_GEOMDATAS <= IMG_UINT32_MAX,
+             "RGXMKIF_NUM_GEOMDATAS must not be larger than IMG_UINT32_MAX");
 
 static IMG_INT
 PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
@@ -92,10 +100,16 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
            (PVRSRV_BRIDGE_OUT_RGXCREATEHWRTDATASET *)
            IMG_OFFSET_ADDR(psRGXCreateHWRTDataSetOUT_UI8, 0);
 
+       IMG_DEV_VIRTADDR *sVHeapTableDevVAddrInt = NULL;
+       IMG_DEV_VIRTADDR *sPMMlistDevVAddrInt = NULL;
        RGX_FREELIST **psapsFreeListsInt = NULL;
        IMG_HANDLE *hapsFreeListsInt2 = NULL;
-       RGX_KM_HW_RT_DATASET *psKmHwRTDataSet0Int = NULL;
-       RGX_KM_HW_RT_DATASET *psKmHwRTDataSet1Int = NULL;
+       IMG_DEV_VIRTADDR *sTailPtrsDevVAddrInt = NULL;
+       IMG_DEV_VIRTADDR *sMacrotileArrayDevVAddrInt = NULL;
+       IMG_DEV_VIRTADDR *sRgnHeaderDevVAddrInt = NULL;
+       IMG_DEV_VIRTADDR *sRTCDevVAddrInt = NULL;
+       RGX_KM_HW_RT_DATASET **psKmHwRTDataSetInt = NULL;
+       IMG_HANDLE *hKmHwRTDataSetInt2 = NULL;
 
        IMG_UINT32 ui32NextOffset = 0;
        IMG_BYTE *pArrayArgsBuffer = NULL;
@@ -103,9 +117,28 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *)) +
-           (RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(RGX_FREELIST *)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATAS * sizeof(RGX_KM_HW_RT_DATASET *)) +
+           ((IMG_UINT64) RGXMKIF_NUM_RTDATAS * sizeof(IMG_HANDLE)) + 0;
+
+       psRGXCreateHWRTDataSetOUT->phKmHwRTDataSet = psRGXCreateHWRTDataSetIN->phKmHwRTDataSet;
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXCreateHWRTDataSet_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
 
        if (ui32BufferSize != 0)
        {
@@ -127,7 +160,7 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -138,27 +171,160 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
        }
 
        {
+               sVHeapTableDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sVHeapTableDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psVHeapTableDevVAddr,
+                    RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
+               sPMMlistDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sPMMlistDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psPMMlistDevVAddr,
+                    RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
                psapsFreeListsInt =
                    (RGX_FREELIST **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
-               ui32NextOffset += RGXFW_MAX_FREELISTS * sizeof(RGX_FREELIST *);
+               OSCachedMemSet(psapsFreeListsInt, 0,
+                              RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(RGX_FREELIST *));
+               ui32NextOffset += RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(RGX_FREELIST *);
                hapsFreeListsInt2 =
                    (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
-               ui32NextOffset += RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE);
+               ui32NextOffset += RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(IMG_HANDLE);
        }
 
        /* Copy the data over */
-       if (RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE) > 0)
+       if (RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(IMG_HANDLE) > 0)
        {
                if (OSCopyFromUser
                    (NULL, hapsFreeListsInt2,
                     (const void __user *)psRGXCreateHWRTDataSetIN->phapsFreeLists,
-                    RGXFW_MAX_FREELISTS * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+                    RGXMKIF_NUM_RTDATA_FREELISTS * sizeof(IMG_HANDLE)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
+               sTailPtrsDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sTailPtrsDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psTailPtrsDevVAddr,
+                    RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
+               sMacrotileArrayDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sMacrotileArrayDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psMacrotileArrayDevVAddr,
+                    RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
+               sRgnHeaderDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sRgnHeaderDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psRgnHeaderDevVAddr,
+                    RGXMKIF_NUM_RTDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
+       {
+               sRTCDevVAddrInt =
+                   (IMG_DEV_VIRTADDR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR);
+       }
+
+       /* Copy the data over */
+       if (RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, sRTCDevVAddrInt,
+                    (const void __user *)psRGXCreateHWRTDataSetIN->psRTCDevVAddr,
+                    RGXMKIF_NUM_GEOMDATAS * sizeof(IMG_DEV_VIRTADDR)) != PVRSRV_OK)
                {
                        psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
 
                        goto RGXCreateHWRTDataSet_exit;
                }
        }
+       if (IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset) != NULL)
+       {
+               psKmHwRTDataSetInt =
+                   (RGX_KM_HW_RT_DATASET **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psKmHwRTDataSetInt, 0,
+                              RGXMKIF_NUM_RTDATAS * sizeof(RGX_KM_HW_RT_DATASET *));
+               ui32NextOffset += RGXMKIF_NUM_RTDATAS * sizeof(RGX_KM_HW_RT_DATASET *);
+               hKmHwRTDataSetInt2 =
+                   (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += RGXMKIF_NUM_RTDATAS * sizeof(IMG_HANDLE);
+       }
 
        /* Lock over handle lookup. */
        LockHandle(psConnection->psHandleBase);
@@ -166,7 +332,7 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
        {
                IMG_UINT32 i;
 
-               for (i = 0; i < RGXFW_MAX_FREELISTS; i++)
+               for (i = 0; i < RGXMKIF_NUM_RTDATA_FREELISTS; i++)
                {
                        /* Look up the address from the handle */
                        psRGXCreateHWRTDataSetOUT->eError =
@@ -186,36 +352,32 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXCreateHWRTDataSetOUT->eError =
            RGXCreateHWRTDataSet(psConnection, OSGetDevNode(psConnection),
-                                psRGXCreateHWRTDataSetIN->ssVHeapTableDevVAddr,
-                                psRGXCreateHWRTDataSetIN->sPMMlistDevVAddr0,
-                                psRGXCreateHWRTDataSetIN->sPMMlistDevVAddr1,
+                                sVHeapTableDevVAddrInt,
+                                sPMMlistDevVAddrInt,
                                 psapsFreeListsInt,
                                 psRGXCreateHWRTDataSetIN->ui32PPPScreen,
                                 psRGXCreateHWRTDataSetIN->ui64MultiSampleCtl,
                                 psRGXCreateHWRTDataSetIN->ui64FlippedMultiSampleCtl,
                                 psRGXCreateHWRTDataSetIN->ui32TPCStride,
-                                psRGXCreateHWRTDataSetIN->sTailPtrsDevVAddr,
+                                sTailPtrsDevVAddrInt,
                                 psRGXCreateHWRTDataSetIN->ui32TPCSize,
                                 psRGXCreateHWRTDataSetIN->ui32TEScreen,
                                 psRGXCreateHWRTDataSetIN->ui32TEAA,
                                 psRGXCreateHWRTDataSetIN->ui32TEMTILE1,
                                 psRGXCreateHWRTDataSetIN->ui32TEMTILE2,
                                 psRGXCreateHWRTDataSetIN->ui32MTileStride,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeLowerX,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeLowerY,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeUpperX,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeUpperY,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeScaleX,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMergeScaleY,
-                                psRGXCreateHWRTDataSetIN->ssMacrotileArrayDevVAddr0,
-                                psRGXCreateHWRTDataSetIN->ssMacrotileArrayDevVAddr1,
-                                psRGXCreateHWRTDataSetIN->ssRgnHeaderDevVAddr0,
-                                psRGXCreateHWRTDataSetIN->ssRgnHeaderDevVAddr1,
-                                psRGXCreateHWRTDataSetIN->ssRTCDevVAddr,
-                                psRGXCreateHWRTDataSetIN->ui64uiRgnHeaderSize,
-                                psRGXCreateHWRTDataSetIN->ui32ui32ISPMtileSize,
-                                psRGXCreateHWRTDataSetIN->ui16MaxRTs,
-                                &psKmHwRTDataSet0Int, &psKmHwRTDataSet1Int);
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeLowerX,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeLowerY,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeUpperX,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeUpperY,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeScaleX,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMergeScaleY,
+                                sMacrotileArrayDevVAddrInt,
+                                sRgnHeaderDevVAddrInt,
+                                sRTCDevVAddrInt,
+                                psRGXCreateHWRTDataSetIN->ui32RgnHeaderSize,
+                                psRGXCreateHWRTDataSetIN->ui32ISPMtileSize,
+                                psRGXCreateHWRTDataSetIN->ui16MaxRTs, psKmHwRTDataSetInt);
        /* Exit early if bridged call fails */
        if (unlikely(psRGXCreateHWRTDataSetOUT->eError != PVRSRV_OK))
        {
@@ -224,38 +386,47 @@ PVRSRVBridgeRGXCreateHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
 
        /* Lock over handle creation. */
        LockHandle(psConnection->psHandleBase);
-
-       psRGXCreateHWRTDataSetOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
-                                                                     &psRGXCreateHWRTDataSetOUT->
-                                                                     hKmHwRTDataSet0,
-                                                                     (void *)psKmHwRTDataSet0Int,
-                                                                     PVRSRV_HANDLE_TYPE_RGX_KM_HW_RT_DATASET,
-                                                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
-                                                                     (PFN_HANDLE_RELEASE) &
-                                                                     _RGXCreateHWRTDataSetpsKmHwRTDataSet0IntRelease);
-       if (unlikely(psRGXCreateHWRTDataSetOUT->eError != PVRSRV_OK))
+       if (hKmHwRTDataSetInt2)
        {
-               UnlockHandle(psConnection->psHandleBase);
-               goto RGXCreateHWRTDataSet_exit;
-       }
+               IMG_UINT32 i;
 
-       psRGXCreateHWRTDataSetOUT->eError = PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
-                                                                     &psRGXCreateHWRTDataSetOUT->
-                                                                     hKmHwRTDataSet1,
-                                                                     (void *)psKmHwRTDataSet1Int,
-                                                                     PVRSRV_HANDLE_TYPE_RGX_KM_HW_RT_DATASET,
-                                                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
-                                                                     (PFN_HANDLE_RELEASE) &
-                                                                     _RGXCreateHWRTDataSetpsKmHwRTDataSet1IntRelease);
-       if (unlikely(psRGXCreateHWRTDataSetOUT->eError != PVRSRV_OK))
-       {
-               UnlockHandle(psConnection->psHandleBase);
-               goto RGXCreateHWRTDataSet_exit;
-       }
+               for (i = 0; i < RGXMKIF_NUM_RTDATAS; i++)
+               {
 
+                       psRGXCreateHWRTDataSetOUT->eError =
+                           PVRSRVAllocHandleUnlocked(psConnection->psHandleBase,
+                                                     &hKmHwRTDataSetInt2[i],
+                                                     (void *)psKmHwRTDataSetInt[i],
+                                                     PVRSRV_HANDLE_TYPE_RGX_KM_HW_RT_DATASET,
+                                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                                     (PFN_HANDLE_RELEASE) &
+                                                     _RGXCreateHWRTDataSetpsKmHwRTDataSetIntRelease);
+                       if (unlikely(psRGXCreateHWRTDataSetOUT->eError != PVRSRV_OK))
+                       {
+                               UnlockHandle(psConnection->psHandleBase);
+                               goto RGXCreateHWRTDataSet_exit;
+                       }
+
+               }
+       }
        /* Release now we have created handles. */
        UnlockHandle(psConnection->psHandleBase);
 
+       /* If dest ptr is non-null and we have data to copy */
+       if ((hKmHwRTDataSetInt2) && ((RGXMKIF_NUM_RTDATAS * sizeof(RGX_KM_HW_RT_DATASET *)) > 0))
+       {
+               if (unlikely
+                   (OSCopyToUser
+                    (NULL, (void __user *)psRGXCreateHWRTDataSetOUT->phKmHwRTDataSet,
+                     hKmHwRTDataSetInt2,
+                     (RGXMKIF_NUM_RTDATAS * sizeof(RGX_KM_HW_RT_DATASET *))) != PVRSRV_OK))
+               {
+                       psRGXCreateHWRTDataSetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto RGXCreateHWRTDataSet_exit;
+               }
+       }
+
 RGXCreateHWRTDataSet_exit:
 
        /* Lock over handle lookup cleanup. */
@@ -265,11 +436,11 @@ RGXCreateHWRTDataSet_exit:
        {
                IMG_UINT32 i;
 
-               for (i = 0; i < RGXFW_MAX_FREELISTS; i++)
+               for (i = 0; i < RGXMKIF_NUM_RTDATA_FREELISTS; i++)
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hapsFreeListsInt2[i])
+                       if (psapsFreeListsInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hapsFreeListsInt2[i],
@@ -282,18 +453,27 @@ RGXCreateHWRTDataSet_exit:
 
        if (psRGXCreateHWRTDataSetOUT->eError != PVRSRV_OK)
        {
-               if (psKmHwRTDataSet0Int)
                {
-                       RGXDestroyHWRTDataSet(psKmHwRTDataSet0Int);
-               }
-               if (psKmHwRTDataSet1Int)
-               {
-                       RGXDestroyHWRTDataSet(psKmHwRTDataSet1Int);
+                       IMG_UINT32 i;
+
+                       if (hKmHwRTDataSetInt2)
+                       {
+                               for (i = 0; i < RGXMKIF_NUM_RTDATAS; i++)
+                               {
+                                       if (hKmHwRTDataSetInt2[i])
+                                       {
+                                               RGXDestroyHWRTDataSet(hKmHwRTDataSetInt2[i]);
+                                       }
+                               }
+                       }
                }
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXCreateHWRTDataSetOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -322,11 +502,14 @@ PVRSRVBridgeRGXDestroyHWRTDataSet(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyHWRTDataSetOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyHWRTDataSetIN->hKmHwRTDataSet,
-                                           PVRSRV_HANDLE_TYPE_RGX_KM_HW_RT_DATASET);
-       if (unlikely((psRGXDestroyHWRTDataSetOUT->eError != PVRSRV_OK) &&
-                    (psRGXDestroyHWRTDataSetOUT->eError != PVRSRV_ERROR_RETRY)))
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyHWRTDataSetIN->
+                                             hKmHwRTDataSet,
+                                             PVRSRV_HANDLE_TYPE_RGX_KM_HW_RT_DATASET);
+       if (unlikely
+           ((psRGXDestroyHWRTDataSetOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyHWRTDataSetOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+            && (psRGXDestroyHWRTDataSetOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: %s",
@@ -473,11 +656,14 @@ PVRSRVBridgeRGXDestroyZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyZSBufferOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyZSBufferIN->hsZSBufferMemDesc,
-                                           PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
-       if (unlikely((psRGXDestroyZSBufferOUT->eError != PVRSRV_OK) &&
-                    (psRGXDestroyZSBufferOUT->eError != PVRSRV_ERROR_RETRY)))
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyZSBufferIN->
+                                             hsZSBufferMemDesc,
+                                             PVRSRV_HANDLE_TYPE_RGX_FWIF_ZSBUFFER);
+       if (unlikely
+           ((psRGXDestroyZSBufferOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyZSBufferOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+            && (psRGXDestroyZSBufferOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: %s",
@@ -605,10 +791,11 @@ PVRSRVBridgeRGXUnpopulateZSBuffer(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXUnpopulateZSBufferOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXUnpopulateZSBufferIN->hsPopulation,
-                                           PVRSRV_HANDLE_TYPE_RGX_POPULATION);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXUnpopulateZSBufferIN->hsPopulation,
+                                             PVRSRV_HANDLE_TYPE_RGX_POPULATION);
        if (unlikely((psRGXUnpopulateZSBufferOUT->eError != PVRSRV_OK) &&
+                    (psRGXUnpopulateZSBufferOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psRGXUnpopulateZSBufferOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -792,10 +979,11 @@ PVRSRVBridgeRGXDestroyFreeList(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyFreeListOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyFreeListIN->hCleanupCookie,
-                                           PVRSRV_HANDLE_TYPE_RGX_FREELIST);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyFreeListIN->hCleanupCookie,
+                                             PVRSRV_HANDLE_TYPE_RGX_FREELIST);
        if (unlikely((psRGXDestroyFreeListOUT->eError != PVRSRV_OK) &&
+                    (psRGXDestroyFreeListOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psRGXDestroyFreeListOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -820,6 +1008,11 @@ static PVRSRV_ERROR _RGXCreateRenderContextpsRenderContextIntRelease(void *pvDat
        return eError;
 }
 
+static_assert(RGXFWIF_RF_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_RF_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_STATIC_RENDERCONTEXT_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_STATIC_RENDERCONTEXT_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
                                   IMG_UINT8 * psRGXCreateRenderContextIN_UI8,
@@ -845,9 +1038,11 @@ PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXCreateRenderContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE)) +
-           (psRGXCreateRenderContextIN->ui32StaticRenderContextStateSize * sizeof(IMG_BYTE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXCreateRenderContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXCreateRenderContextIN->ui32StaticRenderContextStateSize *
+            sizeof(IMG_BYTE)) + 0;
 
        if (unlikely(psRGXCreateRenderContextIN->ui32FrameworkCmdSize > RGXFWIF_RF_CMD_SIZE))
        {
@@ -863,6 +1058,14 @@ PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXCreateRenderContext_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXCreateRenderContextOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXCreateRenderContext_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -883,7 +1086,7 @@ PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -957,6 +1160,7 @@ PVRSRVBridgeRGXCreateRenderContext(IMG_UINT32 ui32DispatchTableEntry,
            PVRSRVRGXCreateRenderContextKM(psConnection, OSGetDevNode(psConnection),
                                           psRGXCreateRenderContextIN->ui32Priority,
                                           psRGXCreateRenderContextIN->sVDMCallStackAddr,
+                                          psRGXCreateRenderContextIN->ui32ui32CallStackDepth,
                                           psRGXCreateRenderContextIN->ui32FrameworkCmdSize,
                                           ui8FrameworkCmdInt,
                                           hPrivDataInt,
@@ -1018,7 +1222,10 @@ RGXCreateRenderContext_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXCreateRenderContextOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -1047,12 +1254,13 @@ PVRSRVBridgeRGXDestroyRenderContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyRenderContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyRenderContextIN->
-                                           hCleanupCookie,
-                                           PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyRenderContextIN->
+                                             hCleanupCookie,
+                                             PVRSRV_HANDLE_TYPE_RGX_SERVER_RENDER_CONTEXT);
        if (unlikely
            ((psRGXDestroyRenderContextOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyRenderContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psRGXDestroyRenderContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1179,6 +1387,25 @@ RGXRenderContextStalled_exit:
        return 0;
 }
 
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
                         IMG_UINT8 * psRGXKickTA3D2IN_UI8,
@@ -1226,27 +1453,31 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE)) +
-           (psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE)) +
-           (psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE)) +
-           (psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
-           (psRGXKickTA3D2IN->ui32TACmdSize * sizeof(IMG_BYTE)) +
-           (psRGXKickTA3D2IN->ui323DPRCmdSize * sizeof(IMG_BYTE)) +
-           (psRGXKickTA3D2IN->ui323DCmdSize * sizeof(IMG_BYTE)) +
-           (psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
-           (psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(PMR *)) +
-           (psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAFenceCount *
+            sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAUpdateCount *
+            sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32Client3DUpdateCount *
+            sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32TACmdSize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui323DPRCmdSize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui323DCmdSize * sizeof(IMG_BYTE)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(PMR *)) +
+           ((IMG_UINT64) psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
 
        if (unlikely(psRGXKickTA3D2IN->ui32ClientTAFenceCount > PVRSRV_MAX_SYNCS))
        {
@@ -1290,6 +1521,14 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXKickTA3D2_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXKickTA3D2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXKickTA3D2_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -1310,7 +1549,7 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -1324,6 +1563,9 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psClientTAFenceSyncPrimBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psClientTAFenceSyncPrimBlockInt, 0,
+                              psRGXKickTA3D2IN->ui32ClientTAFenceCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXKickTA3D2IN->ui32ClientTAFenceCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
                hClientTAFenceSyncPrimBlockInt2 =
@@ -1388,6 +1630,9 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psClientTAUpdateSyncPrimBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psClientTAUpdateSyncPrimBlockInt, 0,
+                              psRGXKickTA3D2IN->ui32ClientTAUpdateCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXKickTA3D2IN->ui32ClientTAUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
                hClientTAUpdateSyncPrimBlockInt2 =
@@ -1452,6 +1697,9 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psClient3DUpdateSyncPrimBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psClient3DUpdateSyncPrimBlockInt, 0,
+                              psRGXKickTA3D2IN->ui32Client3DUpdateCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXKickTA3D2IN->ui32Client3DUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *);
                hClient3DUpdateSyncPrimBlockInt2 =
@@ -1633,6 +1881,8 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
        if (psRGXKickTA3D2IN->ui32SyncPMRCount != 0)
        {
                psSyncPMRsInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psSyncPMRsInt, 0,
+                              psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(PMR *));
                ui32NextOffset += psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(PMR *);
                hSyncPMRsInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psRGXKickTA3D2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
@@ -1808,7 +2058,6 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXKickTA3D2OUT->eError =
            PVRSRVRGXKickTA3DKM(psRenderContextInt,
-                               psRGXKickTA3D2IN->ui32ClientCacheOpSeqNum,
                                psRGXKickTA3D2IN->ui32ClientTAFenceCount,
                                psClientTAFenceSyncPrimBlockInt,
                                ui32ClientTAFenceSyncOffsetInt,
@@ -1822,8 +2071,8 @@ PVRSRVBridgeRGXKickTA3D2(IMG_UINT32 ui32DispatchTableEntry,
                                ui32Client3DUpdateSyncOffsetInt,
                                ui32Client3DUpdateValueInt,
                                psPRFenceUFOSyncPrimBlockInt,
-                               psRGXKickTA3D2IN->ui32FRFenceUFOSyncOffset,
-                               psRGXKickTA3D2IN->ui32FRFenceValue,
+                               psRGXKickTA3D2IN->ui32PRFenceUFOSyncOffset,
+                               psRGXKickTA3D2IN->ui32PRFenceValue,
                                psRGXKickTA3D2IN->hCheckFence,
                                psRGXKickTA3D2IN->hUpdateTimeline,
                                &psRGXKickTA3D2OUT->hUpdateFence,
@@ -1876,7 +2125,7 @@ RGXKickTA3D2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hClientTAFenceSyncPrimBlockInt2[i])
+                       if (psClientTAFenceSyncPrimBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hClientTAFenceSyncPrimBlockInt2[i],
@@ -1893,7 +2142,7 @@ RGXKickTA3D2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hClientTAUpdateSyncPrimBlockInt2[i])
+                       if (psClientTAUpdateSyncPrimBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hClientTAUpdateSyncPrimBlockInt2[i],
@@ -1910,7 +2159,7 @@ RGXKickTA3D2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hClient3DUpdateSyncPrimBlockInt2[i])
+                       if (psClient3DUpdateSyncPrimBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hClient3DUpdateSyncPrimBlockInt2[i],
@@ -1971,7 +2220,7 @@ RGXKickTA3D2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hSyncPMRsInt2[i])
+                       if (psSyncPMRsInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hSyncPMRsInt2[i],
@@ -1983,7 +2232,10 @@ RGXKickTA3D2_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXKickTA3D2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -2057,7 +2309,7 @@ RGXSetRenderContextProperty_exit:
  */
 
 PVRSRV_ERROR InitRGXTA3DBridge(void);
-PVRSRV_ERROR DeinitRGXTA3DBridge(void);
+void DeinitRGXTA3DBridge(void);
 
 /*
  * Register all RGXTA3D functions with services
@@ -2115,7 +2367,7 @@ PVRSRV_ERROR InitRGXTA3DBridge(void)
 /*
  * Unregister all rgxta3d functions with services
  */
-PVRSRV_ERROR DeinitRGXTA3DBridge(void)
+void DeinitRGXTA3DBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D, PVRSRV_BRIDGE_RGXTA3D_RGXCREATEHWRTDATASET);
@@ -2151,5 +2403,4 @@ PVRSRV_ERROR DeinitRGXTA3DBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTA3D,
                                PVRSRV_BRIDGE_RGXTA3D_RGXSETRENDERCONTEXTPROPERTY);
 
-       return PVRSRV_OK;
 }
index ce97a15..99e6239 100644 (file)
@@ -126,7 +126,7 @@ PVRSRVBridgeRGXQueryTimer(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitRGXTIMERQUERYBridge(void);
-PVRSRV_ERROR DeinitRGXTIMERQUERYBridge(void);
+void DeinitRGXTIMERQUERYBridge(void);
 
 /*
  * Register all RGXTIMERQUERY functions with services
@@ -152,7 +152,7 @@ PVRSRV_ERROR InitRGXTIMERQUERYBridge(void)
 /*
  * Unregister all rgxtimerquery functions with services
  */
-PVRSRV_ERROR DeinitRGXTIMERQUERYBridge(void)
+void DeinitRGXTIMERQUERYBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTIMERQUERY,
@@ -164,5 +164,4 @@ PVRSRV_ERROR DeinitRGXTIMERQUERYBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTIMERQUERY,
                                PVRSRV_BRIDGE_RGXTIMERQUERY_RGXQUERYTIMER);
 
-       return PVRSRV_OK;
 }
index c765627..9489dda 100644 (file)
@@ -72,10 +72,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* Bridge in structure for RGXTDMCreateTransferContext */
 typedef struct PVRSRV_BRIDGE_IN_RGXTDMCREATETRANSFERCONTEXT_TAG
 {
+       IMG_UINT64 ui64RobustnessAddress;
        IMG_HANDLE hPrivData;
        IMG_BYTE *pui8FrameworkCmd;
        IMG_UINT32 ui32ContextFlags;
-       IMG_UINT32 ui32FrameworkCmdize;
+       IMG_UINT32 ui32FrameworkCmdSize;
        IMG_UINT32 ui32PackedCCBSizeU88;
        IMG_UINT32 ui32Priority;
 } __packed PVRSRV_BRIDGE_IN_RGXTDMCREATETRANSFERCONTEXT;
@@ -157,7 +158,6 @@ typedef struct PVRSRV_BRIDGE_IN_RGXTDMSUBMITTRANSFER2_TAG
        PVRSRV_TIMELINE hUpdateTimeline;
        IMG_UINT32 ui32Characteristic1;
        IMG_UINT32 ui32Characteristic2;
-       IMG_UINT32 ui32ClientCacheOpSeqNum;
        IMG_UINT32 ui32ClientUpdateCount;
        IMG_UINT32 ui32CommandSize;
        IMG_UINT32 ui32ExternalJobReference;
index 5f2c276..f73bb90 100644 (file)
@@ -74,6 +74,9 @@ static PVRSRV_ERROR _RGXTDMCreateTransferContextpsTransferContextIntRelease(void
        return eError;
 }
 
+static_assert(RGXFWIF_RF_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_RF_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                                        IMG_UINT8 * psRGXTDMCreateTransferContextIN_UI8,
@@ -98,10 +101,12 @@ PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize *
+            sizeof(IMG_BYTE)) + 0;
 
-       if (unlikely(psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize > RGXFWIF_RF_CMD_SIZE))
+       if (unlikely(psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize > RGXFWIF_RF_CMD_SIZE))
        {
                psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
                goto RGXTDMCreateTransferContext_exit;
@@ -121,6 +126,14 @@ PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXTDMCreateTransferContext_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -142,7 +155,7 @@ PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -153,20 +166,20 @@ PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
-       if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize != 0)
+       if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize != 0)
        {
                ui8FrameworkCmdInt = (IMG_BYTE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset +=
-                   psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE);
+                   psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE);
        }
 
        /* Copy the data over */
-       if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE) > 0)
+       if (psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE) > 0)
        {
                if (OSCopyFromUser
                    (NULL, ui8FrameworkCmdInt,
                     (const void __user *)psRGXTDMCreateTransferContextIN->pui8FrameworkCmd,
-                    psRGXTDMCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) !=
+                    psRGXTDMCreateTransferContextIN->ui32FrameworkCmdSize * sizeof(IMG_BYTE)) !=
                    PVRSRV_OK)
                {
                        psRGXTDMCreateTransferContextOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
@@ -195,12 +208,13 @@ PVRSRVBridgeRGXTDMCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
            PVRSRVRGXTDMCreateTransferContextKM(psConnection, OSGetDevNode(psConnection),
                                                psRGXTDMCreateTransferContextIN->ui32Priority,
                                                psRGXTDMCreateTransferContextIN->
-                                               ui32FrameworkCmdize, ui8FrameworkCmdInt,
+                                               ui32FrameworkCmdSize, ui8FrameworkCmdInt,
                                                hPrivDataInt,
                                                psRGXTDMCreateTransferContextIN->
                                                ui32PackedCCBSizeU88,
                                                psRGXTDMCreateTransferContextIN->ui32ContextFlags,
-                                               &psTransferContextInt);
+                                               psRGXTDMCreateTransferContextIN->
+                                               ui64RobustnessAddress, &psTransferContextInt);
        /* Exit early if bridged call fails */
        if (unlikely(psRGXTDMCreateTransferContextOUT->eError != PVRSRV_OK))
        {
@@ -250,7 +264,10 @@ RGXTDMCreateTransferContext_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXTDMCreateTransferContextOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -293,12 +310,13 @@ PVRSRVBridgeRGXTDMDestroyTransferContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXTDMDestroyTransferContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXTDMDestroyTransferContextIN->
-                                           hTransferContext,
-                                           PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXTDMDestroyTransferContextIN->
+                                             hTransferContext,
+                                             PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_TDM_CONTEXT);
        if (unlikely
            ((psRGXTDMDestroyTransferContextOUT->eError != PVRSRV_OK)
+            && (psRGXTDMDestroyTransferContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psRGXTDMDestroyTransferContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -458,6 +476,15 @@ RGXTDMNotifyWriteOffsetUpdate_exit:
        return 0;
 }
 
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                                  IMG_UINT8 * psRGXTDMSubmitTransfer2IN_UI8,
@@ -489,16 +516,18 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(SYNC_PRIMITIVE_BLOCK *)) +
-           (psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
-           (psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
-           (psRGXTDMSubmitTransfer2IN->ui32CommandSize * sizeof(IMG_UINT8)) +
-           (psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
-           (psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *)) +
-           (psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount *
+            sizeof(SYNC_PRIMITIVE_BLOCK *)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_HANDLE)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32CommandSize * sizeof(IMG_UINT8)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *)) +
+           ((IMG_UINT64) psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
 
        if (unlikely(psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount > PVRSRV_MAX_SYNCS))
        {
@@ -533,6 +562,14 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                }
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXTDMSubmitTransfer2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXTDMSubmitTransfer2_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -553,7 +590,7 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -567,6 +604,9 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        {
                psUpdateUFOSyncPrimBlockInt =
                    (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psUpdateUFOSyncPrimBlockInt, 0,
+                              psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount *
+                              sizeof(SYNC_PRIMITIVE_BLOCK *));
                ui32NextOffset +=
                    psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount *
                    sizeof(SYNC_PRIMITIVE_BLOCK *);
@@ -698,6 +738,8 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        if (psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount != 0)
        {
                psSyncPMRsInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psSyncPMRsInt, 0,
+                              psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *));
                ui32NextOffset += psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *);
                hSyncPMRsInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psRGXTDMSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
@@ -776,7 +818,6 @@ PVRSRVBridgeRGXTDMSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        psRGXTDMSubmitTransfer2OUT->eError =
            PVRSRVRGXTDMSubmitTransferKM(psTransferContextInt,
                                         psRGXTDMSubmitTransfer2IN->ui32PDumpFlags,
-                                        psRGXTDMSubmitTransfer2IN->ui32ClientCacheOpSeqNum,
                                         psRGXTDMSubmitTransfer2IN->ui32ClientUpdateCount,
                                         psUpdateUFOSyncPrimBlockInt,
                                         ui32UpdateSyncOffsetInt,
@@ -816,7 +857,7 @@ RGXTDMSubmitTransfer2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hUpdateUFOSyncPrimBlockInt2[i])
+                       if (psUpdateUFOSyncPrimBlockInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hUpdateUFOSyncPrimBlockInt2[i],
@@ -833,7 +874,7 @@ RGXTDMSubmitTransfer2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hSyncPMRsInt2[i])
+                       if (psSyncPMRsInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hSyncPMRsInt2[i],
@@ -845,7 +886,10 @@ RGXTDMSubmitTransfer2_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXTDMSubmitTransfer2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -994,10 +1038,11 @@ PVRSRVBridgeRGXTDMReleaseSharedMemory(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXTDMReleaseSharedMemoryOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXTDMReleaseSharedMemoryIN->hPMRMem,
-                                           PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXTDMReleaseSharedMemoryIN->hPMRMem,
+                                             PVRSRV_HANDLE_TYPE_PMR_LOCAL_EXPORT_HANDLE);
        if (unlikely((psRGXTDMReleaseSharedMemoryOUT->eError != PVRSRV_OK) &&
+                    (psRGXTDMReleaseSharedMemoryOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psRGXTDMReleaseSharedMemoryOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1094,7 +1139,7 @@ RGXTDMSetTransferContextProperty_exit:
  */
 
 PVRSRV_ERROR InitRGXTQ2Bridge(void);
-PVRSRV_ERROR DeinitRGXTQ2Bridge(void);
+void DeinitRGXTQ2Bridge(void);
 
 /*
  * Register all RGXTQ2 functions with services
@@ -1137,7 +1182,7 @@ PVRSRV_ERROR InitRGXTQ2Bridge(void)
 /*
  * Unregister all rgxtq2 functions with services
  */
-PVRSRV_ERROR DeinitRGXTQ2Bridge(void)
+void DeinitRGXTQ2Bridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2,
@@ -1162,5 +1207,4 @@ PVRSRV_ERROR DeinitRGXTQ2Bridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ2,
                                PVRSRV_BRIDGE_RGXTQ2_RGXTDMSETTRANSFERCONTEXTPROPERTY);
 
-       return PVRSRV_OK;
 }
index ce320bb..b864284 100644 (file)
@@ -69,6 +69,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* Bridge in structure for RGXCreateTransferContext */
 typedef struct PVRSRV_BRIDGE_IN_RGXCREATETRANSFERCONTEXT_TAG
 {
+       IMG_UINT64 ui64RobustnessAddress;
        IMG_HANDLE hPrivData;
        IMG_BYTE *pui8FrameworkCmd;
        IMG_UINT32 ui32ContextFlags;
@@ -140,7 +141,6 @@ typedef struct PVRSRV_BRIDGE_IN_RGXSUBMITTRANSFER2_TAG
        PVRSRV_TIMELINE h2DUpdateTimeline;
        PVRSRV_TIMELINE h3DUpdateTimeline;
        PVRSRV_FENCE hCheckFenceFD;
-       IMG_UINT32 ui32ClientCacheOpSeqNum;
        IMG_UINT32 ui32ExtJobRef;
        IMG_UINT32 ui32PrepareCount;
        IMG_UINT32 ui32SyncPMRCount;
index 57be46b..70415f5 100644 (file)
@@ -75,6 +75,9 @@ static PVRSRV_ERROR _RGXCreateTransferContextpsTransferContextIntRelease(void *p
        return eError;
 }
 
+static_assert(RGXFWIF_RF_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_RF_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                                     IMG_UINT8 * psRGXCreateTransferContextIN_UI8,
@@ -101,8 +104,9 @@ PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXCreateTransferContextIN->ui32FrameworkCmdize * sizeof(IMG_BYTE)) + 0;
 
        if (unlikely(psRGXCreateTransferContextIN->ui32FrameworkCmdize > RGXFWIF_RF_CMD_SIZE))
        {
@@ -112,6 +116,14 @@ PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXCreateTransferContextOUT->hTransferContext = NULL;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXCreateTransferContextOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXCreateTransferContext_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -132,7 +144,7 @@ PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -188,6 +200,7 @@ PVRSRVBridgeRGXCreateTransferContext(IMG_UINT32 ui32DispatchTableEntry,
                                             hPrivDataInt,
                                             psRGXCreateTransferContextIN->ui32PackedCCBSizeU8888,
                                             psRGXCreateTransferContextIN->ui32ContextFlags,
+                                            psRGXCreateTransferContextIN->ui64RobustnessAddress,
                                             &psTransferContextInt,
                                             &psCLIPMRMemInt, &psUSCPMRMemInt);
        /* Exit early if bridged call fails */
@@ -265,7 +278,7 @@ RGXCreateTransferContext_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(psConnection->psHandleBase);
 
-                       eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+                       eError = PVRSRVDestroyHandleUnlocked(psConnection->psHandleBase,
                                                             (IMG_HANDLE)
                                                             psRGXCreateTransferContextOUT->
                                                             hTransferContext,
@@ -293,7 +306,10 @@ RGXCreateTransferContext_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXCreateTransferContextOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -322,12 +338,13 @@ PVRSRVBridgeRGXDestroyTransferContext(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRGXDestroyTransferContextOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRGXDestroyTransferContextIN->
-                                           hTransferContext,
-                                           PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRGXDestroyTransferContextIN->
+                                             hTransferContext,
+                                             PVRSRV_HANDLE_TYPE_RGX_SERVER_TQ_CONTEXT);
        if (unlikely
            ((psRGXDestroyTransferContextOUT->eError != PVRSRV_OK)
+            && (psRGXDestroyTransferContextOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psRGXDestroyTransferContextOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -401,6 +418,15 @@ RGXSetTransferContextPriority_exit:
        return 0;
 }
 
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+static_assert(RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE <= IMG_UINT32_MAX,
+             "RGXFWIF_DM_INDEPENDENT_KICK_CMD_SIZE must not be larger than IMG_UINT32_MAX");
+static_assert(PVRSRV_MAX_SYNCS <= IMG_UINT32_MAX,
+             "PVRSRV_MAX_SYNCS must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                               IMG_UINT8 * psRGXSubmitTransfer2IN_UI8,
@@ -435,26 +461,27 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
-           (PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
-           (psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
-           (psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
-           (psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
-           (psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *)) +
-           (psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) PVRSRV_SYNC_NAME_LENGTH * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_UINT32)) +
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *)) +
+           ((IMG_UINT64) psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE)) + 0;
        IMG_UINT32 ui32BufferSize2 = 0;
        IMG_UINT32 ui32NextOffset2 = 0;
 
        if (psRGXSubmitTransfer2IN->ui32PrepareCount != 0)
        {
 
-               ui32BufferSize +=
+               ui64BufferSize +=
                    psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(SYNC_PRIMITIVE_BLOCK **);
-               ui32BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_HANDLE **);
-               ui32BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-               ui32BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32 *);
-               ui32BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT8 *);
+               ui64BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_HANDLE **);
+               ui64BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32 *);
+               ui64BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT32 *);
+               ui64BufferSize += psRGXSubmitTransfer2IN->ui32PrepareCount * sizeof(IMG_UINT8 *);
        }
 
        if (unlikely(psRGXSubmitTransfer2IN->ui32SyncPMRCount > PVRSRV_MAX_SYNCS))
@@ -463,6 +490,14 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                goto RGXSubmitTransfer2_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRGXSubmitTransfer2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RGXSubmitTransfer2_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -483,7 +518,7 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -633,6 +668,8 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        if (psRGXSubmitTransfer2IN->ui32SyncPMRCount != 0)
        {
                psSyncPMRsInt = (PMR **) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               OSCachedMemSet(psSyncPMRsInt, 0,
+                              psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *));
                ui32NextOffset += psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(PMR *);
                hSyncPMRsInt2 = (IMG_HANDLE *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
                ui32NextOffset += psRGXSubmitTransfer2IN->ui32SyncPMRCount * sizeof(IMG_HANDLE);
@@ -654,20 +691,27 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
        if (psRGXSubmitTransfer2IN->ui32PrepareCount != 0)
        {
                IMG_UINT32 i;
+               ui64BufferSize = 0;
                for (i = 0; i < psRGXSubmitTransfer2IN->ui32PrepareCount; i++)
                {
-                       ui32BufferSize2 +=
+                       ui64BufferSize +=
                            ui32ClientUpdateCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
-                       ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE *);
-                       ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
-                       ui32BufferSize2 += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
-                       ui32BufferSize2 += ui32CommandSizeInt[i] * sizeof(IMG_UINT8);
+                       ui64BufferSize += ui32ClientUpdateCountInt[i] * sizeof(IMG_HANDLE *);
+                       ui64BufferSize += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+                       ui64BufferSize += ui32ClientUpdateCountInt[i] * sizeof(IMG_UINT32);
+                       ui64BufferSize += ui32CommandSizeInt[i] * sizeof(IMG_UINT8);
                }
+               if (ui64BufferSize > IMG_UINT32_MAX)
+               {
+                       psRGXSubmitTransfer2OUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+                       goto RGXSubmitTransfer2_exit;
+               }
+               ui32BufferSize2 = (IMG_UINT32) ui64BufferSize;
        }
 
        if (ui32BufferSize2 != 0)
        {
-               pArrayArgsBuffer2 = OSAllocZMemNoStats(ui32BufferSize2);
+               pArrayArgsBuffer2 = OSAllocMemNoStats(ui32BufferSize2);
 
                if (!pArrayArgsBuffer2)
                {
@@ -692,6 +736,9 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
                        psUpdateUFOSyncPrimBlockInt[i] =
                            (SYNC_PRIMITIVE_BLOCK **) IMG_OFFSET_ADDR(pArrayArgsBuffer2,
                                                                      ui32NextOffset2);
+                       OSCachedMemSet(psUpdateUFOSyncPrimBlockInt[i], 0,
+                                      ui32ClientUpdateCountInt[i] *
+                                      sizeof(SYNC_PRIMITIVE_BLOCK *));
                        ui32NextOffset2 +=
                            ui32ClientUpdateCountInt[i] * sizeof(SYNC_PRIMITIVE_BLOCK *);
                        /* Assigning each hUpdateUFOSyncPrimBlockInt2 to the right offset in the pool buffer (this is the second dimension) */
@@ -944,7 +991,6 @@ PVRSRVBridgeRGXSubmitTransfer2(IMG_UINT32 ui32DispatchTableEntry,
 
        psRGXSubmitTransfer2OUT->eError =
            PVRSRVRGXSubmitTransferKM(psTransferContextInt,
-                                     psRGXSubmitTransfer2IN->ui32ClientCacheOpSeqNum,
                                      psRGXSubmitTransfer2IN->ui32PrepareCount,
                                      ui32ClientUpdateCountInt,
                                      psUpdateUFOSyncPrimBlockInt,
@@ -987,7 +1033,7 @@ RGXSubmitTransfer2_exit:
                        {
 
                                /* Unreference the previously looked up handle */
-                               if (hUpdateUFOSyncPrimBlockInt2[i][j])
+                               if (psUpdateUFOSyncPrimBlockInt[i][j])
                                {
                                        PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                                    hUpdateUFOSyncPrimBlockInt2[i]
@@ -1006,7 +1052,7 @@ RGXSubmitTransfer2_exit:
                {
 
                        /* Unreference the previously looked up handle */
-                       if (hSyncPMRsInt2[i])
+                       if (psSyncPMRsInt[i])
                        {
                                PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
                                                            hSyncPMRsInt2[i],
@@ -1018,7 +1064,10 @@ RGXSubmitTransfer2_exit:
        UnlockHandle(psConnection->psHandleBase);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXSubmitTransfer2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -1028,7 +1077,10 @@ RGXSubmitTransfer2_exit:
                OSFreeMemNoStats(pArrayArgsBuffer);
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize2 == ui32NextOffset2);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRGXSubmitTransfer2OUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize2 == ui32NextOffset2);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
        if (pArrayArgsBuffer2)
                OSFreeMemNoStats(pArrayArgsBuffer2);
@@ -1101,7 +1153,7 @@ RGXSetTransferContextProperty_exit:
 
 #if defined(SUPPORT_RGXTQ_BRIDGE)
 PVRSRV_ERROR InitRGXTQBridge(void);
-PVRSRV_ERROR DeinitRGXTQBridge(void);
+void DeinitRGXTQBridge(void);
 
 /*
  * Register all RGXTQ functions with services
@@ -1132,7 +1184,7 @@ PVRSRV_ERROR InitRGXTQBridge(void)
 /*
  * Unregister all rgxtq functions with services
  */
-PVRSRV_ERROR DeinitRGXTQBridge(void)
+void DeinitRGXTQBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ, PVRSRV_BRIDGE_RGXTQ_RGXCREATETRANSFERCONTEXT);
@@ -1147,7 +1199,6 @@ PVRSRV_ERROR DeinitRGXTQBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RGXTQ,
                                PVRSRV_BRIDGE_RGXTQ_RGXSETTRANSFERCONTEXTPROPERTY);
 
-       return PVRSRV_OK;
 }
 #else /* SUPPORT_RGXTQ_BRIDGE */
 /* This bridge is conditional on SUPPORT_RGXTQ_BRIDGE - when not defined,
@@ -1156,7 +1207,6 @@ PVRSRV_ERROR DeinitRGXTQBridge(void)
 #define InitRGXTQBridge() \
        PVRSRV_OK
 
-#define DeinitRGXTQBridge() \
-       PVRSRV_OK
+#define DeinitRGXTQBridge()
 
 #endif /* SUPPORT_RGXTQ_BRIDGE */
index fa6f6c8..80f246c 100644 (file)
@@ -120,6 +120,9 @@ static PVRSRV_ERROR _RIWriteMEMDESCEntrypsRIHandleIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
                                IMG_UINT8 * psRIWriteMEMDESCEntryIN_UI8,
@@ -144,7 +147,9 @@ PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRIWriteMEMDESCEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psRIWriteMEMDESCEntryIN->ui32TextBSize > DEVMEM_ANNOTATION_MAX_LEN))
        {
@@ -152,6 +157,14 @@ PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
                goto RIWriteMEMDESCEntry_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRIWriteMEMDESCEntryOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RIWriteMEMDESCEntry_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -172,7 +185,7 @@ PVRSRVBridgeRIWriteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -277,7 +290,10 @@ RIWriteMEMDESCEntry_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRIWriteMEMDESCEntryOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -296,6 +312,9 @@ static PVRSRV_ERROR _RIWriteProcListEntrypsRIHandleIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(DEVMEM_ANNOTATION_MAX_LEN <= IMG_UINT32_MAX,
+             "DEVMEM_ANNOTATION_MAX_LEN must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeRIWriteProcListEntry(IMG_UINT32 ui32DispatchTableEntry,
                                 IMG_UINT8 * psRIWriteProcListEntryIN_UI8,
@@ -318,8 +337,9 @@ PVRSRVBridgeRIWriteProcListEntry(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psRIWriteProcListEntryIN->ui32TextBSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psRIWriteProcListEntryIN->ui32TextBSize > DEVMEM_ANNOTATION_MAX_LEN))
        {
@@ -327,6 +347,14 @@ PVRSRVBridgeRIWriteProcListEntry(IMG_UINT32 ui32DispatchTableEntry,
                goto RIWriteProcListEntry_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psRIWriteProcListEntryOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto RIWriteProcListEntry_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -347,7 +375,7 @@ PVRSRVBridgeRIWriteProcListEntry(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -421,7 +449,10 @@ RIWriteProcListEntry_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psRIWriteProcListEntryOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -502,10 +533,11 @@ PVRSRVBridgeRIDeleteMEMDESCEntry(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psRIDeleteMEMDESCEntryOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psRIDeleteMEMDESCEntryIN->hRIHandle,
-                                           PVRSRV_HANDLE_TYPE_RI_HANDLE);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psRIDeleteMEMDESCEntryIN->hRIHandle,
+                                             PVRSRV_HANDLE_TYPE_RI_HANDLE);
        if (unlikely((psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_OK) &&
+                    (psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psRIDeleteMEMDESCEntryOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -663,7 +695,7 @@ RIWritePMREntryWithOwner_exit:
  */
 
 PVRSRV_ERROR InitRIBridge(void);
-PVRSRV_ERROR DeinitRIBridge(void);
+void DeinitRIBridge(void);
 
 /*
  * Register all RI functions with services
@@ -704,7 +736,7 @@ PVRSRV_ERROR InitRIBridge(void)
 /*
  * Unregister all ri functions with services
  */
-PVRSRV_ERROR DeinitRIBridge(void)
+void DeinitRIBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RI, PVRSRV_BRIDGE_RI_RIWRITEPMRENTRY);
@@ -725,5 +757,4 @@ PVRSRV_ERROR DeinitRIBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_RI, PVRSRV_BRIDGE_RI_RIWRITEPMRENTRYWITHOWNER);
 
-       return PVRSRV_OK;
 }
index a1269f8..48abd12 100644 (file)
@@ -190,12 +190,13 @@ PVRSRVBridgeReleaseGlobalEventObject(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psReleaseGlobalEventObjectOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psReleaseGlobalEventObjectIN->
-                                           hGlobalEventObject,
-                                           PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psReleaseGlobalEventObjectIN->
+                                             hGlobalEventObject,
+                                             PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
        if (unlikely
            ((psReleaseGlobalEventObjectOUT->eError != PVRSRV_OK)
+            && (psReleaseGlobalEventObjectOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
             && (psReleaseGlobalEventObjectOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -365,10 +366,11 @@ PVRSRVBridgeEventObjectClose(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psEventObjectCloseOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psEventObjectCloseIN->hOSEventKM,
-                                           PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psEventObjectCloseIN->hOSEventKM,
+                                             PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
        if (unlikely((psEventObjectCloseOUT->eError != PVRSRV_OK) &&
+                    (psEventObjectCloseOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psEventObjectCloseOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -438,6 +440,9 @@ PVRSRVBridgeHWOpTimeout(IMG_UINT32 ui32DispatchTableEntry,
        return 0;
 }
 
+static_assert(RGXFW_ALIGN_CHECKS_UM_MAX <= IMG_UINT32_MAX,
+             "RGXFW_ALIGN_CHECKS_UM_MAX must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
                           IMG_UINT8 * psAlignmentCheckIN_UI8,
@@ -456,8 +461,9 @@ PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize =
-           (psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psAlignmentCheckIN->ui32AlignChecksSize * sizeof(IMG_UINT32)) + 0;
 
        if (unlikely(psAlignmentCheckIN->ui32AlignChecksSize > RGXFW_ALIGN_CHECKS_UM_MAX))
        {
@@ -465,6 +471,14 @@ PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
                goto AlignmentCheck_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psAlignmentCheckOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto AlignmentCheck_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -485,7 +499,7 @@ PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -523,7 +537,10 @@ PVRSRVBridgeAlignmentCheck(IMG_UINT32 ui32DispatchTableEntry,
 AlignmentCheck_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psAlignmentCheckOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -572,7 +589,9 @@ PVRSRVBridgeGetMultiCoreInfo(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psGetMultiCoreInfoIN->ui32CapsSize * sizeof(IMG_UINT64)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psGetMultiCoreInfoIN->ui32CapsSize * sizeof(IMG_UINT64)) + 0;
 
        if (psGetMultiCoreInfoIN->ui32CapsSize > 8)
        {
@@ -582,6 +601,14 @@ PVRSRVBridgeGetMultiCoreInfo(IMG_UINT32 ui32DispatchTableEntry,
 
        psGetMultiCoreInfoOUT->pui64Caps = psGetMultiCoreInfoIN->pui64Caps;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psGetMultiCoreInfoOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto GetMultiCoreInfo_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -602,7 +629,7 @@ PVRSRVBridgeGetMultiCoreInfo(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -622,6 +649,11 @@ PVRSRVBridgeGetMultiCoreInfo(IMG_UINT32 ui32DispatchTableEntry,
            PVRSRVGetMultiCoreInfoKM(psConnection, OSGetDevNode(psConnection),
                                     psGetMultiCoreInfoIN->ui32CapsSize,
                                     &psGetMultiCoreInfoOUT->ui32NumCores, pui64CapsInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psGetMultiCoreInfoOUT->eError != PVRSRV_OK))
+       {
+               goto GetMultiCoreInfo_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((pui64CapsInt) && ((psGetMultiCoreInfoIN->ui32CapsSize * sizeof(IMG_UINT64)) > 0))
@@ -640,7 +672,10 @@ PVRSRVBridgeGetMultiCoreInfo(IMG_UINT32 ui32DispatchTableEntry,
 GetMultiCoreInfo_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psGetMultiCoreInfoOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -726,7 +761,9 @@ PVRSRVBridgeFindProcessMemStats(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psFindProcessMemStatsIN->ui32ArrSize * sizeof(IMG_UINT32)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psFindProcessMemStatsIN->ui32ArrSize * sizeof(IMG_UINT32)) + 0;
 
        if (psFindProcessMemStatsIN->ui32ArrSize > PVRSRV_PROCESS_STAT_TYPE_COUNT)
        {
@@ -738,6 +775,14 @@ PVRSRVBridgeFindProcessMemStats(IMG_UINT32 ui32DispatchTableEntry,
 
        psFindProcessMemStatsOUT->pui32MemStatsArray = psFindProcessMemStatsIN->pui32MemStatsArray;
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psFindProcessMemStatsOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto FindProcessMemStats_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -758,7 +803,7 @@ PVRSRVBridgeFindProcessMemStats(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -780,6 +825,11 @@ PVRSRVBridgeFindProcessMemStats(IMG_UINT32 ui32DispatchTableEntry,
                                        psFindProcessMemStatsIN->ui32ArrSize,
                                        psFindProcessMemStatsIN->bbAllProcessStats,
                                        pui32MemStatsArrayInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psFindProcessMemStatsOUT->eError != PVRSRV_OK))
+       {
+               goto FindProcessMemStats_exit;
+       }
 
        /* If dest ptr is non-null and we have data to copy */
        if ((pui32MemStatsArrayInt) &&
@@ -800,7 +850,10 @@ PVRSRVBridgeFindProcessMemStats(IMG_UINT32 ui32DispatchTableEntry,
 FindProcessMemStats_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psFindProcessMemStatsOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -885,10 +938,11 @@ PVRSRVBridgeReleaseInfoPage(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psProcessHandleBase->psHandleBase);
 
        psReleaseInfoPageOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psProcessHandleBase->psHandleBase,
-                                           (IMG_HANDLE) psReleaseInfoPageIN->hPMR,
-                                           PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             (IMG_HANDLE) psReleaseInfoPageIN->hPMR,
+                                             PVRSRV_HANDLE_TYPE_DEVMEM_MEM_IMPORT);
        if (unlikely((psReleaseInfoPageOUT->eError != PVRSRV_OK) &&
+                    (psReleaseInfoPageOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psReleaseInfoPageOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -910,7 +964,7 @@ ReleaseInfoPage_exit:
  */
 
 PVRSRV_ERROR InitSRVCOREBridge(void);
-PVRSRV_ERROR DeinitSRVCOREBridge(void);
+void DeinitSRVCOREBridge(void);
 
 /*
  * Register all SRVCORE functions with services
@@ -975,7 +1029,7 @@ PVRSRV_ERROR InitSRVCOREBridge(void)
 /*
  * Unregister all srvcore functions with services
  */
-PVRSRV_ERROR DeinitSRVCOREBridge(void)
+void DeinitSRVCOREBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_CONNECT);
@@ -1015,5 +1069,4 @@ PVRSRV_ERROR DeinitSRVCOREBridge(void)
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SRVCORE, PVRSRV_BRIDGE_SRVCORE_RELEASEINFOPAGE);
 
-       return PVRSRV_OK;
 }
index ba49566..4788fc1 100644 (file)
@@ -153,7 +153,7 @@ AllocSyncPrimitiveBlock_exit:
                        /* Lock over handle creation cleanup. */
                        LockHandle(psConnection->psHandleBase);
 
-                       eError = PVRSRVReleaseHandleUnlocked(psConnection->psHandleBase,
+                       eError = PVRSRVDestroyHandleUnlocked(psConnection->psHandleBase,
                                                             (IMG_HANDLE)
                                                             psAllocSyncPrimitiveBlockOUT->
                                                             hSyncHandle,
@@ -200,10 +200,11 @@ PVRSRVBridgeFreeSyncPrimitiveBlock(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psFreeSyncPrimitiveBlockOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psFreeSyncPrimitiveBlockIN->hSyncHandle,
-                                           PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psFreeSyncPrimitiveBlockIN->hSyncHandle,
+                                             PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK);
        if (unlikely((psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_OK) &&
+                    (psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psFreeSyncPrimitiveBlockOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -509,6 +510,9 @@ SyncPrimPDumpCBP_exit:
 #define PVRSRVBridgeSyncPrimPDumpCBP NULL
 #endif
 
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
                           IMG_UINT8 * psSyncAllocEventIN_UI8,
@@ -527,7 +531,9 @@ PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncAllocEventIN->ui32ClassNameSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psSyncAllocEventIN->ui32ClassNameSize > PVRSRV_SYNC_NAME_LENGTH))
        {
@@ -535,6 +541,14 @@ PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
                goto SyncAllocEvent_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncAllocEventOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncAllocEvent_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -555,7 +569,7 @@ PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -596,7 +610,10 @@ PVRSRVBridgeSyncAllocEvent(IMG_UINT32 ui32DispatchTableEntry,
 SyncAllocEvent_exit:
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncAllocEventOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -657,7 +674,7 @@ PVRSRVBridgeSyncCheckpointSignalledPDumpPol(IMG_UINT32 ui32DispatchTableEntry,
  */
 
 PVRSRV_ERROR InitSYNCBridge(void);
-PVRSRV_ERROR DeinitSYNCBridge(void);
+void DeinitSYNCBridge(void);
 
 /*
  * Register all SYNC functions with services
@@ -702,7 +719,7 @@ PVRSRV_ERROR InitSYNCBridge(void)
 /*
  * Unregister all sync functions with services
  */
-PVRSRV_ERROR DeinitSYNCBridge(void)
+void DeinitSYNCBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNC, PVRSRV_BRIDGE_SYNC_ALLOCSYNCPRIMITIVEBLOCK);
@@ -726,5 +743,4 @@ PVRSRV_ERROR DeinitSYNCBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNC,
                                PVRSRV_BRIDGE_SYNC_SYNCCHECKPOINTSIGNALLEDPDUMPPOL);
 
-       return PVRSRV_OK;
 }
diff --git a/drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/common_syncfallback_bridge.h b/drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/common_syncfallback_bridge.h
new file mode 100644 (file)
index 0000000..87016c4
--- /dev/null
@@ -0,0 +1,357 @@
+/*******************************************************************************
+@File
+@Title          Common bridge header for syncfallback
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declares common defines and structures used by both the client
+                and server side of the bridge for syncfallback
+@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.
+*******************************************************************************/
+
+#ifndef COMMON_SYNCFALLBACK_BRIDGE_H
+#define COMMON_SYNCFALLBACK_BRIDGE_H
+
+#include <powervr/mem_types.h>
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "pvrsrv_error.h"
+
+#include "pvrsrv_sync_km.h"
+
+#define PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST                   0
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATEPVR                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+0
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINERELEASE                       PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+1
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUP                      PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+2
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEMERGE                    PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+3
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCERELEASE                  PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+4
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEWAIT                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+5
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUMP                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+6
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATESW                      PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+7
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCECREATESW                 PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+8
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINEADVANCESW                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+9
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTINSECURE                   PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+10
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYINSECURE                    PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+11
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTINSECURE                   PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+12
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTSECURE                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+13
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYSECURE                      PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+14
+#define PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTSECURE                     PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+15
+#define PVRSRV_BRIDGE_SYNCFALLBACK_CMD_LAST                    (PVRSRV_BRIDGE_SYNCFALLBACK_CMD_FIRST+15)
+
+/*******************************************
+            SyncFbTimelineCreatePVR
+ *******************************************/
+
+/* Bridge in structure for SyncFbTimelineCreatePVR */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATEPVR_TAG
+{
+       const IMG_CHAR *puiTimelineName;
+       IMG_UINT32 ui32TimelineNameSize;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATEPVR;
+
+/* Bridge out structure for SyncFbTimelineCreatePVR */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATEPVR_TAG
+{
+       IMG_HANDLE hTimeline;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATEPVR;
+
+/*******************************************
+            SyncFbTimelineRelease
+ *******************************************/
+
+/* Bridge in structure for SyncFbTimelineRelease */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBTIMELINERELEASE_TAG
+{
+       IMG_HANDLE hTimeline;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBTIMELINERELEASE;
+
+/* Bridge out structure for SyncFbTimelineRelease */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBTIMELINERELEASE_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBTIMELINERELEASE;
+
+/*******************************************
+            SyncFbFenceDup
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceDup */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEDUP_TAG
+{
+       IMG_HANDLE hInFence;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEDUP;
+
+/* Bridge out structure for SyncFbFenceDup */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUP_TAG
+{
+       IMG_HANDLE hOutFence;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUP;
+
+/*******************************************
+            SyncFbFenceMerge
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceMerge */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEMERGE_TAG
+{
+       IMG_HANDLE hInFence1;
+       IMG_HANDLE hInFence2;
+       const IMG_CHAR *puiFenceName;
+       IMG_UINT32 ui32FenceNameSize;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEMERGE;
+
+/* Bridge out structure for SyncFbFenceMerge */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEMERGE_TAG
+{
+       IMG_HANDLE hOutFence;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEMERGE;
+
+/*******************************************
+            SyncFbFenceRelease
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceRelease */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCERELEASE_TAG
+{
+       IMG_HANDLE hFence;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCERELEASE;
+
+/* Bridge out structure for SyncFbFenceRelease */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCERELEASE_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCERELEASE;
+
+/*******************************************
+            SyncFbFenceWait
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceWait */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEWAIT_TAG
+{
+       IMG_HANDLE hFence;
+       IMG_UINT32 ui32Timeout;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEWAIT;
+
+/* Bridge out structure for SyncFbFenceWait */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEWAIT_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEWAIT;
+
+/*******************************************
+            SyncFbFenceDump
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceDump */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEDUMP_TAG
+{
+       IMG_HANDLE hFence;
+       const IMG_CHAR *puiDescStr;
+       const IMG_CHAR *puiFileStr;
+       const IMG_CHAR *puiModuleStr;
+       IMG_UINT32 ui32DescStrLength;
+       IMG_UINT32 ui32FileStrLength;
+       IMG_UINT32 ui32Line;
+       IMG_UINT32 ui32ModuleStrLength;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEDUMP;
+
+/* Bridge out structure for SyncFbFenceDump */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUMP_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUMP;
+
+/*******************************************
+            SyncFbTimelineCreateSW
+ *******************************************/
+
+/* Bridge in structure for SyncFbTimelineCreateSW */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATESW_TAG
+{
+       const IMG_CHAR *puiTimelineName;
+       IMG_UINT32 ui32TimelineNameSize;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATESW;
+
+/* Bridge out structure for SyncFbTimelineCreateSW */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATESW_TAG
+{
+       IMG_HANDLE hTimeline;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATESW;
+
+/*******************************************
+            SyncFbFenceCreateSW
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceCreateSW */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCECREATESW_TAG
+{
+       IMG_HANDLE hTimeline;
+       const IMG_CHAR *puiFenceName;
+       IMG_UINT32 ui32FenceNameSize;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCECREATESW;
+
+/* Bridge out structure for SyncFbFenceCreateSW */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCECREATESW_TAG
+{
+       IMG_UINT64 ui64SyncPtIdx;
+       IMG_HANDLE hOutFence;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCECREATESW;
+
+/*******************************************
+            SyncFbTimelineAdvanceSW
+ *******************************************/
+
+/* Bridge in structure for SyncFbTimelineAdvanceSW */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBTIMELINEADVANCESW_TAG
+{
+       IMG_HANDLE hTimeline;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBTIMELINEADVANCESW;
+
+/* Bridge out structure for SyncFbTimelineAdvanceSW */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBTIMELINEADVANCESW_TAG
+{
+       IMG_UINT64 ui64SyncPtIdx;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBTIMELINEADVANCESW;
+
+/*******************************************
+            SyncFbFenceExportInsecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceExportInsecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTINSECURE_TAG
+{
+       IMG_HANDLE hFence;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTINSECURE;
+
+/* Bridge out structure for SyncFbFenceExportInsecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTINSECURE_TAG
+{
+       IMG_HANDLE hExport;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTINSECURE;
+
+/*******************************************
+            SyncFbFenceExportDestroyInsecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceExportDestroyInsecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYINSECURE_TAG
+{
+       IMG_HANDLE hExport;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYINSECURE;
+
+/* Bridge out structure for SyncFbFenceExportDestroyInsecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYINSECURE_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYINSECURE;
+
+/*******************************************
+            SyncFbFenceImportInsecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceImportInsecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTINSECURE_TAG
+{
+       IMG_HANDLE hImport;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTINSECURE;
+
+/* Bridge out structure for SyncFbFenceImportInsecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTINSECURE_TAG
+{
+       IMG_HANDLE hSyncHandle;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTINSECURE;
+
+/*******************************************
+            SyncFbFenceExportSecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceExportSecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTSECURE_TAG
+{
+       IMG_HANDLE hFence;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTSECURE;
+
+/* Bridge out structure for SyncFbFenceExportSecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTSECURE_TAG
+{
+       IMG_SECURE_TYPE Export;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTSECURE;
+
+/*******************************************
+            SyncFbFenceExportDestroySecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceExportDestroySecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYSECURE_TAG
+{
+       IMG_HANDLE hExport;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYSECURE;
+
+/* Bridge out structure for SyncFbFenceExportDestroySecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYSECURE_TAG
+{
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYSECURE;
+
+/*******************************************
+            SyncFbFenceImportSecure
+ *******************************************/
+
+/* Bridge in structure for SyncFbFenceImportSecure */
+typedef struct PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTSECURE_TAG
+{
+       IMG_SECURE_TYPE Import;
+} __packed PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTSECURE;
+
+/* Bridge out structure for SyncFbFenceImportSecure */
+typedef struct PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTSECURE_TAG
+{
+       IMG_HANDLE hSyncHandle;
+       PVRSRV_ERROR eError;
+} __packed PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTSECURE;
+
+#endif /* COMMON_SYNCFALLBACK_BRIDGE_H */
diff --git a/drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/server_syncfallback_bridge.c b/drivers/gpu/drm/img/img-rogue/generated/rogue/syncfallback_bridge/server_syncfallback_bridge.c
new file mode 100644 (file)
index 0000000..800a9dd
--- /dev/null
@@ -0,0 +1,1967 @@
+/*******************************************************************************
+@File
+@Title          Server bridge for syncfallback
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Implements the server side of the bridge for syncfallback
+@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.
+*******************************************************************************/
+
+#include <linux/uaccess.h>
+
+#include "img_defs.h"
+
+#include "sync_fallback_server.h"
+#include "pvrsrv_sync_server.h"
+
+#include "common_syncfallback_bridge.h"
+
+#include "allocmem.h"
+#include "pvr_debug.h"
+#include "connection_server.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_RGX)
+#include "rgx_bridge.h"
+#endif
+#include "srvcore.h"
+#include "handle.h"
+
+#include <linux/slab.h>
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+static PVRSRV_ERROR ReleaseExport(void *pvData)
+{
+       PVR_UNREFERENCED_PARAMETER(pvData);
+
+       return PVRSRV_OK;
+}
+#endif
+
+/* ***************************************************************************
+ * Server-side bridge entry points
+ */
+
+static PVRSRV_ERROR _SyncFbTimelineCreatePVRpsTimelineIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbTimelineRelease((PVRSRV_TIMELINE_SERVER *) pvData);
+       return eError;
+}
+
+static_assert(SYNC_FB_TIMELINE_MAX_LENGTH <= IMG_UINT32_MAX,
+             "SYNC_FB_TIMELINE_MAX_LENGTH must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeSyncFbTimelineCreatePVR(IMG_UINT32 ui32DispatchTableEntry,
+                                   IMG_UINT8 * psSyncFbTimelineCreatePVRIN_UI8,
+                                   IMG_UINT8 * psSyncFbTimelineCreatePVROUT_UI8,
+                                   CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATEPVR *psSyncFbTimelineCreatePVRIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATEPVR *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineCreatePVRIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATEPVR *psSyncFbTimelineCreatePVROUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATEPVR *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineCreatePVROUT_UI8, 0);
+
+       IMG_CHAR *uiTimelineNameInt = NULL;
+       PVRSRV_TIMELINE_SERVER *psTimelineInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely
+           (psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize > SYNC_FB_TIMELINE_MAX_LENGTH))
+       {
+               psSyncFbTimelineCreatePVROUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbTimelineCreatePVR_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncFbTimelineCreatePVROUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncFbTimelineCreatePVR_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psSyncFbTimelineCreatePVRIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psSyncFbTimelineCreatePVRIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psSyncFbTimelineCreatePVROUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto SyncFbTimelineCreatePVR_exit;
+                       }
+               }
+       }
+
+       if (psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize != 0)
+       {
+               uiTimelineNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiTimelineNameInt,
+                    (const void __user *)psSyncFbTimelineCreatePVRIN->puiTimelineName,
+                    psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize * sizeof(IMG_CHAR)) !=
+                   PVRSRV_OK)
+               {
+                       psSyncFbTimelineCreatePVROUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbTimelineCreatePVR_exit;
+               }
+               ((IMG_CHAR *)
+                uiTimelineNameInt)[(psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize *
+                                    sizeof(IMG_CHAR)) - 1] = '\0';
+       }
+
+       psSyncFbTimelineCreatePVROUT->eError =
+           SyncFbTimelineCreatePVR(psSyncFbTimelineCreatePVRIN->ui32TimelineNameSize,
+                                   uiTimelineNameInt, &psTimelineInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbTimelineCreatePVROUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbTimelineCreatePVR_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbTimelineCreatePVROUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbTimelineCreatePVROUT->hTimeline,
+                                     (void *)psTimelineInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbTimelineCreatePVRpsTimelineIntRelease);
+       if (unlikely(psSyncFbTimelineCreatePVROUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbTimelineCreatePVR_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbTimelineCreatePVR_exit:
+
+       if (psSyncFbTimelineCreatePVROUT->eError != PVRSRV_OK)
+       {
+               if (psTimelineInt)
+               {
+                       SyncFbTimelineRelease(psTimelineInt);
+               }
+       }
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncFbTimelineCreatePVROUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbTimelineRelease(IMG_UINT32 ui32DispatchTableEntry,
+                                 IMG_UINT8 * psSyncFbTimelineReleaseIN_UI8,
+                                 IMG_UINT8 * psSyncFbTimelineReleaseOUT_UI8,
+                                 CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBTIMELINERELEASE *psSyncFbTimelineReleaseIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBTIMELINERELEASE *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineReleaseIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBTIMELINERELEASE *psSyncFbTimelineReleaseOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBTIMELINERELEASE *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineReleaseOUT_UI8, 0);
+
+       /* Lock over handle destruction. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbTimelineReleaseOUT->eError =
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             (IMG_HANDLE) psSyncFbTimelineReleaseIN->hTimeline,
+                                             PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+       if (unlikely((psSyncFbTimelineReleaseOUT->eError != PVRSRV_OK) &&
+                    (psSyncFbTimelineReleaseOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
+                    (psSyncFbTimelineReleaseOUT->eError != PVRSRV_ERROR_RETRY)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__, PVRSRVGetErrorString(psSyncFbTimelineReleaseOUT->eError)));
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbTimelineRelease_exit;
+       }
+
+       /* Release now we have destroyed handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbTimelineRelease_exit:
+
+       return 0;
+}
+
+static PVRSRV_ERROR _SyncFbFenceDuppsOutFenceIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER *) pvData);
+       return eError;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceDup(IMG_UINT32 ui32DispatchTableEntry,
+                          IMG_UINT8 * psSyncFbFenceDupIN_UI8,
+                          IMG_UINT8 * psSyncFbFenceDupOUT_UI8, CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEDUP *psSyncFbFenceDupIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEDUP *) IMG_OFFSET_ADDR(psSyncFbFenceDupIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUP *psSyncFbFenceDupOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUP *) IMG_OFFSET_ADDR(psSyncFbFenceDupOUT_UI8, 0);
+
+       IMG_HANDLE hInFence = psSyncFbFenceDupIN->hInFence;
+       PVRSRV_FENCE_SERVER *psInFenceInt = NULL;
+       PVRSRV_FENCE_SERVER *psOutFenceInt = NULL;
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceDupOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psInFenceInt,
+                                      hInFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceDupOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceDup_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceDupOUT->eError = SyncFbFenceDup(psInFenceInt, &psOutFenceInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceDupOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceDup_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceDupOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbFenceDupOUT->hOutFence, (void *)psOutFenceInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) & _SyncFbFenceDuppsOutFenceIntRelease);
+       if (unlikely(psSyncFbFenceDupOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceDup_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceDup_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psInFenceInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hInFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       if (psSyncFbFenceDupOUT->eError != PVRSRV_OK)
+       {
+               if (psOutFenceInt)
+               {
+                       SyncFbFenceRelease(psOutFenceInt);
+               }
+       }
+
+       return 0;
+}
+
+static PVRSRV_ERROR _SyncFbFenceMergepsOutFenceIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER *) pvData);
+       return eError;
+}
+
+static_assert(SYNC_FB_FENCE_MAX_LENGTH <= IMG_UINT32_MAX,
+             "SYNC_FB_FENCE_MAX_LENGTH must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceMerge(IMG_UINT32 ui32DispatchTableEntry,
+                            IMG_UINT8 * psSyncFbFenceMergeIN_UI8,
+                            IMG_UINT8 * psSyncFbFenceMergeOUT_UI8, CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEMERGE *psSyncFbFenceMergeIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEMERGE *) IMG_OFFSET_ADDR(psSyncFbFenceMergeIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEMERGE *psSyncFbFenceMergeOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEMERGE *) IMG_OFFSET_ADDR(psSyncFbFenceMergeOUT_UI8, 0);
+
+       IMG_HANDLE hInFence1 = psSyncFbFenceMergeIN->hInFence1;
+       PVRSRV_FENCE_SERVER *psInFence1Int = NULL;
+       IMG_HANDLE hInFence2 = psSyncFbFenceMergeIN->hInFence2;
+       PVRSRV_FENCE_SERVER *psInFence2Int = NULL;
+       IMG_CHAR *uiFenceNameInt = NULL;
+       PVRSRV_FENCE_SERVER *psOutFenceInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncFbFenceMergeIN->ui32FenceNameSize * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely(psSyncFbFenceMergeIN->ui32FenceNameSize > SYNC_FB_FENCE_MAX_LENGTH))
+       {
+               psSyncFbFenceMergeOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbFenceMerge_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncFbFenceMergeOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncFbFenceMerge_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psSyncFbFenceMergeIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psSyncFbFenceMergeIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psSyncFbFenceMergeOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto SyncFbFenceMerge_exit;
+                       }
+               }
+       }
+
+       if (psSyncFbFenceMergeIN->ui32FenceNameSize != 0)
+       {
+               uiFenceNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psSyncFbFenceMergeIN->ui32FenceNameSize * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbFenceMergeIN->ui32FenceNameSize * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiFenceNameInt, (const void __user *)psSyncFbFenceMergeIN->puiFenceName,
+                    psSyncFbFenceMergeIN->ui32FenceNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psSyncFbFenceMergeOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbFenceMerge_exit;
+               }
+               ((IMG_CHAR *)
+                uiFenceNameInt)[(psSyncFbFenceMergeIN->ui32FenceNameSize * sizeof(IMG_CHAR)) - 1] =
+       '\0';
+       }
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceMergeOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psInFence1Int,
+                                      hInFence1, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceMergeOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceMerge_exit;
+       }
+
+       /* Look up the address from the handle */
+       psSyncFbFenceMergeOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psInFence2Int,
+                                      hInFence2, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceMergeOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceMerge_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceMergeOUT->eError =
+           SyncFbFenceMerge(psInFence1Int,
+                            psInFence2Int,
+                            psSyncFbFenceMergeIN->ui32FenceNameSize,
+                            uiFenceNameInt, &psOutFenceInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceMergeOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceMerge_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceMergeOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbFenceMergeOUT->hOutFence, (void *)psOutFenceInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) & _SyncFbFenceMergepsOutFenceIntRelease);
+       if (unlikely(psSyncFbFenceMergeOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceMerge_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceMerge_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psInFence1Int)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hInFence1, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+
+       /* Unreference the previously looked up handle */
+       if (psInFence2Int)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hInFence2, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       if (psSyncFbFenceMergeOUT->eError != PVRSRV_OK)
+       {
+               if (psOutFenceInt)
+               {
+                       SyncFbFenceRelease(psOutFenceInt);
+               }
+       }
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncFbFenceMergeOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceRelease(IMG_UINT32 ui32DispatchTableEntry,
+                              IMG_UINT8 * psSyncFbFenceReleaseIN_UI8,
+                              IMG_UINT8 * psSyncFbFenceReleaseOUT_UI8,
+                              CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCERELEASE *psSyncFbFenceReleaseIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCERELEASE *) IMG_OFFSET_ADDR(psSyncFbFenceReleaseIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCERELEASE *psSyncFbFenceReleaseOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCERELEASE *) IMG_OFFSET_ADDR(psSyncFbFenceReleaseOUT_UI8,
+                                                                    0);
+
+       /* Lock over handle destruction. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceReleaseOUT->eError =
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             (IMG_HANDLE) psSyncFbFenceReleaseIN->hFence,
+                                             PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       if (unlikely((psSyncFbFenceReleaseOUT->eError != PVRSRV_OK) &&
+                    (psSyncFbFenceReleaseOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
+                    (psSyncFbFenceReleaseOUT->eError != PVRSRV_ERROR_RETRY)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__, PVRSRVGetErrorString(psSyncFbFenceReleaseOUT->eError)));
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceRelease_exit;
+       }
+
+       /* Release now we have destroyed handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceRelease_exit:
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceWait(IMG_UINT32 ui32DispatchTableEntry,
+                           IMG_UINT8 * psSyncFbFenceWaitIN_UI8,
+                           IMG_UINT8 * psSyncFbFenceWaitOUT_UI8, CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEWAIT *psSyncFbFenceWaitIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEWAIT *) IMG_OFFSET_ADDR(psSyncFbFenceWaitIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEWAIT *psSyncFbFenceWaitOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEWAIT *) IMG_OFFSET_ADDR(psSyncFbFenceWaitOUT_UI8, 0);
+
+       IMG_HANDLE hFence = psSyncFbFenceWaitIN->hFence;
+       PVRSRV_FENCE_SERVER *psFenceInt = NULL;
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceWaitOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psFenceInt,
+                                      hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceWaitOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceWait_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceWaitOUT->eError =
+           SyncFbFenceWait(psFenceInt, psSyncFbFenceWaitIN->ui32Timeout);
+
+SyncFbFenceWait_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psFenceInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       return 0;
+}
+
+static_assert((SYNC_FB_FILE_STRING_MAX + 1) <= IMG_UINT32_MAX,
+             "(SYNC_FB_FILE_STRING_MAX+1) must not be larger than IMG_UINT32_MAX");
+static_assert((SYNC_FB_MODULE_STRING_LEN_MAX + 1) <= IMG_UINT32_MAX,
+             "(SYNC_FB_MODULE_STRING_LEN_MAX+1) must not be larger than IMG_UINT32_MAX");
+static_assert((SYNC_FB_DESC_STRING_LEN_MAX + 1) <= IMG_UINT32_MAX,
+             "(SYNC_FB_DESC_STRING_LEN_MAX+1) must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceDump(IMG_UINT32 ui32DispatchTableEntry,
+                           IMG_UINT8 * psSyncFbFenceDumpIN_UI8,
+                           IMG_UINT8 * psSyncFbFenceDumpOUT_UI8, CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEDUMP *psSyncFbFenceDumpIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEDUMP *) IMG_OFFSET_ADDR(psSyncFbFenceDumpIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUMP *psSyncFbFenceDumpOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEDUMP *) IMG_OFFSET_ADDR(psSyncFbFenceDumpOUT_UI8, 0);
+
+       IMG_HANDLE hFence = psSyncFbFenceDumpIN->hFence;
+       PVRSRV_FENCE_SERVER *psFenceInt = NULL;
+       IMG_CHAR *uiFileStrInt = NULL;
+       IMG_CHAR *uiModuleStrInt = NULL;
+       IMG_CHAR *uiDescStrInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncFbFenceDumpIN->ui32FileStrLength * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psSyncFbFenceDumpIN->ui32ModuleStrLength * sizeof(IMG_CHAR)) +
+           ((IMG_UINT64) psSyncFbFenceDumpIN->ui32DescStrLength * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely(psSyncFbFenceDumpIN->ui32FileStrLength > (SYNC_FB_FILE_STRING_MAX + 1)))
+       {
+               psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbFenceDump_exit;
+       }
+
+       if (unlikely
+           (psSyncFbFenceDumpIN->ui32ModuleStrLength > (SYNC_FB_MODULE_STRING_LEN_MAX + 1)))
+       {
+               psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbFenceDump_exit;
+       }
+
+       if (unlikely(psSyncFbFenceDumpIN->ui32DescStrLength > (SYNC_FB_DESC_STRING_LEN_MAX + 1)))
+       {
+               psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbFenceDump_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncFbFenceDump_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psSyncFbFenceDumpIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psSyncFbFenceDumpIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto SyncFbFenceDump_exit;
+                       }
+               }
+       }
+
+       if (psSyncFbFenceDumpIN->ui32FileStrLength != 0)
+       {
+               uiFileStrInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psSyncFbFenceDumpIN->ui32FileStrLength * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbFenceDumpIN->ui32FileStrLength * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiFileStrInt, (const void __user *)psSyncFbFenceDumpIN->puiFileStr,
+                    psSyncFbFenceDumpIN->ui32FileStrLength * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbFenceDump_exit;
+               }
+               ((IMG_CHAR *)
+                uiFileStrInt)[(psSyncFbFenceDumpIN->ui32FileStrLength * sizeof(IMG_CHAR)) - 1] =
+       '\0';
+       }
+       if (psSyncFbFenceDumpIN->ui32ModuleStrLength != 0)
+       {
+               uiModuleStrInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psSyncFbFenceDumpIN->ui32ModuleStrLength * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbFenceDumpIN->ui32ModuleStrLength * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiModuleStrInt, (const void __user *)psSyncFbFenceDumpIN->puiModuleStr,
+                    psSyncFbFenceDumpIN->ui32ModuleStrLength * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbFenceDump_exit;
+               }
+               ((IMG_CHAR *)
+                uiModuleStrInt)[(psSyncFbFenceDumpIN->ui32ModuleStrLength * sizeof(IMG_CHAR)) -
+                                1] = '\0';
+       }
+       if (psSyncFbFenceDumpIN->ui32DescStrLength != 0)
+       {
+               uiDescStrInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psSyncFbFenceDumpIN->ui32DescStrLength * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbFenceDumpIN->ui32DescStrLength * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiDescStrInt, (const void __user *)psSyncFbFenceDumpIN->puiDescStr,
+                    psSyncFbFenceDumpIN->ui32DescStrLength * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psSyncFbFenceDumpOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbFenceDump_exit;
+               }
+               ((IMG_CHAR *)
+                uiDescStrInt)[(psSyncFbFenceDumpIN->ui32DescStrLength * sizeof(IMG_CHAR)) - 1] =
+       '\0';
+       }
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceDumpOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psFenceInt,
+                                      hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceDumpOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceDump_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceDumpOUT->eError =
+           SyncFbFenceDump(psFenceInt,
+                           psSyncFbFenceDumpIN->ui32Line,
+                           psSyncFbFenceDumpIN->ui32FileStrLength,
+                           uiFileStrInt,
+                           psSyncFbFenceDumpIN->ui32ModuleStrLength,
+                           uiModuleStrInt, psSyncFbFenceDumpIN->ui32DescStrLength, uiDescStrInt);
+
+SyncFbFenceDump_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psFenceInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncFbFenceDumpOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static PVRSRV_ERROR _SyncFbTimelineCreateSWpsTimelineIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbTimelineRelease((PVRSRV_TIMELINE_SERVER *) pvData);
+       return eError;
+}
+
+static_assert(SYNC_FB_FENCE_MAX_LENGTH <= IMG_UINT32_MAX,
+             "SYNC_FB_FENCE_MAX_LENGTH must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeSyncFbTimelineCreateSW(IMG_UINT32 ui32DispatchTableEntry,
+                                  IMG_UINT8 * psSyncFbTimelineCreateSWIN_UI8,
+                                  IMG_UINT8 * psSyncFbTimelineCreateSWOUT_UI8,
+                                  CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATESW *psSyncFbTimelineCreateSWIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBTIMELINECREATESW *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineCreateSWIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATESW *psSyncFbTimelineCreateSWOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBTIMELINECREATESW *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineCreateSWOUT_UI8, 0);
+
+       IMG_CHAR *uiTimelineNameInt = NULL;
+       PVRSRV_TIMELINE_SERVER *psTimelineInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncFbTimelineCreateSWIN->ui32TimelineNameSize * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely(psSyncFbTimelineCreateSWIN->ui32TimelineNameSize > SYNC_FB_FENCE_MAX_LENGTH))
+       {
+               psSyncFbTimelineCreateSWOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbTimelineCreateSW_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncFbTimelineCreateSWOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncFbTimelineCreateSW_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psSyncFbTimelineCreateSWIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psSyncFbTimelineCreateSWIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psSyncFbTimelineCreateSWOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto SyncFbTimelineCreateSW_exit;
+                       }
+               }
+       }
+
+       if (psSyncFbTimelineCreateSWIN->ui32TimelineNameSize != 0)
+       {
+               uiTimelineNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset +=
+                   psSyncFbTimelineCreateSWIN->ui32TimelineNameSize * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbTimelineCreateSWIN->ui32TimelineNameSize * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiTimelineNameInt,
+                    (const void __user *)psSyncFbTimelineCreateSWIN->puiTimelineName,
+                    psSyncFbTimelineCreateSWIN->ui32TimelineNameSize * sizeof(IMG_CHAR)) !=
+                   PVRSRV_OK)
+               {
+                       psSyncFbTimelineCreateSWOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbTimelineCreateSW_exit;
+               }
+               ((IMG_CHAR *)
+                uiTimelineNameInt)[(psSyncFbTimelineCreateSWIN->ui32TimelineNameSize *
+                                    sizeof(IMG_CHAR)) - 1] = '\0';
+       }
+
+       psSyncFbTimelineCreateSWOUT->eError =
+           SyncFbTimelineCreateSW(psSyncFbTimelineCreateSWIN->ui32TimelineNameSize,
+                                  uiTimelineNameInt, &psTimelineInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbTimelineCreateSWOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbTimelineCreateSW_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbTimelineCreateSWOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbTimelineCreateSWOUT->hTimeline,
+                                     (void *)psTimelineInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbTimelineCreateSWpsTimelineIntRelease);
+       if (unlikely(psSyncFbTimelineCreateSWOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbTimelineCreateSW_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbTimelineCreateSW_exit:
+
+       if (psSyncFbTimelineCreateSWOUT->eError != PVRSRV_OK)
+       {
+               if (psTimelineInt)
+               {
+                       SyncFbTimelineRelease(psTimelineInt);
+               }
+       }
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncFbTimelineCreateSWOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static PVRSRV_ERROR _SyncFbFenceCreateSWpsOutFenceIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER *) pvData);
+       return eError;
+}
+
+static_assert(SYNC_FB_FENCE_MAX_LENGTH <= IMG_UINT32_MAX,
+             "SYNC_FB_FENCE_MAX_LENGTH must not be larger than IMG_UINT32_MAX");
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceCreateSW(IMG_UINT32 ui32DispatchTableEntry,
+                               IMG_UINT8 * psSyncFbFenceCreateSWIN_UI8,
+                               IMG_UINT8 * psSyncFbFenceCreateSWOUT_UI8,
+                               CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCECREATESW *psSyncFbFenceCreateSWIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCECREATESW *) IMG_OFFSET_ADDR(psSyncFbFenceCreateSWIN_UI8,
+                                                                    0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCECREATESW *psSyncFbFenceCreateSWOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCECREATESW *) IMG_OFFSET_ADDR(psSyncFbFenceCreateSWOUT_UI8,
+                                                                     0);
+
+       IMG_HANDLE hTimeline = psSyncFbFenceCreateSWIN->hTimeline;
+       PVRSRV_TIMELINE_SERVER *psTimelineInt = NULL;
+       IMG_CHAR *uiFenceNameInt = NULL;
+       PVRSRV_FENCE_SERVER *psOutFenceInt = NULL;
+
+       IMG_UINT32 ui32NextOffset = 0;
+       IMG_BYTE *pArrayArgsBuffer = NULL;
+#if !defined(INTEGRITY_OS)
+       IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
+#endif
+
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncFbFenceCreateSWIN->ui32FenceNameSize * sizeof(IMG_CHAR)) + 0;
+
+       if (unlikely(psSyncFbFenceCreateSWIN->ui32FenceNameSize > SYNC_FB_FENCE_MAX_LENGTH))
+       {
+               psSyncFbFenceCreateSWOUT->eError = PVRSRV_ERROR_BRIDGE_ARRAY_SIZE_TOO_BIG;
+               goto SyncFbFenceCreateSW_exit;
+       }
+
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncFbFenceCreateSWOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncFbFenceCreateSW_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
+       if (ui32BufferSize != 0)
+       {
+#if !defined(INTEGRITY_OS)
+               /* Try to use remainder of input buffer for copies if possible, word-aligned for safety. */
+               IMG_UINT32 ui32InBufferOffset =
+                   PVR_ALIGN(sizeof(*psSyncFbFenceCreateSWIN), sizeof(unsigned long));
+               IMG_UINT32 ui32InBufferExcessSize =
+                   ui32InBufferOffset >=
+                   PVRSRV_MAX_BRIDGE_IN_SIZE ? 0 : PVRSRV_MAX_BRIDGE_IN_SIZE - ui32InBufferOffset;
+
+               bHaveEnoughSpace = ui32BufferSize <= ui32InBufferExcessSize;
+               if (bHaveEnoughSpace)
+               {
+                       IMG_BYTE *pInputBuffer = (IMG_BYTE *) (void *)psSyncFbFenceCreateSWIN;
+
+                       pArrayArgsBuffer = &pInputBuffer[ui32InBufferOffset];
+               }
+               else
+#endif
+               {
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
+
+                       if (!pArrayArgsBuffer)
+                       {
+                               psSyncFbFenceCreateSWOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto SyncFbFenceCreateSW_exit;
+                       }
+               }
+       }
+
+       if (psSyncFbFenceCreateSWIN->ui32FenceNameSize != 0)
+       {
+               uiFenceNameInt = (IMG_CHAR *) IMG_OFFSET_ADDR(pArrayArgsBuffer, ui32NextOffset);
+               ui32NextOffset += psSyncFbFenceCreateSWIN->ui32FenceNameSize * sizeof(IMG_CHAR);
+       }
+
+       /* Copy the data over */
+       if (psSyncFbFenceCreateSWIN->ui32FenceNameSize * sizeof(IMG_CHAR) > 0)
+       {
+               if (OSCopyFromUser
+                   (NULL, uiFenceNameInt,
+                    (const void __user *)psSyncFbFenceCreateSWIN->puiFenceName,
+                    psSyncFbFenceCreateSWIN->ui32FenceNameSize * sizeof(IMG_CHAR)) != PVRSRV_OK)
+               {
+                       psSyncFbFenceCreateSWOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+
+                       goto SyncFbFenceCreateSW_exit;
+               }
+               ((IMG_CHAR *)
+                uiFenceNameInt)[(psSyncFbFenceCreateSWIN->ui32FenceNameSize * sizeof(IMG_CHAR)) -
+                                1] = '\0';
+       }
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceCreateSWOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psTimelineInt,
+                                      hTimeline,
+                                      PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceCreateSWOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceCreateSW_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceCreateSWOUT->eError =
+           SyncFbFenceCreateSW(psConnection, OSGetDevNode(psConnection),
+                               psTimelineInt,
+                               psSyncFbFenceCreateSWIN->ui32FenceNameSize,
+                               uiFenceNameInt,
+                               &psOutFenceInt, &psSyncFbFenceCreateSWOUT->ui64SyncPtIdx);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceCreateSWOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceCreateSW_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceCreateSWOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbFenceCreateSWOUT->hOutFence, (void *)psOutFenceInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbFenceCreateSWpsOutFenceIntRelease);
+       if (unlikely(psSyncFbFenceCreateSWOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceCreateSW_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceCreateSW_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psTimelineInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hTimeline, PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       if (psSyncFbFenceCreateSWOUT->eError != PVRSRV_OK)
+       {
+               if (psOutFenceInt)
+               {
+                       SyncFbFenceRelease(psOutFenceInt);
+               }
+       }
+
+       /* Allocated space should be equal to the last updated offset */
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncFbFenceCreateSWOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
+
+#if defined(INTEGRITY_OS)
+       if (pArrayArgsBuffer)
+#else
+       if (!bHaveEnoughSpace && pArrayArgsBuffer)
+#endif
+               OSFreeMemNoStats(pArrayArgsBuffer);
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbTimelineAdvanceSW(IMG_UINT32 ui32DispatchTableEntry,
+                                   IMG_UINT8 * psSyncFbTimelineAdvanceSWIN_UI8,
+                                   IMG_UINT8 * psSyncFbTimelineAdvanceSWOUT_UI8,
+                                   CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBTIMELINEADVANCESW *psSyncFbTimelineAdvanceSWIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBTIMELINEADVANCESW *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineAdvanceSWIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBTIMELINEADVANCESW *psSyncFbTimelineAdvanceSWOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBTIMELINEADVANCESW *)
+           IMG_OFFSET_ADDR(psSyncFbTimelineAdvanceSWOUT_UI8, 0);
+
+       IMG_HANDLE hTimeline = psSyncFbTimelineAdvanceSWIN->hTimeline;
+       PVRSRV_TIMELINE_SERVER *psTimelineInt = NULL;
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbTimelineAdvanceSWOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psTimelineInt,
+                                      hTimeline,
+                                      PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbTimelineAdvanceSWOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbTimelineAdvanceSW_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbTimelineAdvanceSWOUT->eError =
+           SyncFbTimelineAdvanceSW(psTimelineInt, &psSyncFbTimelineAdvanceSWOUT->ui64SyncPtIdx);
+
+SyncFbTimelineAdvanceSW_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psTimelineInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hTimeline, PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       return 0;
+}
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+static PVRSRV_ERROR _SyncFbFenceExportInsecurepsExportIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceExportDestroyInsecure((PVRSRV_FENCE_EXPORT *) pvData);
+       return eError;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceExportInsecure(IMG_UINT32 ui32DispatchTableEntry,
+                                     IMG_UINT8 * psSyncFbFenceExportInsecureIN_UI8,
+                                     IMG_UINT8 * psSyncFbFenceExportInsecureOUT_UI8,
+                                     CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTINSECURE *psSyncFbFenceExportInsecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportInsecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTINSECURE *psSyncFbFenceExportInsecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportInsecureOUT_UI8, 0);
+
+       IMG_HANDLE hFence = psSyncFbFenceExportInsecureIN->hFence;
+       PVRSRV_FENCE_SERVER *psFenceInt = NULL;
+       PVRSRV_FENCE_EXPORT *psExportInt = NULL;
+       IMG_HANDLE hExportInt = NULL;
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceExportInsecureOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psFenceInt,
+                                      hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceExportInsecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceExportInsecure_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceExportInsecureOUT->eError =
+           SyncFbFenceExportInsecure(psFenceInt, &psExportInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceExportInsecureOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceExportInsecure_exit;
+       }
+
+       /*
+        * For cases where we need a cross process handle we actually allocate two.
+        *
+        * The first one is a connection specific handle and it gets given the real
+        * release function. This handle does *NOT* get returned to the caller. It's
+        * purpose is to release any leaked resources when we either have a bad or
+        * abnormally terminated client. If we didn't do this then the resource
+        * wouldn't be freed until driver unload. If the resource is freed normally,
+        * this handle can be looked up via the cross process handle and then
+        * released accordingly.
+        *
+        * The second one is a cross process handle and it gets given a noop release
+        * function. This handle does get returned to the caller.
+        */
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceExportInsecureOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase, &hExportInt,
+                                     (void *)psExportInt, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbFenceExportInsecurepsExportIntRelease);
+       if (unlikely(psSyncFbFenceExportInsecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceExportInsecure_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Lock over handle creation. */
+       LockHandle(KERNEL_HANDLE_BASE);
+       psSyncFbFenceExportInsecureOUT->eError = PVRSRVAllocHandleUnlocked(KERNEL_HANDLE_BASE,
+                                                                          &psSyncFbFenceExportInsecureOUT->
+                                                                          hExport,
+                                                                          (void *)psExportInt,
+                                                                          PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT,
+                                                                          PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+                                                                          (PFN_HANDLE_RELEASE) &
+                                                                          ReleaseExport);
+       if (unlikely(psSyncFbFenceExportInsecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(KERNEL_HANDLE_BASE);
+               goto SyncFbFenceExportInsecure_exit;
+       }
+       /* Release now we have created handles. */
+       UnlockHandle(KERNEL_HANDLE_BASE);
+
+SyncFbFenceExportInsecure_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psFenceInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       if (psSyncFbFenceExportInsecureOUT->eError != PVRSRV_OK)
+       {
+               if (psSyncFbFenceExportInsecureOUT->hExport)
+               {
+                       PVRSRV_ERROR eError;
+
+                       /* Lock over handle creation cleanup. */
+                       LockHandle(KERNEL_HANDLE_BASE);
+
+                       eError = PVRSRVDestroyHandleUnlocked(KERNEL_HANDLE_BASE,
+                                                            (IMG_HANDLE)
+                                                            psSyncFbFenceExportInsecureOUT->
+                                                            hExport,
+                                                            PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+                       if (unlikely((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY)))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: %s", __func__, PVRSRVGetErrorString(eError)));
+                       }
+                       /* Releasing the handle should free/destroy/release the resource.
+                        * This should never fail... */
+                       PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+                       /* Release now we have cleaned up creation handles. */
+                       UnlockHandle(KERNEL_HANDLE_BASE);
+
+               }
+
+               if (hExportInt)
+               {
+                       PVRSRV_ERROR eError;
+                       /* Lock over handle creation cleanup. */
+                       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+                       eError =
+                           PVRSRVDestroyHandleUnlocked(psConnection->psProcessHandleBase->
+                                                       psHandleBase, hExportInt,
+                                                       PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+                       if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: %s", __func__, PVRSRVGetErrorString(eError)));
+                       }
+                       /* Releasing the handle should free/destroy/release the resource.
+                        * This should never fail... */
+                       PVR_ASSERT((eError == PVRSRV_OK) || (eError == PVRSRV_ERROR_RETRY));
+
+                       /* Avoid freeing/destroying/releasing the resource a second time below */
+                       psExportInt = NULL;
+                       /* Release now we have cleaned up creation handles. */
+                       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               }
+
+               if (psExportInt)
+               {
+                       SyncFbFenceExportDestroyInsecure(psExportInt);
+               }
+       }
+
+       return 0;
+}
+
+#else
+#define PVRSRVBridgeSyncFbFenceExportInsecure NULL
+#endif
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceExportDestroyInsecure(IMG_UINT32 ui32DispatchTableEntry,
+                                            IMG_UINT8 * psSyncFbFenceExportDestroyInsecureIN_UI8,
+                                            IMG_UINT8 * psSyncFbFenceExportDestroyInsecureOUT_UI8,
+                                            CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYINSECURE *psSyncFbFenceExportDestroyInsecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportDestroyInsecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYINSECURE *psSyncFbFenceExportDestroyInsecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportDestroyInsecureOUT_UI8, 0);
+
+       PVRSRV_FENCE_EXPORT *psExportInt = NULL;
+       IMG_HANDLE hExportInt = NULL;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       /* Lock over handle destruction. */
+       LockHandle(KERNEL_HANDLE_BASE);
+       psSyncFbFenceExportDestroyInsecureOUT->eError =
+           PVRSRVLookupHandleUnlocked(KERNEL_HANDLE_BASE,
+                                      (void **)&psExportInt,
+                                      (IMG_HANDLE) psSyncFbFenceExportDestroyInsecureIN->hExport,
+                                      PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT, IMG_FALSE);
+       if (unlikely(psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_OK))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__,
+                        PVRSRVGetErrorString(psSyncFbFenceExportDestroyInsecureOUT->eError)));
+       }
+       PVR_ASSERT(psSyncFbFenceExportDestroyInsecureOUT->eError == PVRSRV_OK);
+
+       /* Release now we have destroyed handles. */
+       UnlockHandle(KERNEL_HANDLE_BASE);
+
+       /* Lock over handle destruction. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+       /*
+        * Find the connection specific handle that represents the same data
+        * as the cross process handle as releasing it will actually call the
+        * data's real release function (see the function where the cross
+        * process handle is allocated for more details).
+        */
+       psSyncFbFenceExportDestroyInsecureOUT->eError =
+           PVRSRVFindHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                    &hExportInt,
+                                    psExportInt, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+       if (unlikely(psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_OK))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__,
+                        PVRSRVGetErrorString(psSyncFbFenceExportDestroyInsecureOUT->eError)));
+       }
+       PVR_ASSERT(psSyncFbFenceExportDestroyInsecureOUT->eError == PVRSRV_OK);
+
+       psSyncFbFenceExportDestroyInsecureOUT->eError =
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                             hExportInt, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+       if (unlikely((psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_OK) &&
+                    (psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+                    && (psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_ERROR_RETRY)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__,
+                        PVRSRVGetErrorString(psSyncFbFenceExportDestroyInsecureOUT->eError)));
+       }
+       PVR_ASSERT((psSyncFbFenceExportDestroyInsecureOUT->eError == PVRSRV_OK) ||
+                  (psSyncFbFenceExportDestroyInsecureOUT->eError == PVRSRV_ERROR_RETRY));
+       /* Release now we have destroyed handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Lock over handle destruction. */
+       LockHandle(KERNEL_HANDLE_BASE);
+
+       psSyncFbFenceExportDestroyInsecureOUT->eError =
+           PVRSRVDestroyHandleStagedUnlocked(KERNEL_HANDLE_BASE,
+                                             (IMG_HANDLE) psSyncFbFenceExportDestroyInsecureIN->
+                                             hExport, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+       if (unlikely
+           ((psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_OK)
+            && (psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+            && (psSyncFbFenceExportDestroyInsecureOUT->eError != PVRSRV_ERROR_RETRY)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__,
+                        PVRSRVGetErrorString(psSyncFbFenceExportDestroyInsecureOUT->eError)));
+               UnlockHandle(KERNEL_HANDLE_BASE);
+               goto SyncFbFenceExportDestroyInsecure_exit;
+       }
+
+       /* Release now we have destroyed handles. */
+       UnlockHandle(KERNEL_HANDLE_BASE);
+
+SyncFbFenceExportDestroyInsecure_exit:
+
+       return 0;
+}
+
+#else
+#define PVRSRVBridgeSyncFbFenceExportDestroyInsecure NULL
+#endif
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+static PVRSRV_ERROR _SyncFbFenceImportInsecurepsSyncHandleIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER *) pvData);
+       return eError;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceImportInsecure(IMG_UINT32 ui32DispatchTableEntry,
+                                     IMG_UINT8 * psSyncFbFenceImportInsecureIN_UI8,
+                                     IMG_UINT8 * psSyncFbFenceImportInsecureOUT_UI8,
+                                     CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTINSECURE *psSyncFbFenceImportInsecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceImportInsecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTINSECURE *psSyncFbFenceImportInsecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTINSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceImportInsecureOUT_UI8, 0);
+
+       IMG_HANDLE hImport = psSyncFbFenceImportInsecureIN->hImport;
+       PVRSRV_FENCE_EXPORT *psImportInt = NULL;
+       PVRSRV_FENCE_SERVER *psSyncHandleInt = NULL;
+
+       /* Lock over handle lookup. */
+       LockHandle(KERNEL_HANDLE_BASE);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceImportInsecureOUT->eError =
+           PVRSRVLookupHandleUnlocked(KERNEL_HANDLE_BASE,
+                                      (void **)&psImportInt,
+                                      hImport, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT, IMG_TRUE);
+       if (unlikely(psSyncFbFenceImportInsecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(KERNEL_HANDLE_BASE);
+               goto SyncFbFenceImportInsecure_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(KERNEL_HANDLE_BASE);
+
+       psSyncFbFenceImportInsecureOUT->eError =
+           SyncFbFenceImportInsecure(psConnection, OSGetDevNode(psConnection),
+                                     psImportInt, &psSyncHandleInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceImportInsecureOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceImportInsecure_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceImportInsecureOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbFenceImportInsecureOUT->hSyncHandle,
+                                     (void *)psSyncHandleInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbFenceImportInsecurepsSyncHandleIntRelease);
+       if (unlikely(psSyncFbFenceImportInsecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceImportInsecure_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceImportInsecure_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(KERNEL_HANDLE_BASE);
+
+       /* Unreference the previously looked up handle */
+       if (psImportInt)
+       {
+               PVRSRVReleaseHandleUnlocked(KERNEL_HANDLE_BASE,
+                                           hImport, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(KERNEL_HANDLE_BASE);
+
+       if (psSyncFbFenceImportInsecureOUT->eError != PVRSRV_OK)
+       {
+               if (psSyncHandleInt)
+               {
+                       SyncFbFenceRelease(psSyncHandleInt);
+               }
+       }
+
+       return 0;
+}
+
+#else
+#define PVRSRVBridgeSyncFbFenceImportInsecure NULL
+#endif
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceExportSecure(IMG_UINT32 ui32DispatchTableEntry,
+                                   IMG_UINT8 * psSyncFbFenceExportSecureIN_UI8,
+                                   IMG_UINT8 * psSyncFbFenceExportSecureOUT_UI8,
+                                   CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTSECURE *psSyncFbFenceExportSecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportSecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTSECURE *psSyncFbFenceExportSecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportSecureOUT_UI8, 0);
+
+       IMG_HANDLE hFence = psSyncFbFenceExportSecureIN->hFence;
+       PVRSRV_FENCE_SERVER *psFenceInt = NULL;
+       PVRSRV_FENCE_EXPORT *psExportInt = NULL;
+       CONNECTION_DATA *psSecureConnection;
+
+       /* Lock over handle lookup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Look up the address from the handle */
+       psSyncFbFenceExportSecureOUT->eError =
+           PVRSRVLookupHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                      (void **)&psFenceInt,
+                                      hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER, IMG_TRUE);
+       if (unlikely(psSyncFbFenceExportSecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceExportSecure_exit;
+       }
+       /* Release now we have looked up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceExportSecureOUT->eError =
+           SyncFbFenceExportSecure(psConnection, OSGetDevNode(psConnection),
+                                   psFenceInt,
+                                   &psSyncFbFenceExportSecureOUT->Export,
+                                   &psExportInt, &psSecureConnection);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceExportSecureOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceExportSecure_exit;
+       }
+
+SyncFbFenceExportSecure_exit:
+
+       /* Lock over handle lookup cleanup. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       /* Unreference the previously looked up handle */
+       if (psFenceInt)
+       {
+               PVRSRVReleaseHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                           hFence, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       }
+       /* Release now we have cleaned up look up handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       if (psSyncFbFenceExportSecureOUT->eError != PVRSRV_OK)
+       {
+               if (psExportInt)
+               {
+                       SyncFbFenceExportDestroySecure(psExportInt);
+               }
+       }
+
+       return 0;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceExportDestroySecure(IMG_UINT32 ui32DispatchTableEntry,
+                                          IMG_UINT8 * psSyncFbFenceExportDestroySecureIN_UI8,
+                                          IMG_UINT8 * psSyncFbFenceExportDestroySecureOUT_UI8,
+                                          CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYSECURE *psSyncFbFenceExportDestroySecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEEXPORTDESTROYSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportDestroySecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYSECURE *psSyncFbFenceExportDestroySecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEEXPORTDESTROYSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceExportDestroySecureOUT_UI8, 0);
+
+       /* Lock over handle destruction. */
+       LockHandle(psConnection->psHandleBase);
+
+       psSyncFbFenceExportDestroySecureOUT->eError =
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psSyncFbFenceExportDestroySecureIN->
+                                             hExport, PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_EXPORT);
+       if (unlikely
+           ((psSyncFbFenceExportDestroySecureOUT->eError != PVRSRV_OK)
+            && (psSyncFbFenceExportDestroySecureOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL)
+            && (psSyncFbFenceExportDestroySecureOUT->eError != PVRSRV_ERROR_RETRY)))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: %s",
+                        __func__,
+                        PVRSRVGetErrorString(psSyncFbFenceExportDestroySecureOUT->eError)));
+               UnlockHandle(psConnection->psHandleBase);
+               goto SyncFbFenceExportDestroySecure_exit;
+       }
+
+       /* Release now we have destroyed handles. */
+       UnlockHandle(psConnection->psHandleBase);
+
+SyncFbFenceExportDestroySecure_exit:
+
+       return 0;
+}
+
+static PVRSRV_ERROR _SyncFbFenceImportSecurepsSyncHandleIntRelease(void *pvData)
+{
+       PVRSRV_ERROR eError;
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER *) pvData);
+       return eError;
+}
+
+static IMG_INT
+PVRSRVBridgeSyncFbFenceImportSecure(IMG_UINT32 ui32DispatchTableEntry,
+                                   IMG_UINT8 * psSyncFbFenceImportSecureIN_UI8,
+                                   IMG_UINT8 * psSyncFbFenceImportSecureOUT_UI8,
+                                   CONNECTION_DATA * psConnection)
+{
+       PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTSECURE *psSyncFbFenceImportSecureIN =
+           (PVRSRV_BRIDGE_IN_SYNCFBFENCEIMPORTSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceImportSecureIN_UI8, 0);
+       PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTSECURE *psSyncFbFenceImportSecureOUT =
+           (PVRSRV_BRIDGE_OUT_SYNCFBFENCEIMPORTSECURE *)
+           IMG_OFFSET_ADDR(psSyncFbFenceImportSecureOUT_UI8, 0);
+
+       PVRSRV_FENCE_SERVER *psSyncHandleInt = NULL;
+
+       psSyncFbFenceImportSecureOUT->eError =
+           SyncFbFenceImportSecure(psConnection, OSGetDevNode(psConnection),
+                                   psSyncFbFenceImportSecureIN->Import, &psSyncHandleInt);
+       /* Exit early if bridged call fails */
+       if (unlikely(psSyncFbFenceImportSecureOUT->eError != PVRSRV_OK))
+       {
+               goto SyncFbFenceImportSecure_exit;
+       }
+
+       /* Lock over handle creation. */
+       LockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+       psSyncFbFenceImportSecureOUT->eError =
+           PVRSRVAllocHandleUnlocked(psConnection->psProcessHandleBase->psHandleBase,
+                                     &psSyncFbFenceImportSecureOUT->hSyncHandle,
+                                     (void *)psSyncHandleInt,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                     PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                     (PFN_HANDLE_RELEASE) &
+                                     _SyncFbFenceImportSecurepsSyncHandleIntRelease);
+       if (unlikely(psSyncFbFenceImportSecureOUT->eError != PVRSRV_OK))
+       {
+               UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+               goto SyncFbFenceImportSecure_exit;
+       }
+
+       /* Release now we have created handles. */
+       UnlockHandle(psConnection->psProcessHandleBase->psHandleBase);
+
+SyncFbFenceImportSecure_exit:
+
+       if (psSyncFbFenceImportSecureOUT->eError != PVRSRV_OK)
+       {
+               if (psSyncHandleInt)
+               {
+                       SyncFbFenceRelease(psSyncHandleInt);
+               }
+       }
+
+       return 0;
+}
+
+/* ***************************************************************************
+ * Server bridge dispatch related glue
+ */
+
+PVRSRV_ERROR InitSYNCFALLBACKBridge(void);
+void DeinitSYNCFALLBACKBridge(void);
+
+/*
+ * Register all SYNCFALLBACK functions with services
+ */
+PVRSRV_ERROR InitSYNCFALLBACKBridge(void)
+{
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATEPVR,
+                             PVRSRVBridgeSyncFbTimelineCreatePVR, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINERELEASE,
+                             PVRSRVBridgeSyncFbTimelineRelease, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK, PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUP,
+                             PVRSRVBridgeSyncFbFenceDup, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEMERGE,
+                             PVRSRVBridgeSyncFbFenceMerge, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCERELEASE,
+                             PVRSRVBridgeSyncFbFenceRelease, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEWAIT,
+                             PVRSRVBridgeSyncFbFenceWait, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUMP,
+                             PVRSRVBridgeSyncFbFenceDump, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATESW,
+                             PVRSRVBridgeSyncFbTimelineCreateSW, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCECREATESW,
+                             PVRSRVBridgeSyncFbFenceCreateSW, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINEADVANCESW,
+                             PVRSRVBridgeSyncFbTimelineAdvanceSW, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTINSECURE,
+                             PVRSRVBridgeSyncFbFenceExportInsecure, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYINSECURE,
+                             PVRSRVBridgeSyncFbFenceExportDestroyInsecure, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTINSECURE,
+                             PVRSRVBridgeSyncFbFenceImportInsecure, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTSECURE,
+                             PVRSRVBridgeSyncFbFenceExportSecure, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYSECURE,
+                             PVRSRVBridgeSyncFbFenceExportDestroySecure, NULL);
+
+       SetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                             PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTSECURE,
+                             PVRSRVBridgeSyncFbFenceImportSecure, NULL);
+
+       return PVRSRV_OK;
+}
+
+/*
+ * Unregister all syncfallback functions with services
+ */
+void DeinitSYNCFALLBACKBridge(void)
+{
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATEPVR);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINERELEASE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUP);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEMERGE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCERELEASE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEWAIT);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEDUMP);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINECREATESW);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCECREATESW);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBTIMELINEADVANCESW);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTINSECURE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYINSECURE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTINSECURE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTSECURE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEEXPORTDESTROYSECURE);
+
+       UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCFALLBACK,
+                               PVRSRV_BRIDGE_SYNCFALLBACK_SYNCFBFENCEIMPORTSECURE);
+
+}
index db28988..adc8ab4 100644 (file)
@@ -83,10 +83,11 @@ PVRSRVBridgeSyncRecordRemoveByHandle(IMG_UINT32 ui32DispatchTableEntry,
        LockHandle(psConnection->psHandleBase);
 
        psSyncRecordRemoveByHandleOUT->eError =
-           PVRSRVReleaseHandleStagedUnlock(psConnection->psHandleBase,
-                                           (IMG_HANDLE) psSyncRecordRemoveByHandleIN->hhRecord,
-                                           PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
+           PVRSRVDestroyHandleStagedUnlocked(psConnection->psHandleBase,
+                                             (IMG_HANDLE) psSyncRecordRemoveByHandleIN->hhRecord,
+                                             PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE);
        if (unlikely((psSyncRecordRemoveByHandleOUT->eError != PVRSRV_OK) &&
+                    (psSyncRecordRemoveByHandleOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) &&
                     (psSyncRecordRemoveByHandleOUT->eError != PVRSRV_ERROR_RETRY)))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -111,6 +112,9 @@ static PVRSRV_ERROR _SyncRecordAddpshRecordIntRelease(void *pvData)
        return eError;
 }
 
+static_assert(PVRSRV_SYNC_NAME_LENGTH <= IMG_UINT32_MAX,
+             "PVRSRV_SYNC_NAME_LENGTH must not be larger than IMG_UINT32_MAX");
+
 static IMG_INT
 PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
                          IMG_UINT8 * psSyncRecordAddIN_UI8,
@@ -132,7 +136,9 @@ PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
        IMG_BOOL bHaveEnoughSpace = IMG_FALSE;
 #endif
 
-       IMG_UINT32 ui32BufferSize = (psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) + 0;
+       IMG_UINT32 ui32BufferSize = 0;
+       IMG_UINT64 ui64BufferSize =
+           ((IMG_UINT64) psSyncRecordAddIN->ui32ClassNameSize * sizeof(IMG_CHAR)) + 0;
 
        if (unlikely(psSyncRecordAddIN->ui32ClassNameSize > PVRSRV_SYNC_NAME_LENGTH))
        {
@@ -140,6 +146,14 @@ PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
                goto SyncRecordAdd_exit;
        }
 
+       if (ui64BufferSize > IMG_UINT32_MAX)
+       {
+               psSyncRecordAddOUT->eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+               goto SyncRecordAdd_exit;
+       }
+
+       ui32BufferSize = (IMG_UINT32) ui64BufferSize;
+
        if (ui32BufferSize != 0)
        {
 #if !defined(INTEGRITY_OS)
@@ -160,7 +174,7 @@ PVRSRVBridgeSyncRecordAdd(IMG_UINT32 ui32DispatchTableEntry,
                else
 #endif
                {
-                       pArrayArgsBuffer = OSAllocZMemNoStats(ui32BufferSize);
+                       pArrayArgsBuffer = OSAllocMemNoStats(ui32BufferSize);
 
                        if (!pArrayArgsBuffer)
                        {
@@ -266,7 +280,10 @@ SyncRecordAdd_exit:
        }
 
        /* Allocated space should be equal to the last updated offset */
-       PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#ifdef PVRSRV_NEED_PVR_ASSERT
+       if (psSyncRecordAddOUT->eError == PVRSRV_OK)
+               PVR_ASSERT(ui32BufferSize == ui32NextOffset);
+#endif /* PVRSRV_NEED_PVR_ASSERT */
 
 #if defined(INTEGRITY_OS)
        if (pArrayArgsBuffer)
@@ -283,7 +300,7 @@ SyncRecordAdd_exit:
  */
 
 PVRSRV_ERROR InitSYNCTRACKINGBridge(void);
-PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void);
+void DeinitSYNCTRACKINGBridge(void);
 
 /*
  * Register all SYNCTRACKING functions with services
@@ -304,7 +321,7 @@ PVRSRV_ERROR InitSYNCTRACKINGBridge(void)
 /*
  * Unregister all synctracking functions with services
  */
-PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void)
+void DeinitSYNCTRACKINGBridge(void)
 {
 
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCTRACKING,
@@ -313,5 +330,4 @@ PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void)
        UnsetDispatchTableEntry(PVRSRV_BRIDGE_SYNCTRACKING,
                                PVRSRV_BRIDGE_SYNCTRACKING_SYNCRECORDADD);
 
-       return PVRSRV_OK;
 }
index aeaf334..88b1231 100644 (file)
@@ -60,6 +60,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_COMPUTE_OVERLAP
 #define RGX_FEATURE_FBCDC_ALGORITHM (1U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (MTP218)
index 1c8b1c1..ec1bbd6 100644 (file)
@@ -60,6 +60,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_COMPUTE_OVERLAP
 #define RGX_FEATURE_FBCDC_ALGORITHM (1U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (MTP218)
index 44be042..b29afcf 100644 (file)
@@ -59,6 +59,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_COMPUTE_OVERLAP
 #define RGX_FEATURE_FBCDC_ALGORITHM (1U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (MTP218)
index c38e433..a23aebf 100644 (file)
@@ -60,6 +60,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -75,8 +77,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_15_V_1_64_H */
index 1ccf77a..4654391 100644 (file)
@@ -78,9 +78,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_104_18_H */
index 6da7eef..fd5a4d5 100644 (file)
@@ -61,6 +61,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -81,9 +83,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_104_218_H */
index 07e6880..f98ba97 100644 (file)
@@ -61,6 +61,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -81,9 +83,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (2U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_208_318_H */
index ee4c407..0563b1b 100644 (file)
@@ -78,9 +78,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (8U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_21_16_H */
index 511ed0f..05d0a79 100644 (file)
@@ -78,9 +78,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_54_25_H */
index f965862..a16f199 100644 (file)
@@ -78,9 +78,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_54_30_H */
index e0f4745..810b58b 100644 (file)
@@ -61,6 +61,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -81,9 +83,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_54_330_H */
index 1df93c3..84f3454 100644 (file)
@@ -78,9 +78,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_22_V_54_38_H */
index 8a07f8e..bd1d4de 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -83,11 +85,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_24_V_104_504_H */
index 61fed85..ee4a2a5 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -83,11 +85,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (2U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_24_V_208_504_H */
index 17a1a93..9d82a54 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -83,11 +85,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (2U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_24_V_208_505_H */
index 3d06e28..35d2676 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (3U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (3U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -83,11 +85,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (64U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_24_V_54_204_H */
index 0a06cbf..f4c1bb5 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (4U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (4U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -84,6 +86,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (2U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
@@ -91,6 +94,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_29_V_108_208_H */
index 7b57433..a7ee725 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (4U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (4U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_IRQ_PER_OS
@@ -84,6 +86,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TDM_PDS_CHECKSUM
 #define RGX_FEATURE_TILE_SIZE_X (16U)
@@ -91,6 +94,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_29_V_52_202_H */
index fd5094f..acc75a0 100644 (file)
@@ -85,6 +85,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_33_V_11_3_H */
index 3c0362d..80a5d3c 100644 (file)
@@ -80,12 +80,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
 #endif /* RGXCONFIG_KM_33_V_22_1_H */
index cb251a8..0a6cdb0 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (50U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (50U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_MULTICORE_SUPPORT
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
@@ -87,12 +89,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                           /* size must be sourced from */
                                           /* register. */
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 #define RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH (19U)
 #define RGX_FEATURE_XPU_MAX_SLAVES (3U)
diff --git a/drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.104.183.h b/drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.104.183.h
new file mode 100644 (file)
index 0000000..6de1c1b
--- /dev/null
@@ -0,0 +1,105 @@
+/*************************************************************************/ /*!
+@Title          RGX Configuration for BVNC 36.V.104.183 (kernel defines)
+@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.
+*/ /**************************************************************************/
+
+#ifndef RGXCONFIG_KM_36_V_104_183_H
+#define RGXCONFIG_KM_36_V_104_183_H
+
+/***** Automatically generated file. Do not edit manually ********************/
+
+/******************************************************************************
+ * B.V.N.C Validation defines
+ *****************************************************************************/
+#define RGX_BNC_KM_B 36
+#define RGX_BNC_KM_N 104
+#define RGX_BNC_KM_C 183
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT (1U)
+#define RGX_FEATURE_COMPUTE
+#define RGX_FEATURE_COMPUTE_OVERLAP
+#define RGX_FEATURE_COREID_PER_OS
+#define RGX_FEATURE_FBCDC (50U)
+#define RGX_FEATURE_FBCDC_ALGORITHM (50U)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
+#define RGX_FEATURE_GPU_MULTICORE_SUPPORT
+#define RGX_FEATURE_GPU_VIRTUALISATION
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_IRQ_PER_OS
+#define RGX_FEATURE_LAYOUT_MARS (1U)
+#define RGX_FEATURE_MIPS
+#define RGX_FEATURE_NUM_CLUSTERS (1U)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (6U)
+#define RGX_FEATURE_NUM_OSIDS (8U)
+#define RGX_FEATURE_NUM_RASTER_PIPES (1U)
+#define RGX_FEATURE_PBE2_IN_XE
+#define RGX_FEATURE_PBVNC_COREID_REG
+#define RGX_FEATURE_PERFBUS
+#define RGX_FEATURE_PHYS_BUS_WIDTH (36U)
+#define RGX_FEATURE_ROGUEXE
+#define RGX_FEATURE_SIMPLE_INTERNAL_PARAMETER_FORMAT
+#define RGX_FEATURE_SIMPLE_INTERNAL_PARAMETER_FORMAT_V2
+#define RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION (2U)
+#define RGX_FEATURE_SLC_BANKS (1U)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
+#define RGX_FEATURE_SLC_SIZE_CONFIGURABLE /* Specifies the SLC is */
+                                          /* customer-configurable. True SLC */
+                                          /* size must be sourced from */
+                                          /* register. */
+#define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET
+#define RGX_FEATURE_TILE_SIZE_X (16U)
+#define RGX_FEATURE_TILE_SIZE_Y (16U)
+#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
+#define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
+#define RGX_FEATURE_XE_MEMORY_HIERARCHY
+#define RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH (19U)
+#define RGX_FEATURE_XPU_MAX_SLAVES (3U)
+#define RGX_FEATURE_XPU_REGISTER_BROADCAST (1U)
+
+#endif /* RGXCONFIG_KM_36_V_104_183_H */
index 0494edb..9fe1913 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (50U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (50U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_MULTICORE_SUPPORT
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
@@ -88,6 +90,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                           /* size must be sourced from */
                                           /* register. */
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_REGION_PROTECTION
 #define RGX_FEATURE_TILE_SIZE_X (16U)
@@ -96,6 +99,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
 #define RGX_FEATURE_WATCHDOG_TIMER
+#define RGX_FEATURE_WORKGROUP_PROTECTION
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 #define RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH (19U)
 #define RGX_FEATURE_XPU_MAX_SLAVES (3U)
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Configuration for BVNC 36.V.54.102 (kernel defines)
+@Title          RGX Configuration for BVNC 36.V.54.103 (kernel defines)
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,8 +39,8 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef RGXCONFIG_KM_36_V_54_102_H
-#define RGXCONFIG_KM_36_V_54_102_H
+#ifndef RGXCONFIG_KM_36_V_54_103_H
+#define RGXCONFIG_KM_36_V_54_103_H
 
 /***** Automatically generated file. Do not edit manually ********************/
 
@@ -49,7 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 #define RGX_BNC_KM_B 36
 #define RGX_BNC_KM_N 54
-#define RGX_BNC_KM_C 102
+#define RGX_BNC_KM_C 103
 
 /******************************************************************************
  * DDK Defines
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (50U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (50U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_MULTICORE_SUPPORT
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
@@ -86,12 +88,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                           /* size must be sourced from */
                                           /* register. */
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 
-#endif /* RGXCONFIG_KM_36_V_54_102_H */
+#endif /* RGXCONFIG_KM_36_V_54_103_H */
index 16f6967..cfbf51f 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_FBCDC (50U)
 #define RGX_FEATURE_FBCDC_ALGORITHM (50U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_MULTICORE_SUPPORT
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
@@ -87,12 +89,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                           /* size must be sourced from */
                                           /* register. */
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_SYS_BUS_SECURE_RESET
 #define RGX_FEATURE_TILE_SIZE_X (16U)
 #define RGX_FEATURE_TILE_SIZE_Y (16U)
 #define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
 #define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 #define RGX_FEATURE_XE_MEMORY_HIERARCHY
 #define RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH (19U)
 #define RGX_FEATURE_XPU_MAX_SLAVES (3U)
diff --git a/drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.183.h b/drivers/gpu/drm/img/img-rogue/hwdefs/rogue/km/configs/rgxconfig_km_36.V.54.183.h
new file mode 100644 (file)
index 0000000..244eac0
--- /dev/null
@@ -0,0 +1,105 @@
+/*************************************************************************/ /*!
+@Title          RGX Configuration for BVNC 36.V.54.183 (kernel defines)
+@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.
+*/ /**************************************************************************/
+
+#ifndef RGXCONFIG_KM_36_V_54_183_H
+#define RGXCONFIG_KM_36_V_54_183_H
+
+/***** Automatically generated file. Do not edit manually ********************/
+
+/******************************************************************************
+ * B.V.N.C Validation defines
+ *****************************************************************************/
+#define RGX_BNC_KM_B 36
+#define RGX_BNC_KM_N 54
+#define RGX_BNC_KM_C 183
+
+/******************************************************************************
+ * DDK Defines
+ *****************************************************************************/
+#define RGX_FEATURE_AXI_ACELITE
+#define RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT (1U)
+#define RGX_FEATURE_COMPUTE
+#define RGX_FEATURE_COMPUTE_OVERLAP
+#define RGX_FEATURE_COREID_PER_OS
+#define RGX_FEATURE_FBCDC (50U)
+#define RGX_FEATURE_FBCDC_ALGORITHM (50U)
+#define RGX_FEATURE_FBCDC_ARCHITECTURE (7U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
+#define RGX_FEATURE_GPU_MULTICORE_SUPPORT
+#define RGX_FEATURE_GPU_VIRTUALISATION
+#define RGX_FEATURE_GS_RTA_SUPPORT
+#define RGX_FEATURE_IRQ_PER_OS
+#define RGX_FEATURE_LAYOUT_MARS (1U)
+#define RGX_FEATURE_MIPS
+#define RGX_FEATURE_NUM_CLUSTERS (1U)
+#define RGX_FEATURE_NUM_ISP_IPP_PIPES (4U)
+#define RGX_FEATURE_NUM_OSIDS (8U)
+#define RGX_FEATURE_NUM_RASTER_PIPES (1U)
+#define RGX_FEATURE_PBE2_IN_XE
+#define RGX_FEATURE_PBVNC_COREID_REG
+#define RGX_FEATURE_PERFBUS
+#define RGX_FEATURE_PHYS_BUS_WIDTH (36U)
+#define RGX_FEATURE_ROGUEXE
+#define RGX_FEATURE_SIMPLE_INTERNAL_PARAMETER_FORMAT
+#define RGX_FEATURE_SIMPLE_INTERNAL_PARAMETER_FORMAT_V2
+#define RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION (2U)
+#define RGX_FEATURE_SLC_BANKS (1U)
+#define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
+#define RGX_FEATURE_SLC_SIZE_CONFIGURABLE /* Specifies the SLC is */
+                                          /* customer-configurable. True SLC */
+                                          /* size must be sourced from */
+                                          /* register. */
+#define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
+#define RGX_FEATURE_SYS_BUS_SECURE_RESET
+#define RGX_FEATURE_TILE_SIZE_X (16U)
+#define RGX_FEATURE_TILE_SIZE_Y (16U)
+#define RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS
+#define RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS
+#define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
+#define RGX_FEATURE_XE_MEMORY_HIERARCHY
+#define RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH (19U)
+#define RGX_FEATURE_XPU_MAX_SLAVES (3U)
+#define RGX_FEATURE_XPU_REGISTER_BROADCAST (1U)
+
+#endif /* RGXCONFIG_KM_36_V_54_183_H */
index 2464918..b12f3c2 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (LTP218)
@@ -75,6 +77,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_PHYS_BUS_WIDTH (40U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_TLA
index 7f9d18d..8a67d49 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -77,6 +79,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_PHYS_BUS_WIDTH (40U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_TLA
index 5d78851..61c165e 100644 (file)
@@ -62,6 +62,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (LTP218)
@@ -74,6 +76,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_PHYS_BUS_WIDTH (40U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_TLA
index 920b483..74aeef7 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GPU_VIRTUALISATION
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
@@ -78,6 +80,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (4U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_TLA
index abc512b..c2698fe 100644 (file)
@@ -60,6 +60,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (1U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (LTP217)
@@ -73,8 +75,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_SLC_BANKS (1U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (16U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS (40U)
+#define RGX_FEATURE_XE_ARCHITECTURE (1U)
 
 #endif /* RGXCONFIG_KM_5_V_1_46_H */
index b93d4b7..2bd20b2 100644 (file)
@@ -63,6 +63,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_DYNAMIC_DUST_POWER
 #define RGX_FEATURE_FBCDC_ALGORITHM (2U)
 #define RGX_FEATURE_FBCDC_ARCHITECTURE (2U)
+#define RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS (0U)
+#define RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS (0U)
 #define RGX_FEATURE_GS_RTA_SUPPORT
 #define RGX_FEATURE_LAYOUT_MARS (0U)
 #define RGX_FEATURE_META (LTP218)
@@ -75,6 +77,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FEATURE_PHYS_BUS_WIDTH (40U)
 #define RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS (512U)
 #define RGX_FEATURE_SLC_SIZE_IN_KILOBYTES (128U)
+#define RGX_FEATURE_SOC_TIMER
 #define RGX_FEATURE_TILE_SIZE_X (32U)
 #define RGX_FEATURE_TILE_SIZE_Y (32U)
 #define RGX_FEATURE_TLA
index 1c79d77..edd7ec5 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_1_39_4_19_H
 #define RGXCORE_KM_1_39_4_19_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @2784771 */
 
 /******************************************************************************
index 468af13..ab60c2a 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_1_75_2_30_H
 #define RGXCORE_KM_1_75_2_30_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @2309075 */
 
 /******************************************************************************
index afdc28f..7629672 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_1_82_4_5_H
 #define RGXCORE_KM_1_82_4_5_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @2503111 */
 
 /******************************************************************************
index afc9865..b96f1e1 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_15_5_1_64_H
 #define RGXCORE_KM_15_5_1_64_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @3846532 */
 
 /******************************************************************************
index a79d44e..7cd595a 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_102_54_38_H
 #define RGXCORE_KM_22_102_54_38_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4831550 */
 
 /******************************************************************************
index e12e329..a3f5e2d 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_104_208_318_H
 #define RGXCORE_KM_22_104_208_318_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5124208 */
 
 /******************************************************************************
index 08b1221..52de9fc 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_105_208_318_H
 #define RGXCORE_KM_22_105_208_318_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5324554 */
 
 /******************************************************************************
index bc444f2..aaf0ef7 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_30_54_25_H
 #define RGXCORE_KM_22_30_54_25_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4086500 */
 
 /******************************************************************************
index 11e7a56..fe9974c 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_40_54_30_H
 #define RGXCORE_KM_22_40_54_30_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4094817 */
 
 /******************************************************************************
index fde7bc6..fd40adc 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_46_54_330_H
 #define RGXCORE_KM_22_46_54_330_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4136505 */
 
 /******************************************************************************
index 97385d1..8183d38 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_49_21_16_H
 #define RGXCORE_KM_22_49_21_16_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @4158766 */
 
 /******************************************************************************
index 8e0e082..e9253c4 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_67_54_30_H
 #define RGXCORE_KM_22_67_54_30_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @4339986 */
 
 /******************************************************************************
index 9ce5f09..060261f 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_68_54_30_H
 #define RGXCORE_KM_22_68_54_30_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @4339984 */
 
 /******************************************************************************
index ef8018d..42aed9e 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_86_104_218_H
 #define RGXCORE_KM_22_86_104_218_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4665024 */
 
 /******************************************************************************
index 5becbe8..d3ed1e9 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_22_87_104_18_H
 #define RGXCORE_KM_22_87_104_18_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @4658768 */
 
 /******************************************************************************
index 39edc37..c367ce7 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_24_50_208_504_H
 #define RGXCORE_KM_24_50_208_504_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5086680 */
 
 /******************************************************************************
index 2945202..69704f1 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_24_56_208_505_H
 #define RGXCORE_KM_24_56_208_505_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5203837 */
 
 /******************************************************************************
index ea81f68..a580cb2 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_24_66_54_204_H
 #define RGXCORE_KM_24_66_54_204_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5200207 */
 
 /******************************************************************************
index ac023cc..743fd09 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_24_67_104_504_H
 #define RGXCORE_KM_24_67_104_504_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5203838 */
 
 /******************************************************************************
index fc061a7..b04ced1 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_29_14_108_208_H
 #define RGXCORE_KM_29_14_108_208_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5682134 */
 
 /******************************************************************************
index 2da1f04..42de65b 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_29_19_52_202_H
 #define RGXCORE_KM_29_19_52_202_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5691248 */
 
 /******************************************************************************
index d8d30f2..2ad607d 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_33_15_11_3_H
 #define RGXCORE_KM_33_15_11_3_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5820045 */
 
 /******************************************************************************
index c7da643..367a0c1 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_33_8_22_1_H
 #define RGXCORE_KM_33_8_22_1_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5544349 */
 
 /******************************************************************************
index a253349..a55cd70 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_36_50_54_182_H
 #define RGXCORE_KM_36_50_54_182_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5849603 */
 
 /******************************************************************************
index e27c2f7..a3f0919 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_36_52_104_182_H
 #define RGXCORE_KM_36_52_104_182_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @5849605 */
 
 /******************************************************************************
index 80951e9..80e7050 100644 (file)
@@ -42,8 +42,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_36_53_104_796_H
 #define RGXCORE_KM_36_53_104_796_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
-/* CS: @5880522 */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
+/* CS: @5896094 */
 
 /******************************************************************************
  * BVNC = 36.53.104.796
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 36.30.54.182
+@Title          RGX Core BVNC 36.54.54.183
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,19 +39,19 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef RGXCORE_KM_36_30_54_182_H
-#define RGXCORE_KM_36_30_54_182_H
+#ifndef RGXCORE_KM_36_54_54_183_H
+#define RGXCORE_KM_36_54_54_183_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
-/* CS: @5749248 */
+/* Automatically generated file (04/10/2021 09:01:51): Do not edit manually */
+/* CS: @5908021 */
 
 /******************************************************************************
- * BVNC = 36.30.54.182
+ * BVNC = 36.54.54.183
  *****************************************************************************/
 #define RGX_BVNC_KM_B 36
-#define RGX_BVNC_KM_V 30
+#define RGX_BVNC_KM_V 54
 #define RGX_BVNC_KM_N 54
-#define RGX_BVNC_KM_C 182
+#define RGX_BVNC_KM_C 183
 
 /******************************************************************************
  * Errata
@@ -71,4 +71,4 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 
-#endif /* RGXCORE_KM_36_30_54_182_H */
+#endif /* RGXCORE_KM_36_54_54_183_H */
@@ -1,5 +1,5 @@
 /*************************************************************************/ /*!
-@Title          RGX Core BVNC 36.51.54.102
+@Title          RGX Core BVNC 36.55.54.103
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
 @License        Dual MIT/GPLv2
 
@@ -39,19 +39,19 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#ifndef RGXCORE_KM_36_51_54_102_H
-#define RGXCORE_KM_36_51_54_102_H
+#ifndef RGXCORE_KM_36_55_54_103_H
+#define RGXCORE_KM_36_55_54_103_H
 
-/* Automatically generated file (09/12/2020 09:01:24): Do not edit manually */
-/* CS: @5849603 */
+/* Automatically generated file (04/10/2021 09:01:51): Do not edit manually */
+/* CS: @5908021 */
 
 /******************************************************************************
- * BVNC = 36.51.54.102
+ * BVNC = 36.55.54.103
  *****************************************************************************/
 #define RGX_BVNC_KM_B 36
-#define RGX_BVNC_KM_V 51
+#define RGX_BVNC_KM_V 55
 #define RGX_BVNC_KM_N 54
-#define RGX_BVNC_KM_C 102
+#define RGX_BVNC_KM_C 103
 
 /******************************************************************************
  * Errata
@@ -71,4 +71,4 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 
-#endif /* RGXCORE_KM_36_51_54_102_H */
+#endif /* RGXCORE_KM_36_55_54_103_H */
@@ -1,8 +1,6 @@
 /*************************************************************************/ /*!
-@File           rgxsignals.h
-@Title          RGX Signals routines
+@Title          RGX Core BVNC 36.56.104.183
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX Signals routines
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,31 +39,36 @@ 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(RGX_SIGNALS_H)
-#define RGX_SIGNALS_H
+#ifndef RGXCORE_KM_36_56_104_183_H
+#define RGXCORE_KM_36_56_104_183_H
 
-#include "img_types.h"
-#include "pvrsrv_error.h"
-#include "connection_server.h"
-#include "device.h"
+/* Automatically generated file (04/10/2021 09:01:51): Do not edit manually */
+/* CS: @5942195 */
 
-/*!
-*******************************************************************************
+/******************************************************************************
+ * BVNC = 36.56.104.183
+ *****************************************************************************/
+#define RGX_BVNC_KM_B 36
+#define RGX_BVNC_KM_V 56
+#define RGX_BVNC_KM_N 104
+#define RGX_BVNC_KM_C 183
 
- @Function     PVRSRVRGXNotifySignalUpdateKM
+/******************************************************************************
+ * Errata
+ *****************************************************************************/
 
- @Description   Server-side implementation of RGXNotifySignalUpdate
+#define FIX_HW_BRN_63553
 
- @Input hMemCtxPrivData - memory context private data
- @Input sDevSignalAddress - device virtual address of the updated signal
 
- @Return   PVRSRV_ERROR
 
-******************************************************************************/
+/******************************************************************************
+ * Enhancements
+ *****************************************************************************/
+#define HW_ERN_42290
+#define HW_ERN_42606
+#define HW_ERN_47025
+#define HW_ERN_57596
 
-PVRSRV_ERROR PVRSRVRGXNotifySignalUpdateKM(CONNECTION_DATA *psConnection,
-                                           PVRSRV_DEVICE_NODE *psDeviceNode,
-                                           IMG_HANDLE hMemCtxPrivData,
-                                           IMG_DEV_VIRTADDR sDevSignalAddress);
 
-#endif
+
+#endif /* RGXCORE_KM_36_56_104_183_H */
index 32d4975..846af82 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_4_31_4_55_H
 #define RGXCORE_KM_4_31_4_55_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @2919104 */
 
 /******************************************************************************
index 2a87116..c00a3e6 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_4_40_2_51_H
 #define RGXCORE_KM_4_40_2_51_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @3254374 */
 
 /******************************************************************************
index 18f714a..2e24ca5 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_4_43_6_62_H
 #define RGXCORE_KM_4_43_6_62_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @3253129 */
 
 /******************************************************************************
index 5e32eff..47b619d 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_4_45_2_58_H
 #define RGXCORE_KM_4_45_2_58_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:50): Do not edit manually */
 /* CS: @3547765 */
 
 /******************************************************************************
index f420d2c..7dd20c5 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_4_46_6_62_H
 #define RGXCORE_KM_4_46_6_62_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @4015666 */
 
 /******************************************************************************
index fb8e7f6..6a028bc 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_5_9_1_46_H
 #define RGXCORE_KM_5_9_1_46_H
 
-/* Automatically generated file (09/12/2020 09:01:23): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @2967148 */
 
 /******************************************************************************
index cb150c2..e7fb13f 100644 (file)
@@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef RGXCORE_KM_6_34_4_35_H
 #define RGXCORE_KM_6_34_4_35_H
 
-/* Automatically generated file (30/11/2020 09:01:20): Do not edit manually */
+/* Automatically generated file (04/10/2021 09:01:49): Do not edit manually */
 /* CS: @3533654 */
 
 /******************************************************************************
index 28cc350..0aa00be 100644 (file)
@@ -177,45 +177,96 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define        RGX_FEATURE_SLC_VIVT_POS                                        (37U)
 #define        RGX_FEATURE_SLC_VIVT_BIT_MASK                                   (IMG_UINT64_C(0x0000002000000000))
 
-#define        RGX_FEATURE_SYS_BUS_SECURE_RESET_POS                            (38U)
-#define        RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK                       (IMG_UINT64_C(0x0000004000000000))
+#define        RGX_FEATURE_SOC_TIMER_POS                                       (38U)
+#define        RGX_FEATURE_SOC_TIMER_BIT_MASK                                  (IMG_UINT64_C(0x0000004000000000))
 
-#define        RGX_FEATURE_TDM_PDS_CHECKSUM_POS                                (39U)
-#define        RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK                           (IMG_UINT64_C(0x0000008000000000))
+#define        RGX_FEATURE_SYS_BUS_SECURE_RESET_POS                            (39U)
+#define        RGX_FEATURE_SYS_BUS_SECURE_RESET_BIT_MASK                       (IMG_UINT64_C(0x0000008000000000))
 
-#define        RGX_FEATURE_TESSELLATION_POS                                    (40U)
-#define        RGX_FEATURE_TESSELLATION_BIT_MASK                               (IMG_UINT64_C(0x0000010000000000))
+#define        RGX_FEATURE_TDM_PDS_CHECKSUM_POS                                (40U)
+#define        RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK                           (IMG_UINT64_C(0x0000010000000000))
 
-#define        RGX_FEATURE_TILE_REGION_PROTECTION_POS                          (41U)
-#define        RGX_FEATURE_TILE_REGION_PROTECTION_BIT_MASK                     (IMG_UINT64_C(0x0000020000000000))
+#define        RGX_FEATURE_TESSELLATION_POS                                    (41U)
+#define        RGX_FEATURE_TESSELLATION_BIT_MASK                               (IMG_UINT64_C(0x0000020000000000))
 
-#define        RGX_FEATURE_TLA_POS                                             (42U)
-#define        RGX_FEATURE_TLA_BIT_MASK                                        (IMG_UINT64_C(0x0000040000000000))
+#define        RGX_FEATURE_TFBC_DELTA_CORRELATION_POS                          (42U)
+#define        RGX_FEATURE_TFBC_DELTA_CORRELATION_BIT_MASK                     (IMG_UINT64_C(0x0000040000000000))
 
-#define        RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_POS             (43U)
-#define        RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_BIT_MASK        (IMG_UINT64_C(0x0000080000000000))
+#define        RGX_FEATURE_TFBC_LOSSY_37_PERCENT_POS                           (43U)
+#define        RGX_FEATURE_TFBC_LOSSY_37_PERCENT_BIT_MASK                      (IMG_UINT64_C(0x0000080000000000))
 
-#define        RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_POS                         (44U)
-#define        RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_BIT_MASK                    (IMG_UINT64_C(0x0000100000000000))
+#define        RGX_FEATURE_TFBC_NATIVE_YUV10_POS                               (44U)
+#define        RGX_FEATURE_TFBC_NATIVE_YUV10_BIT_MASK                          (IMG_UINT64_C(0x0000100000000000))
 
-#define        RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_POS                      (45U)
-#define        RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK                 (IMG_UINT64_C(0x0000200000000000))
+#define        RGX_FEATURE_TILE_REGION_PROTECTION_POS                          (45U)
+#define        RGX_FEATURE_TILE_REGION_PROTECTION_BIT_MASK                     (IMG_UINT64_C(0x0000200000000000))
 
-#define        RGX_FEATURE_VDM_DRAWINDIRECT_POS                                (46U)
-#define        RGX_FEATURE_VDM_DRAWINDIRECT_BIT_MASK                           (IMG_UINT64_C(0x0000400000000000))
+#define        RGX_FEATURE_TLA_POS                                             (46U)
+#define        RGX_FEATURE_TLA_BIT_MASK                                        (IMG_UINT64_C(0x0000400000000000))
 
-#define        RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_POS                            (47U)
-#define        RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_BIT_MASK                       (IMG_UINT64_C(0x0000800000000000))
+#define        RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_POS             (47U)
+#define        RGX_FEATURE_TPU_CEM_DATAMASTER_GLOBAL_REGISTERS_BIT_MASK        (IMG_UINT64_C(0x0000800000000000))
 
-#define        RGX_FEATURE_WATCHDOG_TIMER_POS                                  (48U)
-#define        RGX_FEATURE_WATCHDOG_TIMER_BIT_MASK                             (IMG_UINT64_C(0x0001000000000000))
+#define        RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_POS                         (48U)
+#define        RGX_FEATURE_TPU_DM_GLOBAL_REGISTERS_BIT_MASK                    (IMG_UINT64_C(0x0001000000000000))
 
-#define        RGX_FEATURE_XE_MEMORY_HIERARCHY_POS                             (49U)
-#define        RGX_FEATURE_XE_MEMORY_HIERARCHY_BIT_MASK                        (IMG_UINT64_C(0x0002000000000000))
+#define        RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_POS                      (49U)
+#define        RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK                 (IMG_UINT64_C(0x0002000000000000))
 
-#define        RGX_FEATURE_XT_TOP_INFRASTRUCTURE_POS                           (50U)
-#define        RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK                      (IMG_UINT64_C(0x0004000000000000))
+#define        RGX_FEATURE_VDM_DRAWINDIRECT_POS                                (50U)
+#define        RGX_FEATURE_VDM_DRAWINDIRECT_BIT_MASK                           (IMG_UINT64_C(0x0004000000000000))
 
+#define        RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_POS                            (51U)
+#define        RGX_FEATURE_VDM_OBJECT_LEVEL_LLS_BIT_MASK                       (IMG_UINT64_C(0x0008000000000000))
+
+#define        RGX_FEATURE_WATCHDOG_TIMER_POS                                  (52U)
+#define        RGX_FEATURE_WATCHDOG_TIMER_BIT_MASK                             (IMG_UINT64_C(0x0010000000000000))
+
+#define        RGX_FEATURE_WORKGROUP_PROTECTION_POS                            (53U)
+#define        RGX_FEATURE_WORKGROUP_PROTECTION_BIT_MASK                       (IMG_UINT64_C(0x0020000000000000))
+
+#define        RGX_FEATURE_XE_MEMORY_HIERARCHY_POS                             (54U)
+#define        RGX_FEATURE_XE_MEMORY_HIERARCHY_BIT_MASK                        (IMG_UINT64_C(0x0040000000000000))
+
+#define        RGX_FEATURE_XT_TOP_INFRASTRUCTURE_POS                           (55U)
+#define        RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK                      (IMG_UINT64_C(0x0080000000000000))
+
+
+/******************************************************************************
+ * Defines for each feature with values used
+ * for handling the corresponding values
+ *****************************************************************************/
+
+#define        RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_MAX_VALUE_IDX     (2)
+#define        RGX_FEATURE_ECC_RAMS_MAX_VALUE_IDX      (2)
+#define        RGX_FEATURE_FBCDC_MAX_VALUE_IDX (4)
+#define        RGX_FEATURE_FBCDC_ALGORITHM_MAX_VALUE_IDX       (6)
+#define        RGX_FEATURE_FBCDC_ARCHITECTURE_MAX_VALUE_IDX    (4)
+#define        RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_MAX_VALUE_IDX   (2)
+#define        RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_MAX_VALUE_IDX     (2)
+#define        RGX_FEATURE_LAYOUT_MARS_MAX_VALUE_IDX   (3)
+#define        RGX_FEATURE_META_MAX_VALUE_IDX  (4)
+#define        RGX_FEATURE_META_COREMEM_BANKS_MAX_VALUE_IDX    (1)
+#define        RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX     (3)
+#define        RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX        (1)
+#define        RGX_FEATURE_NUM_CLUSTERS_MAX_VALUE_IDX  (5)
+#define        RGX_FEATURE_NUM_ISP_IPP_PIPES_MAX_VALUE_IDX     (9)
+#define        RGX_FEATURE_NUM_OSIDS_MAX_VALUE_IDX     (3)
+#define        RGX_FEATURE_NUM_RASTER_PIPES_MAX_VALUE_IDX      (3)
+#define        RGX_FEATURE_PHYS_BUS_WIDTH_MAX_VALUE_IDX        (4)
+#define        RGX_FEATURE_SCALABLE_TE_ARCH_MAX_VALUE_IDX      (1)
+#define        RGX_FEATURE_SCALABLE_VCE_MAX_VALUE_IDX  (1)
+#define        RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_MAX_VALUE_IDX       (3)
+#define        RGX_FEATURE_SLC_BANKS_MAX_VALUE_IDX     (4)
+#define        RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_MAX_VALUE_IDX      (2)
+#define        RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_MAX_VALUE_IDX (6)
+#define        RGX_FEATURE_TILE_SIZE_X_MAX_VALUE_IDX   (3)
+#define        RGX_FEATURE_TILE_SIZE_Y_MAX_VALUE_IDX   (3)
+#define        RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_MAX_VALUE_IDX    (2)
+#define        RGX_FEATURE_XE_ARCHITECTURE_MAX_VALUE_IDX       (2)
+#define        RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_MAX_VALUE_IDX   (2)
+#define        RGX_FEATURE_XPU_MAX_SLAVES_MAX_VALUE_IDX        (2)
+#define        RGX_FEATURE_XPU_REGISTER_BROADCAST_MAX_VALUE_IDX        (2)
 
 /******************************************************************************
  * Features with values indexes
@@ -227,6 +278,8 @@ typedef enum _RGX_FEATURE_WITH_VALUE_INDEX_ {
        RGX_FEATURE_FBCDC_IDX,
        RGX_FEATURE_FBCDC_ALGORITHM_IDX,
        RGX_FEATURE_FBCDC_ARCHITECTURE_IDX,
+       RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_IDX,
+       RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_IDX,
        RGX_FEATURE_LAYOUT_MARS_IDX,
        RGX_FEATURE_META_IDX,
        RGX_FEATURE_META_COREMEM_BANKS_IDX,
@@ -246,6 +299,7 @@ typedef enum _RGX_FEATURE_WITH_VALUE_INDEX_ {
        RGX_FEATURE_TILE_SIZE_X_IDX,
        RGX_FEATURE_TILE_SIZE_Y_IDX,
        RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_IDX,
+       RGX_FEATURE_XE_ARCHITECTURE_IDX,
        RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_IDX,
        RGX_FEATURE_XPU_MAX_SLAVES_IDX,
        RGX_FEATURE_XPU_REGISTER_BROADCAST_IDX,
index 8e9ea6d..4044507 100644 (file)
@@ -50,6 +50,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "img_types.h"
 #include "img_defs.h"
 #include "rgxdefs_km.h"
+#include "rgx_bvnc_defs_km.h"
 
 #ifndef RGXBVNC_C
 #error "This file should only be included from rgxbvnc.c"
@@ -61,90 +62,69 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 /******************************************************************************
- * Defines and arrays for each feature with values used
+ * Arrays for each feature with values used
  * for handling the corresponding values
  *****************************************************************************/
 
-#define        RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_MAX_VALUE_IDX     (3)
-static const IMG_UINT16 aui16_RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_values[RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, };
+static const IMG_UINT16 aui16_RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_values[RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, };
 
-#define        RGX_FEATURE_ECC_RAMS_MAX_VALUE_IDX      (2)
 static const IMG_UINT16 aui16_RGX_FEATURE_ECC_RAMS_values[RGX_FEATURE_ECC_RAMS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 2, };
 
-#define        RGX_FEATURE_FBCDC_MAX_VALUE_IDX (4)
 static const IMG_UINT16 aui16_RGX_FEATURE_FBCDC_values[RGX_FEATURE_FBCDC_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 3, 4, 50, };
 
-#define        RGX_FEATURE_FBCDC_ALGORITHM_MAX_VALUE_IDX       (6)
 static const IMG_UINT16 aui16_RGX_FEATURE_FBCDC_ALGORITHM_values[RGX_FEATURE_FBCDC_ALGORITHM_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 3, 4, 50, };
 
-#define        RGX_FEATURE_FBCDC_ARCHITECTURE_MAX_VALUE_IDX    (5)
-static const IMG_UINT16 aui16_RGX_FEATURE_FBCDC_ARCHITECTURE_values[RGX_FEATURE_FBCDC_ARCHITECTURE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 3, 7, };
+static const IMG_UINT16 aui16_RGX_FEATURE_FBCDC_ARCHITECTURE_values[RGX_FEATURE_FBCDC_ARCHITECTURE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 7, };
+
+static const IMG_UINT16 aui16_RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_values[RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, };
+
+static const IMG_UINT16 aui16_RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_values[RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, };
 
-#define        RGX_FEATURE_LAYOUT_MARS_MAX_VALUE_IDX   (3)
 static const IMG_UINT16 aui16_RGX_FEATURE_LAYOUT_MARS_values[RGX_FEATURE_LAYOUT_MARS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, 1, };
 
-#define        RGX_FEATURE_META_MAX_VALUE_IDX  (5)
-static const IMG_UINT16 aui16_RGX_FEATURE_META_values[RGX_FEATURE_META_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, LTP217, LTP218, MTP218, MTP219, };
+static const IMG_UINT16 aui16_RGX_FEATURE_META_values[RGX_FEATURE_META_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, LTP217, LTP218, MTP218, };
 
-#define        RGX_FEATURE_META_COREMEM_BANKS_MAX_VALUE_IDX    (2)
-static const IMG_UINT16 aui16_RGX_FEATURE_META_COREMEM_BANKS_values[RGX_FEATURE_META_COREMEM_BANKS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 8, };
+static const IMG_UINT16 aui16_RGX_FEATURE_META_COREMEM_BANKS_values[RGX_FEATURE_META_COREMEM_BANKS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, };
 
-#define        RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX     (4)
-static const IMG_UINT16 aui16_RGX_FEATURE_META_COREMEM_SIZE_values[RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, 32, 256, };
+static const IMG_UINT16 aui16_RGX_FEATURE_META_COREMEM_SIZE_values[RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, 32, };
 
-#define        RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX        (2)
-static const IMG_UINT16 aui16_RGX_FEATURE_META_DMA_CHANNEL_COUNT_values[RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 4, };
+static const IMG_UINT16 aui16_RGX_FEATURE_META_DMA_CHANNEL_COUNT_values[RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, };
 
-#define        RGX_FEATURE_NUM_CLUSTERS_MAX_VALUE_IDX  (5)
 static const IMG_UINT16 aui16_RGX_FEATURE_NUM_CLUSTERS_values[RGX_FEATURE_NUM_CLUSTERS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 4, 6, };
 
-#define        RGX_FEATURE_NUM_ISP_IPP_PIPES_MAX_VALUE_IDX     (9)
 static const IMG_UINT16 aui16_RGX_FEATURE_NUM_ISP_IPP_PIPES_values[RGX_FEATURE_NUM_ISP_IPP_PIPES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 3, 4, 6, 7, 8, 12, };
 
-#define        RGX_FEATURE_NUM_OSIDS_MAX_VALUE_IDX     (3)
 static const IMG_UINT16 aui16_RGX_FEATURE_NUM_OSIDS_values[RGX_FEATURE_NUM_OSIDS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 2, 8, };
 
-#define        RGX_FEATURE_NUM_RASTER_PIPES_MAX_VALUE_IDX      (4)
-static const IMG_UINT16 aui16_RGX_FEATURE_NUM_RASTER_PIPES_values[RGX_FEATURE_NUM_RASTER_PIPES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, 1, 2, };
+static const IMG_UINT16 aui16_RGX_FEATURE_NUM_RASTER_PIPES_values[RGX_FEATURE_NUM_RASTER_PIPES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, };
 
-#define        RGX_FEATURE_PHYS_BUS_WIDTH_MAX_VALUE_IDX        (4)
 static const IMG_UINT16 aui16_RGX_FEATURE_PHYS_BUS_WIDTH_values[RGX_FEATURE_PHYS_BUS_WIDTH_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 32, 36, 40, };
 
-#define        RGX_FEATURE_SCALABLE_TE_ARCH_MAX_VALUE_IDX      (2)
-static const IMG_UINT16 aui16_RGX_FEATURE_SCALABLE_TE_ARCH_values[RGX_FEATURE_SCALABLE_TE_ARCH_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, };
+static const IMG_UINT16 aui16_RGX_FEATURE_SCALABLE_TE_ARCH_values[RGX_FEATURE_SCALABLE_TE_ARCH_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, };
 
-#define        RGX_FEATURE_SCALABLE_VCE_MAX_VALUE_IDX  (2)
-static const IMG_UINT16 aui16_RGX_FEATURE_SCALABLE_VCE_values[RGX_FEATURE_SCALABLE_VCE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, };
+static const IMG_UINT16 aui16_RGX_FEATURE_SCALABLE_VCE_values[RGX_FEATURE_SCALABLE_VCE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, };
 
-#define        RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_MAX_VALUE_IDX       (3)
 static const IMG_UINT16 aui16_RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_values[RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, };
 
-#define        RGX_FEATURE_SLC_BANKS_MAX_VALUE_IDX     (4)
 static const IMG_UINT16 aui16_RGX_FEATURE_SLC_BANKS_values[RGX_FEATURE_SLC_BANKS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, 2, 4, };
 
-#define        RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_MAX_VALUE_IDX      (2)
 static const IMG_UINT16 aui16_RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_values[RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 512, };
 
-#define        RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_MAX_VALUE_IDX (7)
-static const IMG_UINT16 aui16_RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_values[RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 2, 8, 16, 64, 128, 512, };
+static const IMG_UINT16 aui16_RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_values[RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 2, 8, 16, 64, 128, };
 
-#define        RGX_FEATURE_TILE_SIZE_X_MAX_VALUE_IDX   (3)
 static const IMG_UINT16 aui16_RGX_FEATURE_TILE_SIZE_X_values[RGX_FEATURE_TILE_SIZE_X_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 16, 32, };
 
-#define        RGX_FEATURE_TILE_SIZE_Y_MAX_VALUE_IDX   (3)
 static const IMG_UINT16 aui16_RGX_FEATURE_TILE_SIZE_Y_values[RGX_FEATURE_TILE_SIZE_Y_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 16, 32, };
 
-#define        RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_MAX_VALUE_IDX    (2)
 static const IMG_UINT16 aui16_RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_values[RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 40, };
 
-#define        RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_MAX_VALUE_IDX   (2)
+static const IMG_UINT16 aui16_RGX_FEATURE_XE_ARCHITECTURE_values[RGX_FEATURE_XE_ARCHITECTURE_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, };
+
 static const IMG_UINT16 aui16_RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_values[RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 19, };
 
-#define        RGX_FEATURE_XPU_MAX_SLAVES_MAX_VALUE_IDX        (3)
-static const IMG_UINT16 aui16_RGX_FEATURE_XPU_MAX_SLAVES_values[RGX_FEATURE_XPU_MAX_SLAVES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 2, 3, };
+static const IMG_UINT16 aui16_RGX_FEATURE_XPU_MAX_SLAVES_values[RGX_FEATURE_XPU_MAX_SLAVES_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 3, };
 
-#define        RGX_FEATURE_XPU_REGISTER_BROADCAST_MAX_VALUE_IDX        (3)
-static const IMG_UINT16 aui16_RGX_FEATURE_XPU_REGISTER_BROADCAST_values[RGX_FEATURE_XPU_REGISTER_BROADCAST_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 0, 1, };
+static const IMG_UINT16 aui16_RGX_FEATURE_XPU_REGISTER_BROADCAST_values[RGX_FEATURE_XPU_REGISTER_BROADCAST_MAX_VALUE_IDX] = {(IMG_UINT16)RGX_FEATURE_VALUE_DISABLED, 1, };
 
 
 /******************************************************************************
@@ -159,6 +139,8 @@ static const IMG_UINT16 * const gaFeaturesValues[RGX_FEATURE_WITH_VALUES_MAX_IDX
        aui16_RGX_FEATURE_FBCDC_values,
        aui16_RGX_FEATURE_FBCDC_ALGORITHM_values,
        aui16_RGX_FEATURE_FBCDC_ARCHITECTURE_values,
+       aui16_RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_values,
+       aui16_RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_values,
        aui16_RGX_FEATURE_LAYOUT_MARS_values,
        aui16_RGX_FEATURE_META_values,
        aui16_RGX_FEATURE_META_COREMEM_BANKS_values,
@@ -178,6 +160,7 @@ static const IMG_UINT16 * const gaFeaturesValues[RGX_FEATURE_WITH_VALUES_MAX_IDX
        aui16_RGX_FEATURE_TILE_SIZE_X_values,
        aui16_RGX_FEATURE_TILE_SIZE_Y_values,
        aui16_RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_values,
+       aui16_RGX_FEATURE_XE_ARCHITECTURE_values,
        aui16_RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_values,
        aui16_RGX_FEATURE_XPU_MAX_SLAVES_values,
        aui16_RGX_FEATURE_XPU_REGISTER_BROADCAST_values,
@@ -196,6 +179,8 @@ static const IMG_UINT16 gaFeaturesValuesMaxIndexes[] = {
        RGX_FEATURE_FBCDC_MAX_VALUE_IDX,
        RGX_FEATURE_FBCDC_ALGORITHM_MAX_VALUE_IDX,
        RGX_FEATURE_FBCDC_ARCHITECTURE_MAX_VALUE_IDX,
+       RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_MAX_VALUE_IDX,
+       RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_MAX_VALUE_IDX,
        RGX_FEATURE_LAYOUT_MARS_MAX_VALUE_IDX,
        RGX_FEATURE_META_MAX_VALUE_IDX,
        RGX_FEATURE_META_COREMEM_BANKS_MAX_VALUE_IDX,
@@ -215,6 +200,7 @@ static const IMG_UINT16 gaFeaturesValuesMaxIndexes[] = {
        RGX_FEATURE_TILE_SIZE_X_MAX_VALUE_IDX,
        RGX_FEATURE_TILE_SIZE_Y_MAX_VALUE_IDX,
        RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_MAX_VALUE_IDX,
+       RGX_FEATURE_XE_ARCHITECTURE_MAX_VALUE_IDX,
        RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_MAX_VALUE_IDX,
        RGX_FEATURE_XPU_MAX_SLAVES_MAX_VALUE_IDX,
        RGX_FEATURE_XPU_REGISTER_BROADCAST_MAX_VALUE_IDX,
@@ -231,25 +217,28 @@ static const IMG_UINT16 aui16FeaturesWithValuesBitPositions[] = {
        (4U), /* RGX_FEATURE_FBCDC_POS */
        (7U), /* RGX_FEATURE_FBCDC_ALGORITHM_POS */
        (10U), /* RGX_FEATURE_FBCDC_ARCHITECTURE_POS */
-       (13U), /* RGX_FEATURE_LAYOUT_MARS_POS */
-       (15U), /* RGX_FEATURE_META_POS */
-       (18U), /* RGX_FEATURE_META_COREMEM_BANKS_POS */
-       (20U), /* RGX_FEATURE_META_COREMEM_SIZE_POS */
-       (23U), /* RGX_FEATURE_META_DMA_CHANNEL_COUNT_POS */
-       (25U), /* RGX_FEATURE_NUM_CLUSTERS_POS */
-       (28U), /* RGX_FEATURE_NUM_ISP_IPP_PIPES_POS */
-       (32U), /* RGX_FEATURE_NUM_OSIDS_POS */
-       (34U), /* RGX_FEATURE_NUM_RASTER_PIPES_POS */
+       (13U), /* RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_POS */
+       (15U), /* RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_POS */
+       (17U), /* RGX_FEATURE_LAYOUT_MARS_POS */
+       (19U), /* RGX_FEATURE_META_POS */
+       (22U), /* RGX_FEATURE_META_COREMEM_BANKS_POS */
+       (23U), /* RGX_FEATURE_META_COREMEM_SIZE_POS */
+       (25U), /* RGX_FEATURE_META_DMA_CHANNEL_COUNT_POS */
+       (26U), /* RGX_FEATURE_NUM_CLUSTERS_POS */
+       (29U), /* RGX_FEATURE_NUM_ISP_IPP_PIPES_POS */
+       (33U), /* RGX_FEATURE_NUM_OSIDS_POS */
+       (35U), /* RGX_FEATURE_NUM_RASTER_PIPES_POS */
        (37U), /* RGX_FEATURE_PHYS_BUS_WIDTH_POS */
        (40U), /* RGX_FEATURE_SCALABLE_TE_ARCH_POS */
-       (42U), /* RGX_FEATURE_SCALABLE_VCE_POS */
-       (44U), /* RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_POS */
-       (46U), /* RGX_FEATURE_SLC_BANKS_POS */
-       (49U), /* RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_POS */
-       (51U), /* RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_POS */
-       (54U), /* RGX_FEATURE_TILE_SIZE_X_POS */
-       (56U), /* RGX_FEATURE_TILE_SIZE_Y_POS */
-       (58U), /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_POS */
+       (41U), /* RGX_FEATURE_SCALABLE_VCE_POS */
+       (42U), /* RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_POS */
+       (44U), /* RGX_FEATURE_SLC_BANKS_POS */
+       (47U), /* RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_POS */
+       (49U), /* RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_POS */
+       (52U), /* RGX_FEATURE_TILE_SIZE_X_POS */
+       (54U), /* RGX_FEATURE_TILE_SIZE_Y_POS */
+       (56U), /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_POS */
+       (58U), /* RGX_FEATURE_XE_ARCHITECTURE_POS */
        (60U), /* RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_POS */
        (62U), /* RGX_FEATURE_XPU_MAX_SLAVES_POS */
        (64U), /* RGX_FEATURE_XPU_REGISTER_BROADCAST_POS */
@@ -266,25 +255,28 @@ static const IMG_UINT64 aui64FeaturesWithValuesBitMasks[] = {
        (IMG_UINT64_C(0x0000000000000070)), /* RGX_FEATURE_FBCDC_BIT_MASK */
        (IMG_UINT64_C(0x0000000000000380)), /* RGX_FEATURE_FBCDC_ALGORITHM_BIT_MASK */
        (IMG_UINT64_C(0x0000000000001C00)), /* RGX_FEATURE_FBCDC_ARCHITECTURE_BIT_MASK */
-       (IMG_UINT64_C(0x0000000000006000)), /* RGX_FEATURE_LAYOUT_MARS_BIT_MASK */
-       (IMG_UINT64_C(0x0000000000038000)), /* RGX_FEATURE_META_BIT_MASK */
-       (IMG_UINT64_C(0x00000000000C0000)), /* RGX_FEATURE_META_COREMEM_BANKS_BIT_MASK */
-       (IMG_UINT64_C(0x0000000000700000)), /* RGX_FEATURE_META_COREMEM_SIZE_BIT_MASK */
-       (IMG_UINT64_C(0x0000000001800000)), /* RGX_FEATURE_META_DMA_CHANNEL_COUNT_BIT_MASK */
-       (IMG_UINT64_C(0x000000000E000000)), /* RGX_FEATURE_NUM_CLUSTERS_BIT_MASK */
-       (IMG_UINT64_C(0x00000000F0000000)), /* RGX_FEATURE_NUM_ISP_IPP_PIPES_BIT_MASK */
-       (IMG_UINT64_C(0x0000000300000000)), /* RGX_FEATURE_NUM_OSIDS_BIT_MASK */
-       (IMG_UINT64_C(0x0000001C00000000)), /* RGX_FEATURE_NUM_RASTER_PIPES_BIT_MASK */
+       (IMG_UINT64_C(0x0000000000006000)), /* RGX_FEATURE_FBC_MAX_DEFAULT_DESCRIPTORS_BIT_MASK */
+       (IMG_UINT64_C(0x0000000000018000)), /* RGX_FEATURE_FBC_MAX_LARGE_DESCRIPTORS_BIT_MASK */
+       (IMG_UINT64_C(0x0000000000060000)), /* RGX_FEATURE_LAYOUT_MARS_BIT_MASK */
+       (IMG_UINT64_C(0x0000000000380000)), /* RGX_FEATURE_META_BIT_MASK */
+       (IMG_UINT64_C(0x0000000000400000)), /* RGX_FEATURE_META_COREMEM_BANKS_BIT_MASK */
+       (IMG_UINT64_C(0x0000000001800000)), /* RGX_FEATURE_META_COREMEM_SIZE_BIT_MASK */
+       (IMG_UINT64_C(0x0000000002000000)), /* RGX_FEATURE_META_DMA_CHANNEL_COUNT_BIT_MASK */
+       (IMG_UINT64_C(0x000000001C000000)), /* RGX_FEATURE_NUM_CLUSTERS_BIT_MASK */
+       (IMG_UINT64_C(0x00000001E0000000)), /* RGX_FEATURE_NUM_ISP_IPP_PIPES_BIT_MASK */
+       (IMG_UINT64_C(0x0000000600000000)), /* RGX_FEATURE_NUM_OSIDS_BIT_MASK */
+       (IMG_UINT64_C(0x0000001800000000)), /* RGX_FEATURE_NUM_RASTER_PIPES_BIT_MASK */
        (IMG_UINT64_C(0x000000E000000000)), /* RGX_FEATURE_PHYS_BUS_WIDTH_BIT_MASK */
-       (IMG_UINT64_C(0x0000030000000000)), /* RGX_FEATURE_SCALABLE_TE_ARCH_BIT_MASK */
-       (IMG_UINT64_C(0x00000C0000000000)), /* RGX_FEATURE_SCALABLE_VCE_BIT_MASK */
-       (IMG_UINT64_C(0x0000300000000000)), /* RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_BIT_MASK */
-       (IMG_UINT64_C(0x0001C00000000000)), /* RGX_FEATURE_SLC_BANKS_BIT_MASK */
-       (IMG_UINT64_C(0x0006000000000000)), /* RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_BIT_MASK */
-       (IMG_UINT64_C(0x0038000000000000)), /* RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_BIT_MASK */
-       (IMG_UINT64_C(0x00C0000000000000)), /* RGX_FEATURE_TILE_SIZE_X_BIT_MASK */
-       (IMG_UINT64_C(0x0300000000000000)), /* RGX_FEATURE_TILE_SIZE_Y_BIT_MASK */
-       (IMG_UINT64_C(0x0C00000000000000)), /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_BIT_MASK */
+       (IMG_UINT64_C(0x0000010000000000)), /* RGX_FEATURE_SCALABLE_TE_ARCH_BIT_MASK */
+       (IMG_UINT64_C(0x0000020000000000)), /* RGX_FEATURE_SCALABLE_VCE_BIT_MASK */
+       (IMG_UINT64_C(0x00000C0000000000)), /* RGX_FEATURE_SIMPLE_PARAMETER_FORMAT_VERSION_BIT_MASK */
+       (IMG_UINT64_C(0x0000700000000000)), /* RGX_FEATURE_SLC_BANKS_BIT_MASK */
+       (IMG_UINT64_C(0x0001800000000000)), /* RGX_FEATURE_SLC_CACHE_LINE_SIZE_BITS_BIT_MASK */
+       (IMG_UINT64_C(0x000E000000000000)), /* RGX_FEATURE_SLC_SIZE_IN_KILOBYTES_BIT_MASK */
+       (IMG_UINT64_C(0x0030000000000000)), /* RGX_FEATURE_TILE_SIZE_X_BIT_MASK */
+       (IMG_UINT64_C(0x00C0000000000000)), /* RGX_FEATURE_TILE_SIZE_Y_BIT_MASK */
+       (IMG_UINT64_C(0x0300000000000000)), /* RGX_FEATURE_VIRTUAL_ADDRESS_SPACE_BITS_BIT_MASK */
+       (IMG_UINT64_C(0x0C00000000000000)), /* RGX_FEATURE_XE_ARCHITECTURE_BIT_MASK */
        (IMG_UINT64_C(0x3000000000000000)), /* RGX_FEATURE_XPU_MAX_REGBANKS_ADDR_WIDTH_BIT_MASK */
        (IMG_UINT64_C(0xC000000000000000)), /* RGX_FEATURE_XPU_MAX_SLAVES_BIT_MASK */
        (IMG_UINT64_C(0x0000000000000003)), /* RGX_FEATURE_XPU_REGISTER_BROADCAST_BIT_MASK */
@@ -298,36 +290,38 @@ static const IMG_UINT64 aui64FeaturesWithValuesBitMasks[] = {
 
 static const IMG_UINT64 gaFeatures[][4]=
 {
-       { IMG_UINT64_C(0x000100000002001e), IMG_UINT64_C(0x0000040000402025), IMG_UINT64_C(0x06aa00683411a481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.2.30 */
-       { IMG_UINT64_C(0x0001000000040005), IMG_UINT64_C(0x0000040000402024), IMG_UINT64_C(0x06aa00683611a481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.4.5 */
-       { IMG_UINT64_C(0x0001000000040013), IMG_UINT64_C(0x0000040000402025), IMG_UINT64_C(0x06aa00683611a481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.4.19 */
-       { IMG_UINT64_C(0x0004000000020033), IMG_UINT64_C(0x00042c0000c0222f), IMG_UINT64_C(0x06aa006874212901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.2.51 */
-       { IMG_UINT64_C(0x000400000002003a), IMG_UINT64_C(0x00042c0000c0322f), IMG_UINT64_C(0x06aa006a74212901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.2.58 */
-       { IMG_UINT64_C(0x0004000000040037), IMG_UINT64_C(0x00042c0000c0222e), IMG_UINT64_C(0x06aa006876212901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.4.55 */
-       { IMG_UINT64_C(0x000400000006003e), IMG_UINT64_C(0x00042c0000c0322f), IMG_UINT64_C(0x06aac06e78212901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.6.62 */
-       { IMG_UINT64_C(0x000500000001002e), IMG_UINT64_C(0x0000000004402205), IMG_UINT64_C(0x069a40681210a501), IMG_UINT64_C(0x0000000000000000) },     /* 5.0.1.46 */
-       { IMG_UINT64_C(0x0006000000040023), IMG_UINT64_C(0x00042c0000c0222f), IMG_UINT64_C(0x06aa006876212901), IMG_UINT64_C(0x0000000000000000) },     /* 6.0.4.35 */
-       { IMG_UINT64_C(0x000f000000010040), IMG_UINT64_C(0x0000000004403205), IMG_UINT64_C(0x06a2406a2210a501), IMG_UINT64_C(0x0000000000000000) },     /* 15.0.1.64 */
-       { IMG_UINT64_C(0x0016000000150010), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0552502a22002001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.21.16 */
-       { IMG_UINT64_C(0x0016000000360019), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562502a32002001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.25 */
-       { IMG_UINT64_C(0x001600000036001e), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562502a42002001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.30 */
-       { IMG_UINT64_C(0x0016000000360026), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562504a42002001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.38 */
-       { IMG_UINT64_C(0x001600000036014a), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562502a42002591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.330 */
-       { IMG_UINT64_C(0x0016000000680012), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562504a62002001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.104.18 */
-       { IMG_UINT64_C(0x00160000006800da), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562504a62002591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.104.218 */
-       { IMG_UINT64_C(0x0016000000d0013e), IMG_UINT64_C(0x00000045844b3025), IMG_UINT64_C(0x0562904e84002591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.208.318 */
-       { IMG_UINT64_C(0x00180000003600cc), IMG_UINT64_C(0x000200c2844f7425), IMG_UINT64_C(0x0562604a42002591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.54.204 */
-       { IMG_UINT64_C(0x00180000006801f8), IMG_UINT64_C(0x000200c2844f7425), IMG_UINT64_C(0x0562604a52002591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.104.504 */
-       { IMG_UINT64_C(0x0018000000d001f8), IMG_UINT64_C(0x000200c2844f7425), IMG_UINT64_C(0x056aa04e84002591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.208.504 */
-       { IMG_UINT64_C(0x0018000000d001f9), IMG_UINT64_C(0x000200c2844f7425), IMG_UINT64_C(0x056aa04e84002591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.208.505 */
-       { IMG_UINT64_C(0x001d0000003400ca), IMG_UINT64_C(0x000218c2844f74a5), IMG_UINT64_C(0x055a604a22002621), IMG_UINT64_C(0x0000000000000000) },     /* 29.0.52.202 */
-       { IMG_UINT64_C(0x001d0000006c00d0), IMG_UINT64_C(0x000218c2844f74a5), IMG_UINT64_C(0x056aa04e74002621), IMG_UINT64_C(0x0000000000000000) },     /* 29.0.108.208 */
-       { IMG_UINT64_C(0x00210000000b0003), IMG_UINT64_C(0x00020052844b5085), IMG_UINT64_C(0x054a604912002001), IMG_UINT64_C(0x0000000000000000) },     /* 33.0.11.3 */
-       { IMG_UINT64_C(0x0021000000160001), IMG_UINT64_C(0x00021842854b70a5), IMG_UINT64_C(0x055a604a22002001), IMG_UINT64_C(0x0000000000000000) },     /* 33.0.22.1 */
-       { IMG_UINT64_C(0x0024000000360066), IMG_UINT64_C(0x00021852844b38a5), IMG_UINT64_C(0x055a604a420032b1), IMG_UINT64_C(0x0000000000000000) },     /* 36.0.54.102 */
-       { IMG_UINT64_C(0x00240000003600b6), IMG_UINT64_C(0x00021852844b78a5), IMG_UINT64_C(0x955a604a420052b1), IMG_UINT64_C(0x0000000000000002) },     /* 36.0.54.182 */
-       { IMG_UINT64_C(0x00240000006800b6), IMG_UINT64_C(0x00021852844b78a5), IMG_UINT64_C(0x955a604a520052b1), IMG_UINT64_C(0x0000000000000002) },     /* 36.0.104.182 */
-       { IMG_UINT64_C(0x002400000068031c), IMG_UINT64_C(0x00031a52864a78a5), IMG_UINT64_C(0x955a604a520052b5), IMG_UINT64_C(0x0000000000000002) },     /* 36.0.104.796 */
+       { IMG_UINT64_C(0x000100000002001e), IMG_UINT64_C(0x0000400000402025), IMG_UINT64_C(0x01aa8068689aa481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.2.30 */
+       { IMG_UINT64_C(0x0001000000040005), IMG_UINT64_C(0x0000400000402024), IMG_UINT64_C(0x01aa80686c9aa481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.4.5 */
+       { IMG_UINT64_C(0x0001000000040013), IMG_UINT64_C(0x0000400000402025), IMG_UINT64_C(0x01aa80686c9aa481), IMG_UINT64_C(0x0000000000000000) },     /* 1.0.4.19 */
+       { IMG_UINT64_C(0x0004000000020033), IMG_UINT64_C(0x0082c04000c0222f), IMG_UINT64_C(0x01aa8068e912a901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.2.51 */
+       { IMG_UINT64_C(0x000400000002003a), IMG_UINT64_C(0x0082c04000c0322f), IMG_UINT64_C(0x01aa806ce912a901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.2.58 */
+       { IMG_UINT64_C(0x0004000000040037), IMG_UINT64_C(0x0082c04000c0222e), IMG_UINT64_C(0x01aa8068ed12a901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.4.55 */
+       { IMG_UINT64_C(0x000400000006003e), IMG_UINT64_C(0x0082c04000c0322f), IMG_UINT64_C(0x01aab074f112a901), IMG_UINT64_C(0x0000000000000000) },     /* 4.0.6.62 */
+       { IMG_UINT64_C(0x000500000001002e), IMG_UINT64_C(0x0000004004402205), IMG_UINT64_C(0x05a69068248aa501), IMG_UINT64_C(0x0000000000000000) },     /* 5.0.1.46 */
+       { IMG_UINT64_C(0x0006000000040023), IMG_UINT64_C(0x0082c04000c0222f), IMG_UINT64_C(0x01aa8068ed12a901), IMG_UINT64_C(0x0000000000000000) },     /* 6.0.4.35 */
+       { IMG_UINT64_C(0x000f000000010040), IMG_UINT64_C(0x0000004004403205), IMG_UINT64_C(0x05a8906c448aa501), IMG_UINT64_C(0x0000000000000000) },     /* 15.0.1.64 */
+       { IMG_UINT64_C(0x0016000000150010), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0554942c44020001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.21.16 */
+       { IMG_UINT64_C(0x0016000000360019), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558942c64020001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.25 */
+       { IMG_UINT64_C(0x001600000036001e), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558942c84020001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.30 */
+       { IMG_UINT64_C(0x0016000000360026), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558944c84020001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.38 */
+       { IMG_UINT64_C(0x001600000036014a), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558942c8402a591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.54.330 */
+       { IMG_UINT64_C(0x0016000000680012), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558944cc4020001), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.104.18 */
+       { IMG_UINT64_C(0x00160000006800da), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558944cc402a591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.104.218 */
+       { IMG_UINT64_C(0x0016000000d0013e), IMG_UINT64_C(0x000000c5844b3025), IMG_UINT64_C(0x0558a4550802a591), IMG_UINT64_C(0x0000000000000000) },     /* 22.0.208.318 */
+       { IMG_UINT64_C(0x00180000003600cc), IMG_UINT64_C(0x004001c2844f7425), IMG_UINT64_C(0x0558984c8402a591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.54.204 */
+       { IMG_UINT64_C(0x00180000006801f8), IMG_UINT64_C(0x004001c2844f7425), IMG_UINT64_C(0x0558984ca402a591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.104.504 */
+       { IMG_UINT64_C(0x0018000000d001f8), IMG_UINT64_C(0x004001c2844f7425), IMG_UINT64_C(0x055aa8550802a591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.208.504 */
+       { IMG_UINT64_C(0x0018000000d001f9), IMG_UINT64_C(0x004001c2844f7425), IMG_UINT64_C(0x055aa8550802a591), IMG_UINT64_C(0x0000000000000000) },     /* 24.0.208.505 */
+       { IMG_UINT64_C(0x001d0000003400ca), IMG_UINT64_C(0x004181c2844f74a5), IMG_UINT64_C(0x0556984c4402a621), IMG_UINT64_C(0x0000000000000000) },     /* 29.0.52.202 */
+       { IMG_UINT64_C(0x001d0000006c00d0), IMG_UINT64_C(0x004181c2844f74a5), IMG_UINT64_C(0x055aa854e802a621), IMG_UINT64_C(0x0000000000000000) },     /* 29.0.108.208 */
+       { IMG_UINT64_C(0x00210000000b0003), IMG_UINT64_C(0x00400092844b5085), IMG_UINT64_C(0x0552984a24020001), IMG_UINT64_C(0x0000000000000000) },     /* 33.0.11.3 */
+       { IMG_UINT64_C(0x0021000000160001), IMG_UINT64_C(0x004180c2854b70a5), IMG_UINT64_C(0x0556984c44020001), IMG_UINT64_C(0x0000000000000000) },     /* 33.0.22.1 */
+       { IMG_UINT64_C(0x0024000000360067), IMG_UINT64_C(0x004180d2844b38a5), IMG_UINT64_C(0x0556984c8402aeb1), IMG_UINT64_C(0x0000000000000000) },     /* 36.0.54.103 */
+       { IMG_UINT64_C(0x00240000003600b6), IMG_UINT64_C(0x004180d2844b78a5), IMG_UINT64_C(0x5556984c8404aeb1), IMG_UINT64_C(0x0000000000000001) },     /* 36.0.54.182 */
+       { IMG_UINT64_C(0x00240000003600b7), IMG_UINT64_C(0x004180d2844b78a5), IMG_UINT64_C(0x5556984c8404aeb1), IMG_UINT64_C(0x0000000000000001) },     /* 36.0.54.183 */
+       { IMG_UINT64_C(0x00240000006800b6), IMG_UINT64_C(0x004180d2844b78a5), IMG_UINT64_C(0x5556984ca404aeb1), IMG_UINT64_C(0x0000000000000001) },     /* 36.0.104.182 */
+       { IMG_UINT64_C(0x00240000006800b7), IMG_UINT64_C(0x004180d2844b78a5), IMG_UINT64_C(0x5556984ca404aeb1), IMG_UINT64_C(0x0000000000000001) },     /* 36.0.104.183 */
+       { IMG_UINT64_C(0x002400000068031c), IMG_UINT64_C(0x0071a0d2864a78a5), IMG_UINT64_C(0x5556984ca404aeb5), IMG_UINT64_C(0x0000000000000001) },     /* 36.0.104.796 */
 };
 
 /******************************************************************************
@@ -367,16 +361,17 @@ static const IMG_UINT64 gaErnsBrns[][2]=
        { IMG_UINT64_C(0x001d0013003400ca), IMG_UINT64_C(0x000000000006212a) }, /* 29.19.52.202 */
        { IMG_UINT64_C(0x0021000800160001), IMG_UINT64_C(0x000000000000212a) }, /* 33.8.22.1 */
        { IMG_UINT64_C(0x0021000f000b0003), IMG_UINT64_C(0x000000000000212a) }, /* 33.15.11.3 */
-       { IMG_UINT64_C(0x0024001e003600b6), IMG_UINT64_C(0x000000000000212a) }, /* 36.30.54.182 */
        { IMG_UINT64_C(0x00240032003600b6), IMG_UINT64_C(0x000000000000212a) }, /* 36.50.54.182 */
-       { IMG_UINT64_C(0x0024003300360066), IMG_UINT64_C(0x000000000000212a) }, /* 36.51.54.102 */
        { IMG_UINT64_C(0x00240034006800b6), IMG_UINT64_C(0x000000000000212a) }, /* 36.52.104.182 */
        { IMG_UINT64_C(0x002400350068031c), IMG_UINT64_C(0x000000000000012a) }, /* 36.53.104.796 */
+       { IMG_UINT64_C(0x00240036003600b7), IMG_UINT64_C(0x000000000000212a) }, /* 36.54.54.183 */
+       { IMG_UINT64_C(0x0024003700360067), IMG_UINT64_C(0x000000000000212a) }, /* 36.55.54.103 */
+       { IMG_UINT64_C(0x00240038006800b7), IMG_UINT64_C(0x000000000000212a) }, /* 36.56.104.183 */
 };
 
 #if defined(DEBUG)
 
-#define        FEATURE_NO_VALUES_NAMES_MAX_IDX (51)
+#define        FEATURE_NO_VALUES_NAMES_MAX_IDX (56)
 
 static const IMG_CHAR * const gaszFeaturesNoValuesNames[FEATURE_NO_VALUES_NAMES_MAX_IDX] =
 {
@@ -418,9 +413,13 @@ static const IMG_CHAR * const gaszFeaturesNoValuesNames[FEATURE_NO_VALUES_NAMES_
        "SLC_HYBRID_CACHELINE_64_128",
        "SLC_SIZE_CONFIGURABLE",
        "SLC_VIVT",
+       "SOC_TIMER",
        "SYS_BUS_SECURE_RESET",
        "TDM_PDS_CHECKSUM",
        "TESSELLATION",
+       "TFBC_DELTA_CORRELATION",
+       "TFBC_LOSSY_37_PERCENT",
+       "TFBC_NATIVE_YUV10",
        "TILE_REGION_PROTECTION",
        "TLA",
        "TPU_CEM_DATAMASTER_GLOBAL_REGISTERS",
@@ -429,6 +428,7 @@ static const IMG_CHAR * const gaszFeaturesNoValuesNames[FEATURE_NO_VALUES_NAMES_
        "VDM_DRAWINDIRECT",
        "VDM_OBJECT_LEVEL_LLS",
        "WATCHDOG_TIMER",
+       "WORKGROUP_PROTECTION",
        "XE_MEMORY_HIERARCHY",
        "XT_TOP_INFRASTRUCTURE",
 };
index 6cfff76..2464d91 100644 (file)
@@ -70,6 +70,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 /*
+    Register RGX_CR_USC_INDIRECT
+*/
+#define RGX_CR_USC_INDIRECT                               (0x8000U)
+#define RGX_CR_USC_INDIRECT_MASKFULL                      (IMG_UINT64_C(0x000000000000000F))
+#define RGX_CR_USC_INDIRECT_ADDRESS_SHIFT                 (0U)
+#define RGX_CR_USC_INDIRECT_ADDRESS_CLRMSK                (0xFFFFFFF0U)
+
+
+/*
     Register RGX_CR_PBE_INDIRECT
 */
 #define RGX_CR_PBE_INDIRECT                               (0x83E0U)
@@ -493,6 +502,24 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 /*
+    Register RGX_CR_SOC_TIMER_GRAY
+*/
+#define RGX_CR_SOC_TIMER_GRAY                             (0x00E0U)
+#define RGX_CR_SOC_TIMER_GRAY_MASKFULL                    (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+#define RGX_CR_SOC_TIMER_GRAY_VALUE_SHIFT                 (0U)
+#define RGX_CR_SOC_TIMER_GRAY_VALUE_CLRMSK                (IMG_UINT64_C(0x0000000000000000))
+
+
+/*
+    Register RGX_CR_SOC_TIMER_BINARY
+*/
+#define RGX_CR_SOC_TIMER_BINARY                           (0x00E8U)
+#define RGX_CR_SOC_TIMER_BINARY_MASKFULL                  (IMG_UINT64_C(0xFFFFFFFFFFFFFFFF))
+#define RGX_CR_SOC_TIMER_BINARY_VALUE_SHIFT               (0U)
+#define RGX_CR_SOC_TIMER_BINARY_VALUE_CLRMSK              (IMG_UINT64_C(0x0000000000000000))
+
+
+/*
     Register RGX_CR_CLK_XTPLUS_CTRL
 */
 #define RGX_CR_CLK_XTPLUS_CTRL                            (0x0080U)
@@ -3530,6 +3557,31 @@ Fast scale render */
 
 
 /*
+    Register RGX_CR_TFBC_COMPRESSION_CONTROL
+*/
+#define RGX_CR_TFBC_COMPRESSION_CONTROL                   (0x14A0U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_MASKFULL          (IMG_UINT64_C(0x00000000000000FF))
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_YUV10_OVERRIDE_SHIFT (7U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_YUV10_OVERRIDE_CLRMSK (0xFFFFFF7FU)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_YUV10_OVERRIDE_EN (0x00000080U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_QUALITY_SHIFT_SHIFT (4U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_QUALITY_SHIFT_CLRMSK (0xFFFFFF8FU)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_QUALITY_ENABLE_SHIFT (3U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_QUALITY_ENABLE_CLRMSK (0xFFFFFFF7U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_QUALITY_ENABLE_EN (0x00000008U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_SHIFT      (1U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_CLRMSK     (0xFFFFFFF9U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_DEFAULT    (0x00000000U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_TFBC_DELTA_STANDARD_AND_CORRELATION (0x00000002U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_TFBC_DELTA_STANDARD (0x00000004U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_RESERVED   (0x00000006U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_SHIFT (0U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_CLRMSK (0xFFFFFFFEU)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_GROUP_0 (0x00000000U)
+#define RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_GROUP_1 (0x00000001U)
+
+
+/*
     Register RGX_CR_MCU_FENCE
 */
 #define RGX_CR_MCU_FENCE                                  (0x1740U)
@@ -5438,6 +5490,25 @@ Fast scale render */
 
 
 /*
+    Register RGX_CR_USC_TIMER
+*/
+#define RGX_CR_USC_TIMER                                  (0x46C8U)
+#define RGX_CR_USC_TIMER_MASKFULL                         (IMG_UINT64_C(0x00000000FFFFFFFF))
+#define RGX_CR_USC_TIMER_CNT_SHIFT                        (0U)
+#define RGX_CR_USC_TIMER_CNT_CLRMSK                       (0x00000000U)
+
+
+/*
+    Register RGX_CR_USC_TIMER_CNT
+*/
+#define RGX_CR_USC_TIMER_CNT                              (0x46D0U)
+#define RGX_CR_USC_TIMER_CNT_MASKFULL                     (IMG_UINT64_C(0x0000000000000001))
+#define RGX_CR_USC_TIMER_CNT_RESET_SHIFT                  (0U)
+#define RGX_CR_USC_TIMER_CNT_RESET_CLRMSK                 (0xFFFFFFFEU)
+#define RGX_CR_USC_TIMER_CNT_RESET_EN                     (0x00000001U)
+
+
+/*
     Register RGX_CR_USC_UVS0_CHECKSUM
 */
 #define RGX_CR_USC_UVS0_CHECKSUM                          (0x5000U)
index 59b60f6..64f4b36 100644 (file)
@@ -81,7 +81,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_BVNC_KM_V_ST       RGX_BVNC_KM_ST(RGX_BVNC_KM_V)
 
 /* Maximum string size is [bb.vvvp.nnnn.cccc\0], includes null char */
-#define RGX_BVNC_STR_SIZE_MAX (2+1+4+1+4+1+4+1)
+#define RGX_BVNC_STR_SIZE_MAX (2U+1U+4U+1U+4U+1U+4U+1U)
 #define RGX_BVNC_STR_FMTSPEC  "%u.%u.%u.%u"
 #define RGX_BVNC_STRP_FMTSPEC "%u.%up.%u.%u"
 
@@ -90,8 +90,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * RGX Defines
  *****************************************************************************/
 
-#define BVNC_FIELD_MASK     ((1 << BVNC_FIELD_WIDTH) - 1)
-#define C_POSITION          (0)
+#define BVNC_FIELD_MASK     ((1UL << BVNC_FIELD_WIDTH) - 1U)
+#define C_POSITION          (0U)
 #define N_POSITION          ((C_POSITION) + (BVNC_FIELD_WIDTH))
 #define V_POSITION          ((N_POSITION) + (BVNC_FIELD_WIDTH))
 #define B_POSITION          ((V_POSITION) + (BVNC_FIELD_WIDTH))
@@ -126,10 +126,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGXFW_THREAD_1                                    (1U)
 
 /* META cores (required for the RGX_FEATURE_META) */
-#define MTP218   (1)
-#define MTP219   (2)
-#define LTP218   (3)
-#define LTP217   (4)
+#define MTP218   (1U)
+#define MTP219   (2U)
+#define LTP218   (3U)
+#define LTP217   (4U)
 
 /* META Core memory feature depending on META variants */
 #define RGX_META_COREMEM_32K      (32*1024)
@@ -157,10 +157,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 #endif
 
-#define GET_ROGUE_CACHE_LINE_SIZE(x)    ((((IMG_INT32)(x)) > 0) ? ((x)/8) : (0))
+#define GET_ROGUE_CACHE_LINE_SIZE(x)    ((((IMG_UINT32)(x)) > 0U) ? ((IMG_UINT32)(x)/8U) : (0U))
 
 
+#if defined(SUPPORT_AGP)
+#define MAX_HW_TA3DCONTEXTS    3U
+#else
 #define MAX_HW_TA3DCONTEXTS    2U
+#endif
 
 #define RGX_CR_CLK_CTRL_ALL_ON          (IMG_UINT64_C(0x5555555555555555)&RGX_CR_CLK_CTRL_MASKFULL)
 #define RGX_CR_CLK_CTRL_ALL_AUTO        (IMG_UINT64_C(0xaaaaaaaaaaaaaaaa)&RGX_CR_CLK_CTRL_MASKFULL)
@@ -207,10 +211,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 #define RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT            (12U)
-#define RGX_BIF_PM_PHYSICAL_PAGE_SIZE                  (1U << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT)
+#define RGX_BIF_PM_PHYSICAL_PAGE_SIZE                  (1UL << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT)
 
 #define RGX_BIF_PM_VIRTUAL_PAGE_ALIGNSHIFT             (14U)
-#define RGX_BIF_PM_VIRTUAL_PAGE_SIZE                   (1U << RGX_BIF_PM_VIRTUAL_PAGE_ALIGNSHIFT)
+#define RGX_BIF_PM_VIRTUAL_PAGE_SIZE                   (1UL << RGX_BIF_PM_VIRTUAL_PAGE_ALIGNSHIFT)
 
 #define RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE        (16U)
 
@@ -243,11 +247,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * FW MMU contexts
  */
 #if defined(SUPPORT_TRUSTED_DEVICE) && defined(RGX_FEATURE_META)
-#define MMU_CONTEXT_MAPPING_FWPRIV (0x0) /* FW code/private data */
-#define MMU_CONTEXT_MAPPING_FWIF   (0x7) /* Host/FW data */
+#define MMU_CONTEXT_MAPPING_FWPRIV (0x0U) /* FW code/private data */
+#define MMU_CONTEXT_MAPPING_FWIF   (0x7U) /* Host/FW data */
 #else
-#define MMU_CONTEXT_MAPPING_FWPRIV (0x0)
-#define MMU_CONTEXT_MAPPING_FWIF   (0x0)
+#define MMU_CONTEXT_MAPPING_FWPRIV (0x0U)
+#define MMU_CONTEXT_MAPPING_FWIF   (0x0U)
 #endif
 
 
index 90e4b1b..fe8272b 100644 (file)
@@ -222,10 +222,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_MH_TAG_SB_MMU_ENCODING_MMU_TAG_PM_PC_WREQUEST (0x00000007U)
 
 
-#define RGX_MH_TAG_ENCODING_MH_TAG_MMU_PT                 (0x00000000U)
-#define RGX_MH_TAG_ENCODING_MH_TAG_MMU_PD                 (0x00000001U)
-#define RGX_MH_TAG_ENCODING_MH_TAG_MMU_PC                 (0x00000002U)
-#define RGX_MH_TAG_ENCODING_MH_TAG_MMU_PM                 (0x00000003U)
+#define RGX_MH_TAG_ENCODING_MH_TAG_MMU                    (0x00000000U)
+#define RGX_MH_TAG_ENCODING_MH_TAG_CPU_MMU                (0x00000001U)
+#define RGX_MH_TAG_ENCODING_MH_TAG_CPU_IFU                (0x00000002U)
+#define RGX_MH_TAG_ENCODING_MH_TAG_CPU_LSU                (0x00000003U)
 #define RGX_MH_TAG_ENCODING_MH_TAG_MIPS                   (0x00000004U)
 #define RGX_MH_TAG_ENCODING_MH_TAG_CDM_STG0               (0x00000005U)
 #define RGX_MH_TAG_ENCODING_MH_TAG_CDM_STG1               (0x00000006U)
index f35324f..a1d7145 100644 (file)
@@ -45,15 +45,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef CACHE_OPS_H
 #define CACHE_OPS_H
 #include "img_types.h"
-
-//#define CACHE_TEST
-
-#define CACHE_BATCH_MAX (8)
+/*!
+* @Defgroup CPUCacheAPIs
+* @{
+*/
+#define CACHE_BATCH_MAX (8U)
 #define MAX_DMA_OPS (34)
 typedef IMG_UINT32 PVRSRV_CACHE_OP;                            /*!< Type represents cache maintenance operation */
-#define PVRSRV_CACHE_OP_NONE                           0x0     /*!< No operation */
-#define PVRSRV_CACHE_OP_CLEAN                          0x1     /*!< Flush w/o invalidate */
-#define PVRSRV_CACHE_OP_INVALIDATE                     0x2     /*!< Invalidate w/o flush */
-#define PVRSRV_CACHE_OP_FLUSH                          0x3     /*!< Flush w/ invalidate */
+#define PVRSRV_CACHE_OP_NONE                           0x0U    /*!< No operation */
+#define PVRSRV_CACHE_OP_CLEAN                          0x1U    /*!< Flush w/o invalidate */
+#define PVRSRV_CACHE_OP_INVALIDATE                     0x2U    /*!< Invalidate w/o flush */
+#define PVRSRV_CACHE_OP_FLUSH                          0x3U    /*!< Flush w/ invalidate */
+/*! @} End of Defgroup CPUCacheAPIs */
 
 #endif /* CACHE_OPS_H */
index 9b63a55..dd66fcc 100644 (file)
@@ -101,27 +101,27 @@ typedef struct
 } DEVMEM_EXPORTCOOKIE;
 
 /* Enum that describes the operation associated with changing sparse memory */
-typedef enum Resize {
-       SPARSE_RESIZE_NONE = 0,
+typedef IMG_UINT32 SPARSE_MEM_RESIZE_FLAGS;
+#define SPARSE_RESIZE_NONE 0U
 
        /* This should be set to indicate the change needs allocation */
-       SPARSE_RESIZE_ALLOC = 1,
+#define SPARSE_RESIZE_ALLOC 1U
 
        /* This should be set to indicate the change needs free */
-       SPARSE_RESIZE_FREE = 2,
+#define SPARSE_RESIZE_FREE 2U
 
-       SPARSE_RESIZE_BOTH = ((IMG_UINT8)SPARSE_RESIZE_ALLOC | (IMG_UINT8)SPARSE_RESIZE_FREE),
+#define SPARSE_RESIZE_BOTH (SPARSE_RESIZE_ALLOC | SPARSE_RESIZE_FREE)
 
        /* This should be set to silently swap underlying physical memory
         * without disturbing its device or cpu virtual maps.
         * This flag is not supported in the case of PDUMP and could lead to
         * PDUMP panic when used.
         */
-       SPARSE_REMAP_MEM = 4,
+#define SPARSE_REMAP_MEM 4U
 
        /* Should be set to get the sparse changes appear in cpu virtual map */
-       SPARSE_MAP_CPU_ADDR = 8
-}SPARSE_MEM_RESIZE_FLAGS;
+#define SPARSE_MAP_CPU_ADDR 8U
+
 
 /* To be used with all the sparse allocations that gets mapped to CPU Virtual
  * space. The sparse allocation CPU mapping is torn down and re-mapped every
@@ -137,6 +137,6 @@ typedef enum Resize {
 /* Defines the max length for PMR, MemDesc, Device memory History and RI debug
  * annotations stored in memory, including the null terminator.
  */
-#define DEVMEM_ANNOTATION_MAX_LEN (PVR_ANNOTATION_MAX_LEN + 1)
+#define DEVMEM_ANNOTATION_MAX_LEN ((IMG_UINT32)PVR_ANNOTATION_MAX_LEN + 1U)
 
 #endif /* #ifndef DEVICEMEM_TYPEDEFS_H */
index 94f1156..c0d00c9 100644 (file)
 #if !defined(__PVR_DRM_H__)
 #define __PVR_DRM_H__
 
-#include "pvr_drm_core.h"
+#include <linux/types.h>
+
+#if defined(__KERNEL__)
+#include <drm/drm.h>
+#else
+#include <drm.h>
+#endif
 
 /*
  * IMPORTANT:
@@ -68,16 +74,73 @@ struct drm_pvr_srvkm_cmd {
        __u32 out_data_size;
 };
 
+struct pvr_sync_rename_ioctl_data {
+       char szName[32];
+};
+
+struct pvr_sw_sync_create_fence_data {
+       char name[32];
+       __s32 fence;
+       __u32 pad;
+       __u64 sync_pt_idx;
+};
+
+struct pvr_sw_timeline_advance_data {
+       __u64 sync_pt_idx;
+};
+
+#define PVR_SRVKM_SERVICES_INIT  1
+#define PVR_SRVKM_SYNC_INIT 2
+struct drm_pvr_srvkm_init_data {
+       __u32 init_module;
+};
+
+/* Values used to configure the PVRSRV_DEVICE_INIT_MODE tunable (Linux-only) */
+#define PVRSRV_LINUX_DEV_INIT_ON_PROBE   1
+#define PVRSRV_LINUX_DEV_INIT_ON_OPEN    2
+#define PVRSRV_LINUX_DEV_INIT_ON_CONNECT 3
+
 /*
  * DRM command numbers, relative to DRM_COMMAND_BASE.
  * These defines must be prefixed with "DRM_".
  */
-#define DRM_PVR_SRVKM_CMD              0 /* Used for PVR Services ioctls */
 
+/* PVR Services command */
+#define DRM_PVR_SRVKM_CMD                      0
+
+/* PVR Sync commands */
+#define DRM_PVR_SYNC_RENAME_CMD                        1
+#define DRM_PVR_SYNC_FORCE_SW_ONLY_CMD         2
+
+/* PVR Software Sync commands */
+#define DRM_PVR_SW_SYNC_CREATE_FENCE_CMD       3
+#define DRM_PVR_SW_SYNC_INC_CMD                        4
+
+/* PVR Services Render Device Init command */
+#define DRM_PVR_SRVKM_INIT             5
 
 /* These defines must be prefixed with "DRM_IOCTL_". */
 #define        DRM_IOCTL_PVR_SRVKM_CMD \
        DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SRVKM_CMD, \
                 struct drm_pvr_srvkm_cmd)
 
+#define DRM_IOCTL_PVR_SYNC_RENAME_CMD \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_SYNC_RENAME_CMD, \
+               struct pvr_sync_rename_ioctl_data)
+
+#define DRM_IOCTL_PVR_SYNC_FORCE_SW_ONLY_CMD \
+       DRM_IO(DRM_COMMAND_BASE + DRM_PVR_SYNC_FORCE_SW_ONLY_CMD)
+
+#define        DRM_IOCTL_PVR_SW_SYNC_CREATE_FENCE_CMD \
+       DRM_IOWR(DRM_COMMAND_BASE + DRM_PVR_SW_SYNC_CREATE_FENCE_CMD, \
+               struct pvr_sw_sync_create_fence_data)
+
+#define DRM_IOCTL_PVR_SW_SYNC_INC_CMD \
+       DRM_IOR(DRM_COMMAND_BASE + DRM_PVR_SW_SYNC_INC_CMD, \
+               struct pvr_sw_timeline_advance_data)
+
+#define DRM_IOCTL_PVR_SRVKM_INIT \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_PVR_SRVKM_INIT, \
+               struct drm_pvr_srvkm_init_data)
+
 #endif /* defined(__PVR_DRM_H__) */
diff --git a/drivers/gpu/drm/img/img-rogue/include/drm/pvr_drm_core.h b/drivers/gpu/drm/img/img-rogue/include/drm/pvr_drm_core.h
deleted file mode 100644 (file)
index 4ffca19..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * @File
- * @Title       Linux DRM definitions shared between kernel and user space.
- * @Codingstyle LinuxKernel
- * @Copyright   1999 Precision Insight, Inc., Cedar Park, Texas.
- *              2000 VA Linux Systems, Inc., Sunnyvale, California.
- *              All rights reserved.
- * @Description This header contains a subset of the Linux kernel DRM uapi
- *              and is designed to be used in kernel and user mode. When
- *              included from kernel mode, it pulls in the full version of
- *              drm.h. Whereas, when included from user mode, it defines a
- *              minimal version of drm.h (as found in libdrm). As such, the
- *              structures and ioctl commands must exactly match those found
- *              in the Linux kernel/libdrm.
- * @License     MIT
- *
- * 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 (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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(__PVR_DRM_CORE_H__)
-#define __PVR_DRM_CORE_H__
-
-#if defined(__KERNEL__)
-#include <drm/drm.h>
-#else
-#include <asm/ioctl.h>
-#include <linux/types.h>
-
-#define DRM_IOCTL_BASE                 'd'
-#define DRM_COMMAND_BASE                0x40
-
-#define DRM_IOWR(nr, type)             _IOWR(DRM_IOCTL_BASE, nr, type)
-
-struct drm_version {
-       int version_major;
-       int version_minor;
-       int version_patchlevel;
-       __kernel_size_t name_len;
-       char *name;
-       __kernel_size_t date_len;
-       char *date;
-       __kernel_size_t desc_len;
-       char *desc;
-};
-
-struct drm_set_version {
-       int drm_di_major;
-       int drm_di_minor;
-       int drm_dd_major;
-       int drm_dd_minor;
-};
-
-#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, struct drm_version)
-#define DRM_IOCTL_SET_VERSION          DRM_IOWR(0x07, struct drm_set_version)
-#endif
-
-#endif
index 43983de..a79e8a6 100644 (file)
@@ -80,9 +80,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* True if the GCC version is at least the given version. False for older
  * versions of GCC, or other compilers.
  */
+#if defined(__GNUC__)
 #define GCC_VERSION_AT_LEAST(major, minor) \
        (__GNUC__ > (major) || \
        (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#else
+#define GCC_VERSION_AT_LEAST(major, minor) 0
+#endif
 
 /* Use Clang's __has_extension and __has_builtin macros if available. */
 #if defined(__has_extension)
@@ -146,19 +150,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                do { \
                        assert(!(msg)); \
                        __builtin_unreachable(); \
-               } while (0)
+               } while (false)
 #elif defined(_MSC_VER)
        #define unreachable(msg) \
                do { \
                        assert(!(msg)); \
                        __assume(0); \
-               } while (0)
+               } while (false)
 #else
        #define unreachable(msg) \
                do { \
                        assert(!(msg)); \
                        while (1); \
-               } while (0)
+               } while (false)
 #endif
 
 /*
@@ -171,13 +175,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                do { \
                        assert(expr); \
                        __builtin_assume(expr); \
-               } while (0)
+               } while (false)
 #elif defined(_MSC_VER)
        #define assume(expr) \
                do { \
                        assert(expr); \
                        __assume(expr); \
-               } while (0)
+               } while (false)
 #elif defined(__linux__) && defined(__KERNEL__)
        #define assume(expr) ((void)(expr))
 #elif GCC_VERSION_AT_LEAST(4, 5) || has_clang_builtin(__builtin_unreachable)
@@ -185,7 +189,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                do { \
                        if (unlikely(!(expr))) \
                                unreachable("Assumption isn't true: " # expr); \
-               } while (0)
+               } while (false)
 #else
        #define assume(expr) assert(expr)
 #endif
@@ -316,7 +320,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        #include <linux/compiler.h>
 
        #if !defined(__fallthrough)
-               #if defined(__GNUC__) && GCC_VERSION_AT_LEAST(7, 0)
+               #if GCC_VERSION_AT_LEAST(7, 0)
                        #define __fallthrough __attribute__((__fallthrough__))
                #else
                        #define __fallthrough
@@ -349,7 +353,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
        #if defined(__cplusplus) && (__cplusplus >= 201703L)
                #define __fallthrough [[fallthrough]]
-       #elif defined(__GNUC__) && GCC_VERSION_AT_LEAST(7, 0)
+       #elif GCC_VERSION_AT_LEAST(7, 0)
                #define __fallthrough __attribute__((__fallthrough__))
        #else
                #define __fallthrough
@@ -502,6 +506,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        #define VG_MARK_INITIALIZED(pvData,ui32Size) VALGRIND_MAKE_MEM_DEFINED(pvData,ui32Size)
        #define VG_MARK_NOACCESS(pvData,ui32Size) VALGRIND_MAKE_MEM_NOACCESS(pvData,ui32Size)
        #define VG_MARK_ACCESS(pvData,ui32Size) VALGRIND_MAKE_MEM_UNDEFINED(pvData,ui32Size)
+       #define VG_ASSERT_DEFINED(pvData,ui32Size) VALGRIND_CHECK_MEM_IS_DEFINED(pvData,ui32Size)
 #else
        #if defined(_MSC_VER)
        #       define PVR_MSC_SUPPRESS_4127 __pragma(warning(suppress:4127))
@@ -509,9 +514,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        #       define PVR_MSC_SUPPRESS_4127
        #endif
 
-       #define VG_MARK_INITIALIZED(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (0)
-       #define VG_MARK_NOACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (0)
-       #define VG_MARK_ACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (0)
+       #define VG_MARK_INITIALIZED(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (false)
+       #define VG_MARK_NOACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (false)
+       #define VG_MARK_ACCESS(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (false)
+       #define VG_ASSERT_DEFINED(pvData,ui32Size) PVR_MSC_SUPPRESS_4127 do { } while (false)
 #endif
 
 #define IMG_STRINGIFY_IMPL(x) # x
index 162a646..ee88e90 100644 (file)
@@ -61,7 +61,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0      fourcc_mod_code(PVR, 1)
 #define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V0_FIX  fourcc_mod_code(PVR, 2) /* Fix for HW_BRN_37464 */
-#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V1      fourcc_mod_code(PVR, 3)
+/* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V1 - moved to the public header */
 #define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V2      fourcc_mod_code(PVR, 4)
 #define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V3      fourcc_mod_code(PVR, 5)
 /* DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7 - moved to the public header */
@@ -74,7 +74,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* DRM_FORMAT_MOD_PVR_FBCDC_8x8_LOSSY75_V13 - moved to the public header */
 #define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0     fourcc_mod_code(PVR, 7)
 #define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V0_FIX fourcc_mod_code(PVR, 8) /* Fix for HW_BRN_37464 */
-#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V1     fourcc_mod_code(PVR, 9)
+/* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V1 - moved to the public header */
 #define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V2     fourcc_mod_code(PVR, 10)
 #define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V3     fourcc_mod_code(PVR, 11)
 /* DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7 - moved to the public header */
index 886b345..c2654d2 100644 (file)
@@ -109,12 +109,32 @@ typedef uint16_t          IMG_UINT16,     *IMG_PUINT16;
 typedef int16_t                        IMG_INT16;
 typedef uint32_t               IMG_UINT32,     *IMG_PUINT32;
 typedef int32_t                        IMG_INT32,      *IMG_PINT32;
+#if defined(INTEGRITY_OS)
+#if __INT_BIT >= 32U
+#define IMG_UINT32_C(n) ((IMG_UINT32)(n ## U))
+#elif __LONG_BIT >= 32U
+#define IMG_UINT32_C(n) ((IMG_UINT32)(n ## UL))
+#elif defined(__LLONG_BIT) && __LLONG_BIT >= 32U
+#define IMG_UINT32_C(n) ((IMG_UINT32)(n ## ULL))
+#endif
+#else /* defined(INTEGRITY_OS) */
 #define IMG_UINT32_C(c) ((IMG_UINT32)UINT32_C(c))
+#endif /* defined(INTEGRITY_OS) */
 
 typedef uint64_t               IMG_UINT64,     *IMG_PUINT64;
 typedef int64_t                        IMG_INT64;
 #define IMG_INT64_C(c) INT64_C(c)
+#if defined(INTEGRITY_OS)
+#if __INT_BIT >= 64U
+#define IMG_UINT64_C(n)        (n ## U)
+#elif defined(__LONG_BIT) && __LONG_BIT >= 64U
+#define IMG_UINT64_C(n)        (n ## UL)
+#elif defined(__LLONG_BIT) && __LLONG_BIT >= 64U
+#define IMG_UINT64_C(n)        (n ## ULL)
+#endif
+#else /* defined(INTEGRITY_OS) */
 #define IMG_UINT64_C(c)        UINT64_C(c)
+#endif /* defined(INTEGRITY_OS) */
 #define IMG_UINT16_C(c)        UINT16_C(c)
 #define IMG_UINT64_FMTSPEC PRIu64
 #define IMG_UINT64_FMTSPECX PRIX64
@@ -234,13 +254,19 @@ typedef struct
 {
 #if defined(UNDER_WDDM) || defined(WINDOWS_WDF)
        uintptr_t uiAddr;
-#define IMG_CAST_TO_CPUPHYADDR_UINT(var)               (uintptr_t)(var)
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var)       (uintptr_t)(var)
+#define CPUPHYADDR_FMTARG(var)                         (IMG_UINT64)(var)
+#define CPUPHYADDR_UINT_FMTSPEC "0x%016" IMG_UINT64_FMTSPECx
 #elif defined(__linux__) && defined(__KERNEL__)
        phys_addr_t uiAddr;
-#define IMG_CAST_TO_CPUPHYADDR_UINT(var)               (phys_addr_t)(var)
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var)       (phys_addr_t)(var)
+#define CPUPHYADDR_FMTARG(var)                         (&var)
+#define CPUPHYADDR_UINT_FMTSPEC "%pa"
 #else
        IMG_UINT64 uiAddr;
-#define IMG_CAST_TO_CPUPHYADDR_UINT(var)               (IMG_UINT64)(var)
+#define IMG_CAST_TO_CPUPHYADDR_UINT(var)       (IMG_UINT64)(var)
+#define CPUPHYADDR_FMTARG(var)                         (var)
+#define CPUPHYADDR_UINT_FMTSPEC "0x%016" IMG_UINT64_FMTSPECx
 #endif
 } IMG_CPU_PHYADDR;
 
@@ -292,7 +318,7 @@ typedef struct
 }
 #endif
 
-#endif /* IMG_TYPES_H */
+#endif /* IMG_TYPES_H */
 /******************************************************************************
  End of file (img_types.h)
 ******************************************************************************/
index fc66e98..c12c650 100644 (file)
@@ -46,21 +46,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/types.h>
 
 #include "pvrsrv_sync_km.h"
-
-struct pvr_sw_sync_create_fence_data {
-  char name[PVRSRV_SYNC_NAME_LENGTH];
-  __s32 fence;
-  __u32 pad;
-  __u64 sync_pt_idx;
-};
-
-struct pvr_sw_timeline_advance_data {
-  __u64 sync_pt_idx;
-};
-
-#define PVR_SW_SYNC_IOC_MAGIC 'W'
-#define PVR_SW_SYNC_IOC_CREATE_FENCE _IOWR(PVR_SW_SYNC_IOC_MAGIC, 0, struct pvr_sw_sync_create_fence_data)
-#define PVR_SW_SYNC_IOC_INC _IOR(PVR_SW_SYNC_IOC_MAGIC, 1, struct pvr_sw_timeline_advance_data)
+#include "pvr_drm.h"
 
 #endif /* defined(SUPPORT_NATIVE_FENCE_SYNC) */
 #endif
index c9e784e..370ffc0 100644 (file)
@@ -60,29 +60,29 @@ typedef atomic_t ATOMIC_T;
 
 #else /* defined(__linux__) && defined(__KERNEL__) */
 #include "img_types.h" /* needed for IMG_INT */
-typedef struct _OS_LOCK_ *POS_LOCK;
+typedef struct OS_LOCK_TAG *POS_LOCK;
 
 #if defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS)
-typedef struct _OSWR_LOCK_ *POSWR_LOCK;
+typedef struct OSWR_LOCK_TAG *POSWR_LOCK;
 #else /* defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS) */
-typedef struct _OSWR_LOCK_ {
+typedef struct OSWR_LOCK_TAG {
        IMG_UINT32 ui32Dummy;
 } *POSWR_LOCK;
 #endif /* defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS) */
 
 #if defined(__linux__)
-       typedef struct _OS_ATOMIC {IMG_INT32 counter;} ATOMIC_T;
+       typedef struct OS_ATOMIC_TAG {IMG_INT32 counter;} ATOMIC_T;
 #elif defined(__QNXNTO__)
-       typedef struct _OS_ATOMIC {IMG_INT32 counter;} ATOMIC_T;
+       typedef struct OS_ATOMIC_TAG {IMG_INT32 counter;} ATOMIC_T;
 #elif defined(_WIN32)
        /*
         * Dummy definition. WDDM doesn't use Services, but some headers
         * still have to be shared. This is one such case.
         */
-       typedef struct _OS_ATOMIC {IMG_INT32 counter;} ATOMIC_T;
+       typedef struct OS_ATOMIC_TAG {IMG_INT32 counter;} ATOMIC_T;
 #elif defined(INTEGRITY_OS)
        /* Only lower 32bits are used in OS ATOMIC APIs to have consistent behaviour across all OS */
-       typedef struct _OS_ATOMIC {IMG_INT64 counter;} ATOMIC_T;
+       typedef struct OS_ATOMIC_TAG {IMG_INT64 counter;} ATOMIC_T;
 #else
        #error "Please type-define an atomic lock for this environment"
 #endif
index 04f862b..2182a02 100644 (file)
@@ -268,14 +268,14 @@ static INLINE uint64_t __const_function RoundUpToNextPowerOfTwo_64(uint64_t n)
 */ /**************************************************************************/
 static INLINE uint32_t __const_function FloorLog2(uint32_t n)
 {
-       uint32_t log2 = 0;
+       uint32_t ui32log2 = 0;
 
-       while (n >>= 1)
+       while ((n >>= 1) != 0U)
        {
-               log2++;
+               ui32log2++;
        }
 
-       return log2;
+       return ui32log2;
 }
 
 /*************************************************************************/ /*!
@@ -285,14 +285,14 @@ static INLINE uint32_t __const_function FloorLog2(uint32_t n)
 */ /**************************************************************************/
 static INLINE uint32_t __const_function FloorLog2_64(uint64_t n)
 {
-       uint32_t log2 = 0;
+       uint32_t ui32log2 = 0;
 
-       while (n >>= 1)
+       while ((n >>= 1) != 0U)
        {
-               log2++;
+               ui32log2++;
        }
 
-       return log2;
+       return ui32log2;
 }
 
 /*************************************************************************/ /*!
@@ -302,22 +302,22 @@ static INLINE uint32_t __const_function FloorLog2_64(uint64_t n)
 */ /**************************************************************************/
 static INLINE uint32_t __const_function CeilLog2(uint32_t n)
 {
-       uint32_t log2 = 0;
+       uint32_t ui32log2 = 0;
 
-       if (n == 0)
+       if (n == 0U)
        {
                return 0;
        }
 
        n--; /* Handle powers of 2 */
 
-       while (n)
+       while (n != 0U)
        {
-               log2++;
+               ui32log2++;
                n >>= 1;
        }
 
-       return log2;
+       return ui32log2;
 }
 
 /*************************************************************************/ /*!
@@ -327,22 +327,22 @@ static INLINE uint32_t __const_function CeilLog2(uint32_t n)
 */ /**************************************************************************/
 static INLINE uint32_t __const_function CeilLog2_64(uint64_t n)
 {
-       uint32_t log2 = 0;
+       uint32_t ui32log2 = 0;
 
-       if (n == 0)
+       if (n == 0U)
        {
                return 0;
        }
 
        n--; /* Handle powers of 2 */
 
-       while (n)
+       while (n != 0U)
        {
-               log2++;
+               ui32log2++;
                n >>= 1;
        }
 
-       return log2;
+       return ui32log2;
 }
 
 /*************************************************************************/ /*!
@@ -353,13 +353,13 @@ static INLINE uint32_t __const_function CeilLog2_64(uint64_t n)
 static INLINE uint32_t __const_function ExactLog2(uint32_t n)
 {
        static const uint32_t b[] =
-               {0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
-       uint32_t r = (n & b[0]) != 0;
+               {0xAAAAAAAAU, 0xCCCCCCCCU, 0xF0F0F0F0U, 0xFF00FF00U, 0xFFFF0000U};
+       uint32_t r = (n & b[0]) != 0U;
 
-       r |= (uint32_t) ((n & b[4]) != 0) << 4;
-       r |= (uint32_t) ((n & b[3]) != 0) << 3;
-       r |= (uint32_t) ((n & b[2]) != 0) << 2;
-       r |= (uint32_t) ((n & b[1]) != 0) << 1;
+       r |= (uint32_t) ((n & b[4]) != 0U) << 4;
+       r |= (uint32_t) ((n & b[3]) != 0U) << 3;
+       r |= (uint32_t) ((n & b[2]) != 0U) << 2;
+       r |= (uint32_t) ((n & b[1]) != 0U) << 1;
 
        return r;
 }
@@ -375,13 +375,13 @@ static INLINE uint32_t __const_function ExactLog2_64(uint64_t n)
                {0xAAAAAAAAAAAAAAAAULL, 0xCCCCCCCCCCCCCCCCULL,
                 0xF0F0F0F0F0F0F0F0ULL, 0xFF00FF00FF00FF00ULL,
                 0xFFFF0000FFFF0000ULL, 0xFFFFFFFF00000000ULL};
-       uint32_t r = (n & b[0]) != 0;
+       uint32_t r = (n & b[0]) != 0U;
 
-       r |= (uint32_t) ((n & b[5]) != 0) << 5;
-       r |= (uint32_t) ((n & b[4]) != 0) << 4;
-       r |= (uint32_t) ((n & b[3]) != 0) << 3;
-       r |= (uint32_t) ((n & b[2]) != 0) << 2;
-       r |= (uint32_t) ((n & b[1]) != 0) << 1;
+       r |= (uint32_t) ((n & b[5]) != 0U) << 5;
+       r |= (uint32_t) ((n & b[4]) != 0U) << 4;
+       r |= (uint32_t) ((n & b[3]) != 0U) << 3;
+       r |= (uint32_t) ((n & b[2]) != 0U) << 2;
+       r |= (uint32_t) ((n & b[1]) != 0U) << 1;
 
        return r;
 }
index 600c004..539ef2c 100644 (file)
@@ -154,7 +154,14 @@ size_t StringLCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uDataSize);
 @Input          c     the number of bytes to be set to the given value
 @Return         Pointer to the destination memory.
  */ /**************************************************************************/
-#define OSDeviceMemSet(a,b,c) memset((a), (b), (c))
+#define OSDeviceMemSet(a,b,c) \
+       do { \
+               if ((c) != 0) \
+               { \
+                       (void) memset((a), (b), (c)); \
+                       (void) *(volatile IMG_UINT32*)((void*)(a)); \
+               } \
+       } while (false)
 
 /**************************************************************************/ /*!
 @Function       OSDeviceMemCopy
@@ -167,7 +174,14 @@ size_t StringLCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uDataSize);
 @Input          c     the number of bytes to be copied
 @Return         Pointer to the destination memory.
  */ /**************************************************************************/
-#define OSDeviceMemCopy(a,b,c) memcpy((a), (b), (c))
+#define OSDeviceMemCopy(a,b,c) \
+       do { \
+               if ((c) != 0) \
+               { \
+                       memcpy((a), (b), (c)); \
+                       (void) *(volatile IMG_UINT32*)((void*)(a)); \
+               } \
+       } while (false)
 
 #endif /* (defined(__arm64__) || defined(__aarch64__) || defined(PVRSRV_DEVMEM_TEST_SAFE_MEMSETCPY)) */
 
@@ -181,7 +195,7 @@ size_t StringLCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uDataSize);
 @Input          c     the number of bytes to be set to the given value
 @Return         Pointer to the destination memory.
  */ /**************************************************************************/
-#define OSCachedMemSet(a,b,c)  memset((a), (b), (c))
+#define OSCachedMemSet(a,b,c)  (void) memset((a), (b), (c))
 
 /**************************************************************************/ /*!
 @Function       OSCachedMemCopy
@@ -210,12 +224,22 @@ size_t StringLCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uDataSize);
 @Input          c     the number of bytes to be set to the given value
 @Return         Pointer to the destination memory.
  */ /**************************************************************************/
+#if !defined(SERVICES_SC)
+#define OSCachedMemSetWMB(a,b,c) \
+       do { \
+               if ((c) != 0) \
+               { \
+                       (void) memset((a), (b), (c)); \
+                       OSWriteMemoryBarrier(a); \
+               } \
+       } while (false)
+#else
 #define OSCachedMemSetWMB(a,b,c) \
        do { \
-               memset((a), (b), (c)); \
+               (void) memset((a), (b), (c)); \
                OSWriteMemoryBarrier(); \
-       } while (0)
-
+       } while (false)
+#endif /* !defined(SERVICES_SC) */
 /**************************************************************************/ /*!
 @Function       OSCachedMemCopy
 @Description    Copy values from one area of memory, to another, when both
@@ -228,12 +252,22 @@ size_t StringLCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc, size_t uDataSize);
 @Input          c     the number of bytes to be copied
 @Return         Pointer to the destination memory.
  */ /**************************************************************************/
+#if !defined(SERVICES_SC)
 #define OSCachedMemCopyWMB(a,b,c) \
        do { \
-               memcpy((a), (b), (c)); \
+               if ((c) != 0) \
+               { \
+                       (void) memcpy((a), (b), (c)); \
+                       OSWriteMemoryBarrier(a); \
+               } \
+       } while (false)
+#else
+#define OSCachedMemCopyWMB(a,b,c) \
+       do { \
+               (void) memcpy((a), (b), (c)); \
                OSWriteMemoryBarrier(); \
-       } while (0)
-
+       } while (false)
+#endif /* !defined(SERVICES_SC) */
 #endif /* defined(__KERNEL__) */
 
 /**************************************************************************/ /*!
index 36b47d5..3f8ccca 100644 (file)
@@ -186,6 +186,8 @@ typedef enum _PDUMP_FBC_SWIZZLE_
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_1_SURFACE   (6U << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_1_RESOURCE  (7U << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
 #define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V4                             (8U << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V4PLUS                 (9U << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
+#define PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_TFBCDC                 (10U << PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_SHIFT)
 
 /*! PDump Poll Operator */
 typedef enum _PDUMP_POLL_OPERATOR
@@ -224,9 +226,10 @@ typedef enum
        PDump states
        These values are used by the bridge call PVRSRVPDumpGetState
 */
-#define PDUMP_STATE_CAPTURE_FRAME      (1)             /*!< Flag represents the PDump being in capture range or not*/
-#define PDUMP_STATE_CONNECTED          (2)             /*!< Flag represents the PDump Client App being connected on not */
-#define PDUMP_STATE_SUSPENDED          (4)             /*!< Flag represents the PDump being suspended or not */
+#define PDUMP_STATE_CAPTURE_FRAME              (1U)            /*!< Flag represents the PDump being in capture range or not*/
+#define PDUMP_STATE_CONNECTED                  (2U)            /*!< Flag represents the PDump Client App being connected on not */
+#define PDUMP_STATE_SUSPENDED                  (4U)            /*!< Flag represents the PDump being suspended or not */
+#define PDUMP_STATE_CAPTURE_IN_INTERVAL        (8U)            /*!< Flag represents the PDump being in a capture range interval */
 
 /*!
        PDump Capture modes
index 9cd26d4..d159bf4 100644 (file)
@@ -140,6 +140,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* TFBC */
 #define IMAGE_HEADER_WORD9_LOSSY_75                                    (1 << IMAGE_HEADER_WORD9_LOSSY_SHIFT)
+#define IMAGE_HEADER_WORD9_LOSSY_37                                    (1 << IMAGE_HEADER_WORD9_LOSSY_SHIFT)
 #define IMAGE_HEADER_WORD9_LOSSY_50                                    (2 << IMAGE_HEADER_WORD9_LOSSY_SHIFT)
 #define IMAGE_HEADER_WORD9_LOSSY_25                                    (3 << IMAGE_HEADER_WORD9_LOSSY_SHIFT)
 #define IMAGE_HEADER_WORD9_LOSSY_OFF                           (0 << IMAGE_HEADER_WORD9_LOSSY_SHIFT)
@@ -171,7 +172,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define IMAGE_HEADER_WORD13_FBCCLEAR_CH3_SHIFT         (0)
 #define IMAGE_HEADER_WORD13_FBCCLEAR_CH3_CLRMSK                (0xFFFFFFFFU)
 
-/* IMAGE_HEADER_WORD14_RESERVED1 */
+#define IMAGE_HEADER_WORD14_TFBC_GROUP_SHIFT           (0)
+#define IMAGE_HEADER_WORD14_TFBC_GROUP_CLRMSK          (0x000000FFU)
+#define IMAGE_HEADER_WORD14_TFBC_GROUP_25_50_75                (0 << IMAGE_HEADER_WORD14_TFBC_GROUP_SHIFT)
+#define IMAGE_HEADER_WORD14_TFBC_GROUP_25_37_50                (1 << IMAGE_HEADER_WORD14_TFBC_GROUP_SHIFT)
+
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_SHIFT          (8)
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_CLRMSK         (0x0000FF00U)
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_ALL                    (0 << IMAGE_HEADER_WORD14_COMP_SCHEME_SHIFT)
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_D_STD_CORR     (1 << IMAGE_HEADER_WORD14_COMP_SCHEME_SHIFT)
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_D_STD_ONLY     (2 << IMAGE_HEADER_WORD14_COMP_SCHEME_SHIFT)
+#define IMAGE_HEADER_WORD14_COMP_SCHEME_PTC_ONLY       (3 << IMAGE_HEADER_WORD14_COMP_SCHEME_SHIFT)
+
+#define IMAGE_HEADER_WORD14_YUV10_OPTIMAL_FMT_8_SHIFT  (16)
+#define IMAGE_HEADER_WORD14_YUV10_OPTIMAL_FMT_8_CLRMSK (0x00FF0000U)
+#define IMAGE_HEADER_WORD14_YUV10_OPTIMAL_FMT_8_EN             (1 << IMAGE_HEADER_WORD14_YUV10_OPTIMAL_FMT_8_SHIFT) /* Treat YUV10 optimal formats as 8 bits */
 
 /* IMAGE_HEADER_WORD15_RESERVED2 */
 
index 9665ba2..41eaaae 100644 (file)
@@ -27,7 +27,7 @@ THE SOFTWARE.
 #ifndef POWERVR_BUFFER_ATTRIBS_H
 #define POWERVR_BUFFER_ATTRIBS_H
 
-/**
+/*!
  * Memory layouts
  * Defines how pixels are laid out within a surface.
  */
@@ -41,7 +41,7 @@ typedef enum
        IMG_MEMLAYOUT_INVNTWIDDLED,  /**< Resource is 2D twiddled !N style */
 } IMG_MEMLAYOUT;
 
-/**
+/*!
  * Rotation types
  */
 typedef enum
@@ -55,74 +55,117 @@ typedef enum
        IMG_ROTATION_BAD = 255,
 } IMG_ROTATION;
 
-/**
+/*!
  * Alpha types.
  */
 typedef enum
 {
-       IMG_COLOURSPACE_FORMAT_UNKNOWN                 =  0x0 << 16,
-       IMG_COLOURSPACE_FORMAT_LINEAR                  =  0x1 << 16,
-       IMG_COLOURSPACE_FORMAT_SRGB                    =  0x2 << 16,
-       IMG_COLOURSPACE_FORMAT_SCRGB                   =  0x3 << 16,
-       IMG_COLOURSPACE_FORMAT_SCRGB_LINEAR            =  0x4 << 16,
-       IMG_COLOURSPACE_FORMAT_DISPLAY_P3_LINEAR       =  0x5 << 16,
-       IMG_COLOURSPACE_FORMAT_DISPLAY_P3              =  0x6 << 16,
-       IMG_COLOURSPACE_FORMAT_BT2020_PQ               =  0x7 << 16,
-       IMG_COLOURSPACE_FORMAT_BT2020_LINEAR           =  0x8 << 16,
-       IMG_COLOURSPACE_FORMAT_DISPLAY_P3_PASSTHROUGH  =  0x9 << 16,
-       IMG_COLOURSPACE_FORMAT_MASK                    =  0xF << 16,
+       IMG_COLOURSPACE_FORMAT_UNKNOWN                 =  0x0UL << 16,
+       IMG_COLOURSPACE_FORMAT_LINEAR                  =  0x1UL << 16,
+       IMG_COLOURSPACE_FORMAT_SRGB                    =  0x2UL << 16,
+       IMG_COLOURSPACE_FORMAT_SCRGB                   =  0x3UL << 16,
+       IMG_COLOURSPACE_FORMAT_SCRGB_LINEAR            =  0x4UL << 16,
+       IMG_COLOURSPACE_FORMAT_DISPLAY_P3_LINEAR       =  0x5UL << 16,
+       IMG_COLOURSPACE_FORMAT_DISPLAY_P3              =  0x6UL << 16,
+       IMG_COLOURSPACE_FORMAT_BT2020_PQ               =  0x7UL << 16,
+       IMG_COLOURSPACE_FORMAT_BT2020_LINEAR           =  0x8UL << 16,
+       IMG_COLOURSPACE_FORMAT_DISPLAY_P3_PASSTHROUGH  =  0x9UL << 16,
+       IMG_COLOURSPACE_FORMAT_MASK                    =  0xFUL << 16,
 } IMG_COLOURSPACE_FORMAT;
 
+/*!
+ * Determines if FB Compression is Lossy
+ */
 #define IS_FBCDC_LOSSY(mode)                   ((mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8) ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4) ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2) ? IMG_TRUE : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8) ? IMG_TRUE : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8)  ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_16x4) ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_32x2) ? IMG_TRUE : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8) ? IMG_TRUE : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8)  ? IMG_TRUE : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4) ? IMG_TRUE : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2) ? IMG_TRUE : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8)  ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_16x4) ? IMG_TRUE : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_32x2) ? IMG_TRUE : IMG_FALSE)
 
+/*!
+ * Determines if FB Compression is Packed
+ */
 #define IS_FBCDC_PACKED(mode)                  ((mode == IMG_FB_COMPRESSION_DIRECT_PACKED_8x8) ? IMG_TRUE : IMG_FALSE)
 
-#define GET_FBCDC_BLOCK_TYPE(mode)             ((mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+/*!
+ * Returns type of FB Compression
+ */
+#define GET_FBCDC_BLOCK_TYPE(mode)             ((mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_PACKED_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_PACKED_8x8)   ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : mode)
 
+/*!
+ * Adds Packing compression setting to mode if viable
+ */
 #define FBCDC_MODE_ADD_PACKING(mode)   ((mode == IMG_FB_COMPRESSION_DIRECT_8x8) ? IMG_FB_COMPRESSION_DIRECT_PACKED_8x8 : mode)
 
+/*!
+ * Removes Packing compression setting from mode
+ */
 #define FBCDC_MODE_REMOVE_PACKING(mode)        ((mode == IMG_FB_COMPRESSION_DIRECT_PACKED_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : mode)
 
+/*!
+ * Adds Lossy25 compression setting to mode if viable
+ */
 #define FBCDC_MODE_ADD_LOSSY25(mode)   ((mode == IMG_FB_COMPRESSION_DIRECT_8x8) ? IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_16x4) ? IMG_FB_COMPRESSION_DIRECT_LOSSY25_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_32x2) ? IMG_FB_COMPRESSION_DIRECT_LOSSY25_32x2 : mode)
 
+/*!
+ * Adds Lossy37 compression setting to mode if viable
+ */
+#define FBCDC_MODE_ADD_LOSSY37(mode)   ((mode == IMG_FB_COMPRESSION_DIRECT_8x8) ? IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_16x4) ? IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_32x2) ? IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2 : mode)
+
+/*!
+ * Adds Lossy50 compression setting to mode if viable
+ */
 #define FBCDC_MODE_ADD_LOSSY50(mode)   ((mode == IMG_FB_COMPRESSION_DIRECT_8x8) ? IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_16x4) ? IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_32x2) ? IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2 : mode)
 
+/*!
+ * Adds Lossy75 compression setting to mode if viable
+ */
 #define FBCDC_MODE_ADD_LOSSY75(mode)   ((mode == IMG_FB_COMPRESSION_DIRECT_8x8) ? IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_16x4) ? IMG_FB_COMPRESSION_DIRECT_LOSSY75_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_32x2) ? IMG_FB_COMPRESSION_DIRECT_LOSSY75_32x2 : mode)
 
-#define FBCDC_MODE_REMOVE_LOSSY(mode)  ((mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+/*!
+ * Removes Lossy compression setting from mode
+ */
+#define FBCDC_MODE_REMOVE_LOSSY(mode)  ((mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY25_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
-                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8) ? IMG_FB_COMPRESSION_DIRECT_8x8 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : \
+                                                                               (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_8x8)  ? IMG_FB_COMPRESSION_DIRECT_8x8  : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_16x4) ? IMG_FB_COMPRESSION_DIRECT_16x4 : \
                                                                                (mode == IMG_FB_COMPRESSION_DIRECT_LOSSY75_32x2) ? IMG_FB_COMPRESSION_DIRECT_32x2 : mode)
 
-/**
+/*!
  * Types of framebuffer compression
  */
 typedef enum
@@ -141,6 +184,9 @@ typedef enum
        IMG_FB_COMPRESSION_DIRECT_PACKED_8x8,
        IMG_FB_COMPRESSION_DIRECT_LOSSY75_16x4,
        IMG_FB_COMPRESSION_DIRECT_LOSSY75_32x2,
+       IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8,
+       IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4,
+       IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2,
 } IMG_FB_COMPRESSION;
 
 
index 4856a8d..5fd79a6 100644 (file)
@@ -114,6 +114,9 @@ THE SOFTWARE.
 #define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
 #endif
 
+#define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V1      fourcc_mod_code(PVR, 3)
+#define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V1     fourcc_mod_code(PVR, 9)
+
 #define DRM_FORMAT_MOD_PVR_FBCDC_8x8_V7      fourcc_mod_code(PVR, 6)
 #define DRM_FORMAT_MOD_PVR_FBCDC_16x4_V7     fourcc_mod_code(PVR, 12)
 
index a54ee41..30f7972 100644 (file)
@@ -37,12 +37,12 @@ extern "C" {
 /*!
  * Number of sync prims still used internally in operations
  */
-#define PVRSRV_MAX_SYNC_PRIMS 4
+#define PVRSRV_MAX_SYNC_PRIMS 4U
 
 /*!
  * Maximum number of dev var updates passed in a kick call
  */
-#define PVRSRV_MAX_DEV_VARS 13
+#define PVRSRV_MAX_DEV_VARS 13U
 
 /*!
  * Number of UFOs in operations
@@ -56,7 +56,7 @@ typedef int32_t PVRSRV_TIMELINE;
 
 /*! Maximum length for an annotation name string for fence sync model objects.
  */
-#define PVRSRV_SYNC_NAME_LENGTH 32
+#define PVRSRV_SYNC_NAME_LENGTH 32U
 
 /* Macros for API callers using the fence sync model
  */
index 326bc75..7a11091 100644 (file)
@@ -44,8 +44,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef PVR_BUFFER_SYNC_SHARED_H
 #define PVR_BUFFER_SYNC_SHARED_H
 
-#define PVR_BUFFER_FLAG_READ           (1 << 0)
-#define PVR_BUFFER_FLAG_WRITE          (1 << 1)
+#define PVR_BUFFER_FLAG_READ           (1U << 0)
+#define PVR_BUFFER_FLAG_WRITE          (1U << 1)
 #define PVR_BUFFER_FLAG_MASK           (PVR_BUFFER_FLAG_READ | \
                                                                         PVR_BUFFER_FLAG_WRITE)
 
index 003afd4..56bbb13 100644 (file)
@@ -119,7 +119,7 @@ __noreturn void klocwork_abort(void);
  * them.
  */
 #if defined(__KLOCWORK__)
-#define PVR_ASSERT(x) do { if (!(x)) {klocwork_abort();} } while (0)
+#define PVR_ASSERT(x) do { if (!(x)) {klocwork_abort();} } while (false)
 #else /* ! __KLOCWORKS__ */
 
 #if defined(_WIN32)
@@ -133,7 +133,7 @@ __noreturn void klocwork_abort(void);
                        __debugbreak();                                                                         \
                }                                                                                                               \
        MSC_SUPPRESS_4127                                                                                       \
-       } while (0)
+       } while (false)
 
 #else
 
@@ -152,7 +152,7 @@ __noreturn void klocwork_abort(void);
                                                          "Debug assertion failed!");                   \
                        WARN_ON(1);                                                                                             \
                }                                                                                                                       \
-       } while (0)
+       } while (false)
 
 #else /* defined(__linux__) && defined(__KERNEL__) */
 
@@ -177,14 +177,14 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
                {                                                                                                               \
                        PVRSRVDebugAssertFail(__FILE__, __LINE__, #EXPR);       \
                }                                                                                                               \
-       } while (0)
+       } while (false)
 
 #endif /* defined(__linux__) && defined(__KERNEL__) */
 #endif /* defined(_WIN32) */
 #endif /* defined(__KLOCWORK__) */
 
 #if defined(__KLOCWORK__)
-       #define PVR_DBG_BREAK do { klocwork_abort(); } while (0)
+       #define PVR_DBG_BREAK do { klocwork_abort(); } while (false)
 #else
        #if defined(WIN32)
                #define PVR_DBG_BREAK __debugbreak()   /*!< Implementation of PVR_DBG_BREAK for (non-WinCE) Win32 */
@@ -214,8 +214,8 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
        * macros in a special way when the code is analysed by Klocwork avoids
        * them.
        */
-       #if defined(__KLOCWORK__)
-               #define PVR_ASSERT(EXPR) do { if (!(EXPR)) {klocwork_abort();} } while (0)
+       #if defined(__KLOCWORK__) && !defined(SERVICES_SC)
+               #define PVR_ASSERT(EXPR) do { if (!(EXPR)) {klocwork_abort();} } while (false)
        #else
                #define PVR_ASSERT(EXPR) (void)(EXPR) /*!< Null Implementation of PVR_ASSERT (does nothing) */
        #endif
@@ -294,21 +294,21 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
                        PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                  } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_WARN_IF_ERROR(_rc, _call) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_WARNING, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                  } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_NOMEM(_expr, _call) do \
                { if (unlikely(_expr == NULL)) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s failed (PVRSRV_ERROR_OUT_OF_MEMORY) in %s()", _call, __func__)); \
                        return PVRSRV_ERROR_OUT_OF_MEMORY; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_NOMEM(_expr, _err, _go) do \
                { if (unlikely(_expr == NULL)) { \
@@ -316,70 +316,70 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
                        _err = PVRSRV_ERROR_OUT_OF_MEMORY; \
                        goto _go; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_ERROR(_rc, _call) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                        return _rc; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_VOID_IF_ERROR(_rc, _call) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                        return; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_ERROR(_rc, _call, _go) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                        goto _go; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_WITH_ERROR(_call, _err, _rc, _go) do \
                { PVR_DPF((PVR_DBG_ERROR, "%s() failed (%s) in %s()", _call, PVRSRVGETERRORSTRING(_rc), __func__)); \
                        _err = _rc; \
                        goto _go; \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_IF_FALSE(_expr, _msg) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
                  } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_FALSE(_expr, _msg, _rc) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
                        return _rc; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_VOID_IF_FALSE(_expr, _msg) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
                        return; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_FALSE(_expr, _msg, _go) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s in %s()", _msg, __func__)); \
                        goto _go; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_INVALID_PARAM(_expr, _param) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, "%s invalid in %s()", _param, __func__)); \
                        return PVRSRV_ERROR_INVALID_PARAMS; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_INVALID_PARAM(_expr, _err, _go) do \
                { if (unlikely(!(_expr))) { \
@@ -387,7 +387,7 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
                        _err = PVRSRV_ERROR_INVALID_PARAMS; \
                        goto _go; } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_MSG(_lvl, _msg) \
                PVR_DPF((_lvl, ("In %s() "_msg), __func__))
@@ -400,42 +400,42 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
                        PVR_DPF((_lvl, ("In %s() "_msg), __func__, __VA_ARGS__)); \
                } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_IF_FALSE_VA(_lvl, _expr, _msg, ...) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((_lvl, ("In %s() "_msg), __func__, __VA_ARGS__)); \
                } \
                MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_ERROR_VA(_rc, _msg, ...) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_ERROR, ("In %s() "_msg), __func__, __VA_ARGS__)); \
                        return _rc; \
                } MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_ERROR_VA(_rc, _go, _msg, ...) do \
                { if (unlikely(_rc != PVRSRV_OK)) { \
                        PVR_DPF((PVR_DBG_ERROR, ("In %s() "_msg), __func__, __VA_ARGS__)); \
                        goto _go; \
                } MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_RETURN_IF_FALSE_VA(_expr, _rc, _msg, ...) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, ("At %s: "_msg), __func__, __VA_ARGS__)); \
                        return _rc; \
                } MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
        #define PVR_LOG_GOTO_IF_FALSE_VA(_expr, _go, _msg, ...) do \
                { if (unlikely(!(_expr))) { \
                        PVR_DPF((PVR_DBG_ERROR, ("In %s() "_msg), __func__, __VA_ARGS__)); \
                        goto _go; \
                } MSC_SUPPRESS_4127\
-               } while (0)
+               } while (false)
 
 #else /* defined(PVRSRV_NEED_PVR_DPF) */
 
@@ -450,27 +450,27 @@ PVRSRVDebugAssertFail(const IMG_CHAR *pszFile,
        #define PVR_LOG_IF_ERROR_VA(_lvl, _rc, _msg, ...) (void)(_rc)
        #define PVR_LOG_IF_FALSE_VA(_lvl, _expr, _msg, ...) (void)(_expr)
 
-       #define PVR_LOG_RETURN_IF_NOMEM(_expr, _call) do { if (unlikely(_expr == NULL)) { return PVRSRV_ERROR_OUT_OF_MEMORY; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_IF_NOMEM(_expr, _err, _go) do { if (unlikely(_expr == NULL)) { _err = PVRSRV_ERROR_OUT_OF_MEMORY; goto _go; } MSC_SUPPRESS_4127    } while (0)
+       #define PVR_LOG_RETURN_IF_NOMEM(_expr, _call) do { if (unlikely(_expr == NULL)) { return PVRSRV_ERROR_OUT_OF_MEMORY; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_IF_NOMEM(_expr, _err, _go) do { if (unlikely(_expr == NULL)) { _err = PVRSRV_ERROR_OUT_OF_MEMORY; goto _go; } MSC_SUPPRESS_4127    } while (false)
 
-       #define PVR_LOG_RETURN_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return (_rc); } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_RETURN_IF_ERROR_VA(_rc, _msg, ...) do { if (unlikely(_rc != PVRSRV_OK)) { return (_rc); } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_RETURN_VOID_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return; } MSC_SUPPRESS_4127 } while (0)
+       #define PVR_LOG_RETURN_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return (_rc); } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_RETURN_IF_ERROR_VA(_rc, _msg, ...) do { if (unlikely(_rc != PVRSRV_OK)) { return (_rc); } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_RETURN_VOID_IF_ERROR(_rc, _call) do { if (unlikely(_rc != PVRSRV_OK)) { return; } MSC_SUPPRESS_4127 } while (false)
 
-       #define PVR_LOG_GOTO_IF_ERROR(_rc, _call, _go) do { if (unlikely(_rc != PVRSRV_OK)) { goto _go; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_IF_ERROR_VA(_rc, _go, _msg, ...) do { if (unlikely(_rc != PVRSRV_OK)) { goto _go; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_WITH_ERROR(_call, _err, _rc, _go) do { _err = _rc; goto _go; MSC_SUPPRESS_4127 } while (0)
+       #define PVR_LOG_GOTO_IF_ERROR(_rc, _call, _go) do { if (unlikely(_rc != PVRSRV_OK)) { goto _go; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_IF_ERROR_VA(_rc, _go, _msg, ...) do { if (unlikely(_rc != PVRSRV_OK)) { goto _go; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_WITH_ERROR(_call, _err, _rc, _go) do { _err = _rc; goto _go; MSC_SUPPRESS_4127 } while (false)
 
        #define PVR_LOG_IF_FALSE(_expr, _msg) (void)(_expr)
-       #define PVR_LOG_RETURN_IF_FALSE(_expr, _msg, _rc) do { if (unlikely(!(_expr))) { return (_rc); } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_RETURN_IF_FALSE_VA(_expr, _rc, _msg, ...) do { if (unlikely(!(_expr))) { return (_rc); } MSC_SUPPRESS_4127 } while (0)
+       #define PVR_LOG_RETURN_IF_FALSE(_expr, _msg, _rc) do { if (unlikely(!(_expr))) { return (_rc); } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_RETURN_IF_FALSE_VA(_expr, _rc, _msg, ...) do { if (unlikely(!(_expr))) { return (_rc); } MSC_SUPPRESS_4127 } while (false)
 
-       #define PVR_LOG_RETURN_VOID_IF_FALSE(_expr, _msg) do { if (unlikely(!(_expr))) { return; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_IF_FALSE(_expr, _msg, _go) do { if (unlikely(!(_expr))) { goto _go; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_IF_FALSE_VA(_expr, _go, _msg, ...) do { if (unlikely(!(_expr))) { goto _go; } MSC_SUPPRESS_4127 } while (0)
+       #define PVR_LOG_RETURN_VOID_IF_FALSE(_expr, _msg) do { if (unlikely(!(_expr))) { return; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_IF_FALSE(_expr, _msg, _go) do { if (unlikely(!(_expr))) { goto _go; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_IF_FALSE_VA(_expr, _go, _msg, ...) do { if (unlikely(!(_expr))) { goto _go; } MSC_SUPPRESS_4127 } while (false)
 
-       #define PVR_LOG_RETURN_IF_INVALID_PARAM(_expr, _param) do { if (unlikely(!(_expr))) { return PVRSRV_ERROR_INVALID_PARAMS; } MSC_SUPPRESS_4127 } while (0)
-       #define PVR_LOG_GOTO_IF_INVALID_PARAM(_expr, _err, _go) do { if (unlikely(!(_expr))) { _err = PVRSRV_ERROR_INVALID_PARAMS; goto _go; } MSC_SUPPRESS_4127 } while (0)
+       #define PVR_LOG_RETURN_IF_INVALID_PARAM(_expr, _param) do { if (unlikely(!(_expr))) { return PVRSRV_ERROR_INVALID_PARAMS; } MSC_SUPPRESS_4127 } while (false)
+       #define PVR_LOG_GOTO_IF_INVALID_PARAM(_expr, _err, _go) do { if (unlikely(!(_expr))) { _err = PVRSRV_ERROR_INVALID_PARAMS; goto _go; } MSC_SUPPRESS_4127 } while (false)
 
        #undef PVR_DPF_FUNCTION_TRACE_ON
 
@@ -520,8 +520,10 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintf(IMG_UINT32 ui32DebugLevel,
 */ /**************************************************************************/
 IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
 
+#if !defined(DOXYGEN)
 #define PVR_DPF_FUNC__(lvl, message, ...) PVR_DPF((lvl, "%s: " message, __func__, ##__VA_ARGS__))
 #define PVR_DPF_FUNC(x) PVR_DPF_FUNC__ x
+#endif /*!defined(DOXYGEN) */
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_RETURN_IF_ERROR macro.
@@ -530,7 +532,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(_rc != PVRSRV_OK)) { \
                return _rc; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_RETURN_IF_FALSE macro.
@@ -539,7 +541,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(!(_expr))) { \
                return _rc; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_RETURN_IF_INVALID_PARAM macro.
@@ -548,7 +550,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(!(_expr))) { \
                return PVRSRV_ERROR_INVALID_PARAMS; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_RETURN_IF_NOMEM macro.
@@ -557,7 +559,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(!(_expr))) { \
                return PVRSRV_ERROR_OUT_OF_MEMORY; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_GOTO_IF_NOMEM macro.
@@ -567,7 +569,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
                _err = PVRSRV_ERROR_OUT_OF_MEMORY; \
                goto _go; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_GOTO_IF_INVALID_PARAM macro.
@@ -577,7 +579,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
                _err = PVRSRV_ERROR_INVALID_PARAMS; \
                goto _go; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_GOTO_IF_FALSE macro.
@@ -586,7 +588,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(!(_expr))) { \
                goto _go; } \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_GOTO_IF_ERROR macro.
@@ -595,7 +597,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
        { if (unlikely(_rc != PVRSRV_OK)) { \
                goto _go; } \
        MSC_SUPPRESS_4127\
-       } while (0)
+       } while (false)
 
 /* Note: Use only when a log message due to the error absolutely should not
  *       be printed. Otherwise use PVR_LOG_GOTO_WITH_ERROR macro.
@@ -603,7 +605,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
 #define PVR_GOTO_WITH_ERROR(_err, _rc, _go) do \
        { _err = _rc; goto _go; \
        MSC_SUPPRESS_4127 \
-       } while (0)
+       } while (false)
 
 /*! @cond Doxygen_Suppress */
 #if defined(PVR_DPF_FUNCTION_TRACE_ON)
@@ -615,19 +617,19 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVDebugPrintfDumpCCB(void);
                PVR_DPF((PVR_DBG_CALLTRACE, "|-> %s:%d entered (0x%lx)", __func__, __LINE__, ((unsigned long)p1)))
 
        #define PVR_DPF_RETURN_RC(a) \
-       do { int _r = (a); PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned %d", __func__, __LINE__, (_r))); return (_r); MSC_SUPPRESS_4127 } while (0)
+       do { int _r = (a); PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned %d", __func__, __LINE__, (_r))); return (_r); MSC_SUPPRESS_4127 } while (false)
 
        #define PVR_DPF_RETURN_RC1(a,p1) \
-               do { int _r = (a); PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned %d (0x%lx)", __func__, __LINE__, (_r), ((unsigned long)p1))); return (_r); MSC_SUPPRESS_4127 } while (0)
+               do { int _r = (a); PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned %d (0x%lx)", __func__, __LINE__, (_r), ((unsigned long)p1))); return (_r); MSC_SUPPRESS_4127 } while (false)
 
        #define PVR_DPF_RETURN_VAL(a) \
-               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned with value", __func__, __LINE__)); return (a); MSC_SUPPRESS_4127 } while (0)
+               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned with value", __func__, __LINE__)); return (a); MSC_SUPPRESS_4127 } while (false)
 
        #define PVR_DPF_RETURN_OK \
-               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned ok", __func__, __LINE__)); return PVRSRV_OK; MSC_SUPPRESS_4127 } while (0)
+               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned ok", __func__, __LINE__)); return PVRSRV_OK; MSC_SUPPRESS_4127 } while (false)
 
        #define PVR_DPF_RETURN \
-               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned", __func__, __LINE__)); return; MSC_SUPPRESS_4127 } while (0)
+               do { PVR_DPF((PVR_DBG_CALLTRACE, "<-| %s:%d returned", __func__, __LINE__)); return; MSC_SUPPRESS_4127 } while (false)
 
        #if !defined(DEBUG)
        #error PVR DPF Function trace enabled in release build, rectify
@@ -742,7 +744,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
        #define PVR_DBG_FILELINE_ARG , pszaFile, ui32Line
        #define PVR_DBG_FILELINE_FMT " %s:%u"
        #define PVR_DBG_FILELINE_UNREF() do { PVR_UNREFERENCED_PARAMETER(pszaFile); \
-                               PVR_UNREFERENCED_PARAMETER(ui32Line); } while (0)
+                               PVR_UNREFERENCED_PARAMETER(ui32Line); } while (false)
 #else
        #define PVR_DBG_FILELINE
        #define PVR_DBG_FILELINE_PARAM
@@ -840,7 +842,7 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
     @brief Goes to a label if expression is false.
 
     @def PVR_GOTO_IF_FALSE
-    @def Goes to a label if expression is false.
+    @brief Goes to a label if expression is false.
 
     @def PVR_GOTO_IF_ERROR
     @brief Goes to a label if the error code is different than PVRSRV_OK;
@@ -852,6 +854,29 @@ IMG_EXPORT void IMG_CALLCONV PVRSRVTrace(const IMG_CHAR* pszFormat, ... )
     @brief Prints message to a log unconditionally.
 
     This macro will print messages only if PVRSRV_NEED_PVR_LOG macro is defined.
+    @def PVR_LOG_MSG
+    @brief Prints message to a log with the given log-level.
+
+    @def PVR_LOG_VA
+    @brief Prints message with var-args to a log with the given log-level.
+
+    @def PVR_LOG_IF_ERROR_VA
+    @brief Prints message with var-args to a log if the error code is different than PVRSRV_OK.
+
+    @def PVR_LOG_IF_FALSE_VA
+    @brief Prints message with var-args if expression is false.
+
+    @def PVR_LOG_RETURN_IF_ERROR_VA
+    @brief Prints message with var-args to a log and returns the error code.
+
+    @def PVR_LOG_GOTO_IF_ERROR_VA
+    @brief Prints message with var-args to a log and goes to a label if the error code is different than PVRSRV_OK.
+
+    @def PVR_LOG_RETURN_IF_FALSE_VA
+    @brief Logs the error message with var-args if the expression is false and returns the error code.
+
+    @def PVR_LOG_GOTO_IF_FALSE_VA
+    @brief Logs the error message with var-args and goes to a label if the expression is false.
 
     @def PVR_TRACE_EMPTY_LINE
     @brief Prints empty line to a log (PVRSRV_NEED_PVR_LOG must be defined).
index 7d10816..3645e29 100644 (file)
@@ -48,15 +48,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/types.h>
 #include <linux/ioctl.h>
 
-#define PVR_SYNC_MAX_QUERY_FENCE_POINTS 14
-
-#define PVR_SYNC_IOC_MAGIC 'W'
-
-#define PVR_SYNC_IOC_RENAME \
- _IOW(PVR_SYNC_IOC_MAGIC,  4, struct pvr_sync_rename_ioctl_data)
+#include "pvr_drm.h"
 
-#define PVR_SYNC_IOC_FORCE_SW_ONLY \
- _IO(PVR_SYNC_IOC_MAGIC,   5)
+#define PVR_SYNC_MAX_QUERY_FENCE_POINTS 14
 
 struct pvr_sync_pt_info {
        /* Output */
@@ -67,10 +61,4 @@ struct pvr_sync_pt_info {
        __u32 ui32TlTaken;
 } __attribute__((packed, aligned(8)));
 
-struct pvr_sync_rename_ioctl_data
-{
-       /* Input */
-       char szName[32];
-} __attribute__((packed, aligned(8)));
-
 #endif /* _PVR_FD_SYNC_KERNEL_H_ */
index 3832fdb..662e3bc 100644 (file)
@@ -45,7 +45,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "img_types.h"
 
-#define PVRSRV_MAX_DEVICES             16      /*!< Largest supported number of devices on the system */
+#define PVRSRV_MAX_DEVICES             16U     /*!< Largest supported number of devices on the system */
 
 #if defined(__KERNEL__) && defined(__linux__) && !defined(__GENKSYMS__)
 #define __pvrsrv_defined_struct_enum__
index 19dc0a4..a8c64e3 100644 (file)
@@ -55,8 +55,8 @@ extern "C" {
 
 #define DEVVAR_MAX_NAME_LEN 32
 
-typedef struct _PVRSRV_DEVVARCTX_ *PDEVVARCTX;
-typedef struct _PVRSRV_DEVVAR_    *PDEVVAR;
+typedef struct SYNC_PRIM_CONTEXT_TAG *PDEVVARCTX;
+typedef struct PVRSRV_CLIENT_SYNC_PRIM_TAG *PDEVVAR;
 
 typedef struct PVRSRV_DEV_VAR_UPDATE_TAG
 {
index e560d09..59b9cfe 100644 (file)
@@ -405,3 +405,6 @@ PVRE(PVRSRV_ERROR_UNABLE_TO_DESTROY_SEMAPHORE)
 PVRE(PVRSRV_ERROR_TOO_MANY_SYNCS)
 PVRE(PVRSRV_ERROR_ION_NO_CLIENT)
 PVRE(PVRSRV_ERROR_ION_FAILED_TO_ALLOC)
+PVRE(PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+PVRE(PVRSRV_ERROR_REFCOUNT_OVERFLOW)
+PVRE(PVRSRV_ERROR_OUT_OF_RANGE)
index 3ab4a6f..1072ba8 100644 (file)
@@ -52,34 +52,119 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * A system Phys Heap Config is linked to one or more Phys Heaps. When a heap
  * is not present in the system configuration the allocation will fallback to
  * the default GPU_LOCAL physical heap which all systems must define.
+ * See PVRSRV_MEMALLOCFLAGS_*_MAPPABLE_MASK.
+ *
+ * NOTE: Enum order important, table in physheap.c must change if order changed.
  */
-typedef enum
+typedef IMG_UINT32 PVRSRV_PHYS_HEAP;
+/* Services client accessible heaps */
+#define PVRSRV_PHYS_HEAP_DEFAULT      0U  /* default phys heap for device memory allocations */
+#define PVRSRV_PHYS_HEAP_GPU_LOCAL    1U  /* used for buffers with more GPU access than CPU */
+#define PVRSRV_PHYS_HEAP_CPU_LOCAL    2U  /* used for buffers with more CPU access than GPU */
+#define PVRSRV_PHYS_HEAP_GPU_PRIVATE  3U  /* used for buffers that only required GPU read/write access, not visible to the CPU. */
+
+#define HEAPSTR(x) #x
+static inline const IMG_CHAR *PVRSRVGetClientPhysHeapName(PVRSRV_PHYS_HEAP ePhysHeapID)
+{
+       switch (ePhysHeapID)
+       {
+               case PVRSRV_PHYS_HEAP_DEFAULT:
+                       return HEAPSTR(PVRSRV_PHYS_HEAP_DEFAULT);
+               case PVRSRV_PHYS_HEAP_GPU_LOCAL:
+                       return HEAPSTR(PVRSRV_PHYS_HEAP_GPU_LOCAL);
+               case PVRSRV_PHYS_HEAP_CPU_LOCAL:
+                       return HEAPSTR(PVRSRV_PHYS_HEAP_CPU_LOCAL);
+               case PVRSRV_PHYS_HEAP_GPU_PRIVATE:
+                       return HEAPSTR(PVRSRV_PHYS_HEAP_GPU_PRIVATE);
+               default:
+                       return "Unknown Heap";
+       }
+}
+
+/* Services internal heaps */
+#define PVRSRV_PHYS_HEAP_FW_MAIN      4U  /* runtime data, e.g. CCBs, sync objects */
+#define PVRSRV_PHYS_HEAP_EXTERNAL     5U  /* used by some PMR import/export factories where the physical memory heap is not managed by the pvrsrv driver */
+#define PVRSRV_PHYS_HEAP_GPU_COHERENT 6U  /* used for a cache coherent region */
+#define PVRSRV_PHYS_HEAP_GPU_SECURE   7U  /* used by security validation */
+#define PVRSRV_PHYS_HEAP_FW_CONFIG    8U  /* subheap of FW_MAIN, configuration data for FW init */
+#define PVRSRV_PHYS_HEAP_FW_CODE      9U  /* used by security validation or dedicated fw */
+#define PVRSRV_PHYS_HEAP_FW_PRIV_DATA 10U /* internal FW data (like the stack, FW control data structures, etc.) */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP0   11U /* Host OS premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP1   12U /* Guest OS 1 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP2   13U /* Guest OS 2 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP3   14U /* Guest OS 3 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP4   15U /* Guest OS 4 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP5   16U /* Guest OS 5 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP6   17U /* Guest OS 6 premap fw heap */
+#define PVRSRV_PHYS_HEAP_FW_PREMAP7   18U /* Guest OS 7 premap fw heap */
+#define PVRSRV_PHYS_HEAP_LAST         19U
+
+
+static_assert(PVRSRV_PHYS_HEAP_LAST <= (0x1FU + 1U), "Ensure enum fits in memalloc flags bitfield.");
+
+/*! Type conveys the class of physical heap to instantiate within Services
+ * for the physical pool of memory. */
+typedef enum _PHYS_HEAP_TYPE_
+{
+       PHYS_HEAP_TYPE_UNKNOWN = 0,     /*!< Not a valid value for any config */
+       PHYS_HEAP_TYPE_UMA,             /*!< Heap represents OS managed physical memory heap
+                                            i.e. system RAM. Unified Memory Architecture
+                                            physmem_osmem PMR factory */
+       PHYS_HEAP_TYPE_LMA,             /*!< Heap represents physical memory pool managed by
+                                            Services i.e. carve out from system RAM or local
+                                            card memory. Local Memory Architecture
+                                            physmem_lma PMR factory */
+#if defined(__KERNEL__)
+       PHYS_HEAP_TYPE_DMA,             /*!< Heap represents a physical memory pool managed by
+                                            Services, alias of LMA and is only used on
+                                            VZ non-native system configurations for
+                                            a heap used for PHYS_HEAP_USAGE_FW_MAIN tagged
+                                            buffers */
+#if defined(SUPPORT_WRAP_EXTMEMOBJECT)
+       PHYS_HEAP_TYPE_WRAP,            /*!< Heap used to group UM buffers given
+                                            to Services. Integrity OS port only. */
+#endif
+#endif
+} PHYS_HEAP_TYPE;
+
+/* Defines used when interpreting the ui32PhysHeapFlags in PHYS_HEAP_MEM_STATS
+     0x000000000000dttt
+     d = is this the default heap? (1=yes, 0=no)
+   ttt = heap type (000 = PHYS_HEAP_TYPE_UNKNOWN,
+                    001 = PHYS_HEAP_TYPE_UMA,
+                    010 = PHYS_HEAP_TYPE_LMA,
+                    011 = PHYS_HEAP_TYPE_DMA)
+*/
+#define PVRSRV_PHYS_HEAP_FLAGS_TYPE_MASK  (0x7U << 0)
+#define PVRSRV_PHYS_HEAP_FLAGS_IS_DEFAULT (0x1U << 7)
+
+typedef struct PHYS_HEAP_MEM_STATS_TAG
+{
+       IMG_UINT64      ui64TotalSize;
+       IMG_UINT64      ui64FreeSize;
+       IMG_UINT32      ui32PhysHeapFlags;
+}PHYS_HEAP_MEM_STATS, *PHYS_HEAP_MEM_STATS_PTR;
+
+typedef struct PHYS_HEAP_MEM_STATS_PKD_TAG
+{
+       IMG_UINT64      ui64TotalSize;
+       IMG_UINT64      ui64FreeSize;
+       IMG_UINT32      ui32PhysHeapFlags;
+       IMG_UINT32      ui32Dummy;
+}PHYS_HEAP_MEM_STATS_PKD, *PHYS_HEAP_MEM_STATS_PKD_PTR;
+
+static inline const IMG_CHAR *PVRSRVGetClientPhysHeapTypeName(PHYS_HEAP_TYPE ePhysHeapType)
 {
-       /* Services external heaps */
-       PVRSRV_PHYS_HEAP_GPU_LOCAL    = 0, /* default phys heap for device memory allocations */
-       PVRSRV_PHYS_HEAP_CPU_LOCAL    = 1, /* used for buffers with more CPU access than GPU */
-
-       /* Services internal heaps */
-       PVRSRV_PHYS_HEAP_FW_MAIN      = 2, /* runtime data, e.g. CCBs, sync objects */
-       PVRSRV_PHYS_HEAP_EXTERNAL     = 3, /* used by some PMR import/export factories where the physical memory heap is not managed by the pvrsrv driver */
-       PVRSRV_PHYS_HEAP_GPU_PRIVATE  = 4, /* Non CPU-mappable memory region. See PVRSRV_MEMALLOCFLAGS_CPU_MAPPABLE_MASK. */
-       PVRSRV_PHYS_HEAP_GPU_COHERENT = 5, /* used for a cache coherent region */
-       PVRSRV_PHYS_HEAP_GPU_SECURE   = 6, /* used by security validation */
-       PVRSRV_PHYS_HEAP_FW_CONFIG    = 7, /* subheap of FW_MAIN, configuration data for FW init */
-       PVRSRV_PHYS_HEAP_FW_CODE      = 8, /* used by security validation or dedicated fw */
-       PVRSRV_PHYS_HEAP_FW_PRIV_DATA = 9, /* internal FW data (like the stack, FW control data structures, etc.) */
-       PVRSRV_PHYS_HEAP_FW_PREMAP0   = 10, /* Host OS premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP1   = 11, /* Guest OS 1 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP2   = 12, /* Guest OS 2 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP3   = 13, /* Guest OS 3 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP4   = 14, /* Guest OS 4 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP5   = 15, /* Guest OS 5 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP6   = 16, /* Guest OS 6 premap fw heap */
-       PVRSRV_PHYS_HEAP_FW_PREMAP7   = 17, /* Guest OS 7 premap fw heap */
-       PVRSRV_PHYS_HEAP_LAST
-} PVRSRV_PHYS_HEAP;
-
-
-static_assert(PVRSRV_PHYS_HEAP_LAST <= (0x1F + 1), "Ensure enum fits in memalloc flags bitfield.");
+       switch (ePhysHeapType)
+       {
+               case PHYS_HEAP_TYPE_UMA:
+                       return HEAPSTR(PHYS_HEAP_TYPE_UMA);
+               case PHYS_HEAP_TYPE_LMA:
+                       return HEAPSTR(PHYS_HEAP_TYPE_LMA);
+               default:
+                       return "Unknown Heap Type";
+       }
+}
+#undef HEAPSTR
 
 #endif /* PVRSRV_MEMALLOC_PHYSHEAP_H */
index 6e92be9..3b87dbf 100644 (file)
@@ -58,7 +58,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
 #define PVRSRV_MEMALLOCFLAGS_FMTSPEC IMG_UINT64_FMTSPECx
 
-#if defined(__KERNEL__) || defined(SERVICES_SC)
+#if defined(__KERNEL__)
 #include "pvrsrv_memallocflags_internal.h"
 #endif /* __KERNEL__ */
 
@@ -131,7 +131,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_GPU_READABLE(uiFlags)             (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READABLE) != 0)
+#define PVRSRV_CHECK_GPU_READABLE(uiFlags)             (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READABLE) != 0U)
 
 /*!
  * This flag affects the device MMU protection flags, and specifies
@@ -161,7 +161,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_GPU_WRITEABLE(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE) != 0)
+#define PVRSRV_CHECK_GPU_WRITEABLE(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE) != 0U)
 
 /*!
   The flag indicates whether an allocation can be mapped as GPU readable in another GPU memory context.
@@ -173,7 +173,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_GPU_READ_PERMITTED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED) != 0)
+#define PVRSRV_CHECK_GPU_READ_PERMITTED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_READ_PERMITTED) != 0U)
 
 /*!
   The flag indicates whether an allocation can be mapped as GPU writable in another GPU memory context.
@@ -185,7 +185,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_GPU_WRITE_PERMITTED(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED) != 0)
+#define PVRSRV_CHECK_GPU_WRITE_PERMITTED(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_GPU_WRITE_PERMITTED) != 0U)
 
 /*!
   The flag indicates that an allocation is mapped as readable to the CPU.
@@ -197,7 +197,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_CPU_READABLE(uiFlags)                             (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READABLE) != 0)
+#define PVRSRV_CHECK_CPU_READABLE(uiFlags)                             (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READABLE) != 0U)
 
 /*!
   The flag indicates that an allocation is mapped as writable to the CPU.
@@ -209,7 +209,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_CPU_WRITEABLE(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE) != 0)
+#define PVRSRV_CHECK_CPU_WRITEABLE(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE) != 0U)
 
 /*!
   The flag indicates whether an allocation can be mapped as CPU readable in another CPU memory context.
@@ -221,7 +221,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_CPU_READ_PERMITTED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED) != 0)
+#define PVRSRV_CHECK_CPU_READ_PERMITTED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED) != 0U)
 
 /*!
   The flag indicates whether an allocation can be mapped as CPU writable in another CPU memory context.
@@ -233,7 +233,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_CPU_WRITE_PERMITTED(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED) != 0)
+#define PVRSRV_CHECK_CPU_WRITE_PERMITTED(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED) != 0U)
 
 
 /*
@@ -503,7 +503,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_KERNEL_CPU_MAPPABLE(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE) != 0)
+#define PVRSRV_CHECK_KERNEL_CPU_MAPPABLE(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE) != 0U)
 
 
 
@@ -519,7 +519,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
  *
  */
 #define PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC                        (1ULL<<15)
-#define PVRSRV_CHECK_ON_DEMAND(uiFlags)                                        (((uiFlags) & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_ON_DEMAND(uiFlags)                                        (((uiFlags) & PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC) != 0U)
 
 /*!
     Indicates that the allocation will be accessed by the CPU and GPU using
@@ -533,12 +533,12 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_SVM_ALLOC(uiFlags)                                        (((uiFlags) & PVRSRV_MEMALLOCFLAG_SVM_ALLOC) != 0)
+#define PVRSRV_CHECK_SVM_ALLOC(uiFlags)                                        (((uiFlags) & PVRSRV_MEMALLOCFLAG_SVM_ALLOC) != 0U)
 
 /*!
     Indicates the particular memory that's being allocated is sparse and the
     sparse regions should not be backed by dummy page
-*/
+ */
 #define PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING            (1ULL << 18)
 
 /*!
@@ -546,12 +546,15 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_IS_SPARSE_DUMMY_BACKING_REQUIRED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING) == 0)
+#define PVRSRV_IS_SPARSE_DUMMY_BACKING_REQUIRED(uiFlags)               (((uiFlags) & PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING) == 0U)
 
 /*!
-    Services is going to clean the cache for the allocated memory.
-    For performance reasons avoid usage if allocation is written to by the
-    CPU anyway before the next GPU kick.
+  Used to force Services to carry out at least one CPU cache invalidate on a
+  CPU cached buffer during allocation of the memory. Applicable to incoherent
+  systems, it must be used for buffers which are CPU cached and which will not
+  be 100% written to by the CPU before the GPU accesses it. For performance
+  reasons, avoid usage if the whole buffer that is allocated is written to by
+  the CPU anyway before the next GPU kick, or if the system is coherent.
  */
 #define PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN                            (1ULL<<19)
 
@@ -560,7 +563,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_CPU_CACHE_CLEAN(uiFlags)                  (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN) != 0)
+#define PVRSRV_CHECK_CPU_CACHE_CLEAN(uiFlags)                  (((uiFlags) & PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN) != 0U)
 
 /*! PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING
 
@@ -570,7 +573,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
     by zero page at the time of mapping.
     The zero backed page is always with read only attribute irrespective of its
     original attributes.
-*/
+ */
 #define PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING                        (1ULL << 20)
 #define PVRSRV_IS_SPARSE_ZERO_BACKING_REQUIRED(uiFlags)                (((uiFlags) & \
                        PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING) == PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING)
@@ -630,7 +633,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags)                            (((uiFlags) & PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) != 0U)
 
 /*!
     Scribbles over the allocated memory with a poison value
@@ -648,10 +651,12 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags)                  (((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC) != 0)
+#define PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags)                  (((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC) != 0U)
 
+#if defined(DEBUG) || defined(SERVICES_SC)
 /*!
-    Causes memory to be trashed when freed, as a lazy man's security measure.
+    Causes memory to be trashed when freed, used when debugging only, not to be used
+    as a security measure.
  */
 #define PVRSRV_MEMALLOCFLAG_POISON_ON_FREE                             (1ULL<<29)
 
@@ -660,7 +665,8 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_POISON_ON_FREE(uiFlags)                   (((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE) != 0)
+#define PVRSRV_CHECK_POISON_ON_FREE(uiFlags)                   (((uiFlags) & PVRSRV_MEMALLOCFLAG_POISON_ON_FREE) != 0U)
+#endif /* DEBUG */
 
 /*!
     Avoid address alignment to a CPU or GPU cache line size.
@@ -672,7 +678,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Input  uiFlags Allocation flags.
   @Return         True if the flag is set, false otherwise
  */
-#define PVRSRV_CHECK_NO_CACHE_LINE_ALIGN(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_NO_CACHE_LINE_ALIGN) != 0)
+#define PVRSRV_CHECK_NO_CACHE_LINE_ALIGN(uiFlags)              (((uiFlags) & PVRSRV_MEMALLOCFLAG_NO_CACHE_LINE_ALIGN) != 0U)
 
 
 /*
@@ -707,7 +713,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   @Return         Flag vector with the specified bit set.
  */
 #define PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(n)     \
-                       (((n) << PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET) & \
+                       (((PVRSRV_MEMALLOCFLAGS_T)(n) << PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_OFFSET) & \
                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK)
 
 /*
@@ -727,7 +733,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
  */
 
 #define PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER           (1ULL<<35)
-#define PVRSRV_CHECK_SHARED_BUFFER(uiFlags)             (((uiFlags) & PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER) != 0)
+#define PVRSRV_CHECK_SHARED_BUFFER(uiFlags)             (((uiFlags) & PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER) != 0U)
 
 /*
  *
@@ -743,7 +749,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
 
 /*!
  * Value of enum PVRSRV_PHYS_HEAP stored in memalloc flags. If not set
- * defaults to GPU_LOCAL (value 0).
+ * i.e. PVRSRV_PHYS_HEAP_DEFAULT (value 0) used, the system layer defined default physical heap is used.
  */
 #define PVRSRV_PHYS_HEAP_HINT_SHIFT        (59)
 #define PVRSRV_PHYS_HEAP_HINT_MASK         (0x1FULL << PVRSRV_PHYS_HEAP_HINT_SHIFT)
@@ -767,7 +773,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
                                                            & PVRSRV_PHYS_HEAP_HINT_MASK)
 /*!
   @Description    Macro to replace an existing phys heap hint value in flags.
-  @Input uiFlags  Phys Heap
+  @Input PhysHeap Phys Heap Macro
   @Input uiFlags  Allocation flags
   @Return         N/A
  */
@@ -775,6 +781,17 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
                                                            PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(PhysHeap)
 
 /*!
+  @Description    Macro to replace an existing phys heap hint value using Phys Heap value.
+  @Input PhysHeap Phys Heap Value
+  @Input uiFlags  Allocation flags
+  @Return         N/A
+ */
+#define PVRSRV_CHANGE_PHYS_HEAP_HINT(Physheap, uiFlags)          (uiFlags) = ((uiFlags) & ~PVRSRV_PHYS_HEAP_HINT_MASK) | \
+                                                           (((PVRSRV_MEMALLOCFLAGS_T)(Physheap) << \
+                                                            PVRSRV_PHYS_HEAP_HINT_SHIFT) \
+                                                           & PVRSRV_PHYS_HEAP_HINT_MASK)
+
+/*!
   @Description    Macros checking if a Phys Heap hint is set.
   @Input  uiFlags Allocation flags.
   @Return         True if the hint is set, false otherwise
@@ -811,20 +828,27 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
  * Trusted device mask -- Flags in the mask are allowed for trusted device
  * because the driver cannot access the memory
  */
+#if defined(DEBUG) || defined(SERVICES_SC)
 #define PVRSRV_MEMALLOCFLAGS_TDFWMASK    ~(PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
                                            PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
                                            PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
-                                           PVRSRV_MEMALLOCFLAG_POISON_ON_FREE |        \
+                                           PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
                                            PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
                                            PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING)
-
+#else
+#define PVRSRV_MEMALLOCFLAGS_TDFWMASK    ~(PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                           PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                           PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
+                                           PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
+                                           PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING)
+#endif
 
 /*!
   PMR flags mask -- for internal services use only.  This is the set of flags
   that will be passed down and stored with the PMR, this also includes the
   MMU flags which the PMR has to pass down to mm_common.c at PMRMap time.
 */
-
+#if defined(DEBUG) || defined(SERVICES_SC)
 #define PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK  (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
                                             PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
                                             PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
@@ -837,8 +861,23 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
                                             PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC | \
                                             PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING | \
                                             PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING | \
-                                                                                       PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER | \
+                                            PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER | \
+                                            PVRSRV_PHYS_HEAP_HINT_MASK)
+#else
+#define PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK  (PVRSRV_MEMALLOCFLAG_DEVICE_FLAGS_MASK | \
+                                            PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
+                                            PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                            PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                            PVRSRV_MEMALLOCFLAG_SVM_ALLOC | \
+                                            PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
+                                            PVRSRV_MEMALLOCFLAGS_GPU_MMUFLAGSMASK | \
+                                            PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
+                                            PVRSRV_MEMALLOCFLAG_NO_OSPAGES_ON_ALLOC | \
+                                            PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING | \
+                                            PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING | \
+                                            PVRSRV_MEMALLOCFLAG_VAL_SHARED_BUFFER | \
                                             PVRSRV_PHYS_HEAP_HINT_MASK)
+#endif
 
 /*!
  * CPU mappable mask -- Any flag set in the mask requires memory to be CPU mappable
@@ -863,11 +902,18 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
   memory might be reused.
 
 */
+#if defined(DEBUG) || defined(SERVICES_SC)
+#define PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK (PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK \
+                                                      & \
+                                                      ~(PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC   | \
+                                                        PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
+                                                        PVRSRV_MEMALLOCFLAG_POISON_ON_FREE))
+#else
 #define PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK (PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK \
                                                       & \
                                                       ~(PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC   | \
                                                         PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC))
-
+#endif
 /*!
   Flags that affect _allocation_
 */
@@ -884,7 +930,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
                                                     PVRSRV_MEMALLOCFLAG_SPARSE_ZERO_BACKING | \
                                                     PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING)
 
-#if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK) != 0)
+#if ((~(PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK) & PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK) != 0U)
 #error PVRSRV_MEMALLOCFLAGS_PERMAPPINGFLAGSMASK is not a subset of PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK
 #endif
 
@@ -892,6 +938,7 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
 /*!
   Flags that affect _physical allocations_ in the DevMemX API
  */
+#if defined(DEBUG) || defined(SERVICES_SC)
 #define PVRSRV_MEMALLOCFLAGS_DEVMEMX_PHYSICAL_MASK (PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
                                                     PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
                                                     PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED | \
@@ -901,6 +948,16 @@ typedef IMG_UINT64 PVRSRV_MEMALLOCFLAGS_T;
                                                     PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
                                                     PVRSRV_MEMALLOCFLAG_POISON_ON_FREE | \
                                                     PVRSRV_PHYS_HEAP_HINT_MASK)
+#else
+#define PVRSRV_MEMALLOCFLAGS_DEVMEMX_PHYSICAL_MASK (PVRSRV_MEMALLOCFLAGS_CPU_MMUFLAGSMASK | \
+                                                    PVRSRV_MEMALLOCFLAG_GPU_CACHE_MODE_MASK | \
+                                                    PVRSRV_MEMALLOCFLAG_CPU_READ_PERMITTED | \
+                                                    PVRSRV_MEMALLOCFLAG_CPU_WRITE_PERMITTED | \
+                                                    PVRSRV_MEMALLOCFLAG_CPU_CACHE_CLEAN | \
+                                                    PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                                    PVRSRV_MEMALLOCFLAG_POISON_ON_ALLOC | \
+                                                    PVRSRV_PHYS_HEAP_HINT_MASK)
+#endif
 
 /*!
   Flags that affect _virtual allocations_ in the DevMemX API
index 9c7dfd1..28999e5 100644 (file)
@@ -62,7 +62,7 @@ typedef IMG_HANDLE PVRSRVTL_SD;
 
 /*! Packet lengths are always rounded up to a multiple of 8 bytes */
 #define PVRSRVTL_PACKET_ALIGNMENT              8U
-#define PVRSRVTL_ALIGN(x)                              (((x)+PVRSRVTL_PACKET_ALIGNMENT-1) & ~(PVRSRVTL_PACKET_ALIGNMENT-1))
+#define PVRSRVTL_ALIGN(x)                              (((x)+PVRSRVTL_PACKET_ALIGNMENT-1U) & ~(PVRSRVTL_PACKET_ALIGNMENT-1U))
 
 
 /*! A packet is made up of a header structure followed by the data bytes.
@@ -117,61 +117,60 @@ static_assert((sizeof(PVRSRVTL_PACKETHDR) & (PVRSRVTL_PACKET_ALIGNMENT-1U)) == 0
 
 /*! Packet type enumeration.
  */
-typedef enum
-{
-       /*! Undefined packet */
-       PVRSRVTL_PACKETTYPE_UNDEF = 0,
-
-       /*! Normal packet type. Indicates data follows the header.
-        */
-       PVRSRVTL_PACKETTYPE_DATA = 1,
-
-       /*! When seen this packet type indicates that at this moment in the stream
-        * packet(s) were not able to be accepted due to space constraints and
-        * that recent data may be lost - depends on how the producer handles the
-        * error. Such packets have no data, data length is 0.
-        */
-       PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED = 2,
-
-       /*! Packets with this type set are padding packets that contain undefined
-        * data and must be ignored/skipped by the client. They are used when the
-        * circular stream buffer wraps around and there is not enough space for
-        * the data at the end of the buffer. Such packets have a length of 0 or
-        * more.
-        */
-       PVRSRVTL_PACKETTYPE_PADDING = 3,
-
-       /*! This packet type conveys to the stream consumer that the stream
-        * producer has reached the end of data for that data sequence. The
-        * TLDaemon has several options for processing these packets that can
-        * be selected on a per stream basis.
-        */
-       PVRSRVTL_PACKETTYPE_MARKER_EOS = 4,
-
-       /*! This is same as PVRSRVTL_PACKETTYPE_MARKER_EOS but additionally removes
-        * old data record output file before opening new/next one
-        */
-       PVRSRVTL_PACKETTYPE_MARKER_EOS_REMOVEOLD = 5,
-
-       /*! Packet emitted on first stream opened by writer. Packet carries a name
-        * of the opened stream in a form of null-terminated string.
-        */
-       PVRSRVTL_PACKETTYPE_STREAM_OPEN_FOR_WRITE = 6,
-
-       /*! Packet emitted on last stream closed by writer. Packet carries a name
-        * of the closed stream in a form of null-terminated string.
-        */
-       PVRSRVTL_PACKETTYPE_STREAM_CLOSE_FOR_WRITE = 7,
-
-       PVRSRVTL_PACKETTYPE_LAST
-} PVRSRVTL_PACKETTYPE;
+typedef IMG_UINT32 PVRSRVTL_PACKETTYPE;
+
+/*! Undefined packet */
+#define PVRSRVTL_PACKETTYPE_UNDEF 0U
+
+/*! Normal packet type. Indicates data follows the header.
+ */
+#define PVRSRVTL_PACKETTYPE_DATA 1U
+
+/*! When seen this packet type indicates that at this moment in the stream
+ * packet(s) were not able to be accepted due to space constraints and
+ * that recent data may be lost - depends on how the producer handles the
+ * error. Such packets have no data, data length is 0.
+ */
+#define PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED 2U
+
+/*! Packets with this type set are padding packets that contain undefined
+ * data and must be ignored/skipped by the client. They are used when the
+ * circular stream buffer wraps around and there is not enough space for
+ * the data at the end of the buffer. Such packets have a length of 0 or
+ * more.
+ */
+#define PVRSRVTL_PACKETTYPE_PADDING 3U
+
+/*! This packet type conveys to the stream consumer that the stream
+ * producer has reached the end of data for that data sequence. The
+ * TLDaemon has several options for processing these packets that can
+ * be selected on a per stream basis.
+ */
+#define PVRSRVTL_PACKETTYPE_MARKER_EOS 4U
+
+/*! This is same as PVRSRVTL_PACKETTYPE_MARKER_EOS but additionally removes
+ * old data record output file before opening new/next one
+ */
+#define PVRSRVTL_PACKETTYPE_MARKER_EOS_REMOVEOLD 5U
+
+/*! Packet emitted on first stream opened by writer. Packet carries a name
+ * of the opened stream in a form of null-terminated string.
+ */
+#define PVRSRVTL_PACKETTYPE_STREAM_OPEN_FOR_WRITE 6U
+
+/*! Packet emitted on last stream closed by writer. Packet carries a name
+ * of the closed stream in a form of null-terminated string.
+ */
+#define PVRSRVTL_PACKETTYPE_STREAM_CLOSE_FOR_WRITE 7U
+
+#define PVRSRVTL_PACKETTYPE_LAST 8U
 
 /* The SET_PACKET_* macros rely on the order the PVRSRVTL_PACKETHDR members are declared:
  * uiFlags is the upper half of a structure consisting of 2 uint16 quantities.
  */
 #define PVRSRVTL_SET_PACKET_DATA(len)       (len) | (PVRSRVTL_PACKETTYPE_DATA                     << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
 #define PVRSRVTL_SET_PACKET_PADDING(len)    (len) | (PVRSRVTL_PACKETTYPE_PADDING                  << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
-#define PVRSRVTL_SET_PACKET_WRITE_FAILED    (0)   | (PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
+#define PVRSRVTL_SET_PACKET_WRITE_FAILED    (0U)   | (PVRSRVTL_PACKETTYPE_MOST_RECENT_WRITE_FAILED << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
 #define PVRSRVTL_SET_PACKET_HDR(len, type)  (len) | ((type)                                       << PVRSRVTL_PACKETHDR_TYPE_OFFSET)
 
 /*! Returns the number of bytes of data in the packet.
@@ -197,8 +196,8 @@ typedef enum
        GET_PACKET_HDR( \
                GET_PACKET_DATA_PTR(p) + \
                ( \
-                       (GET_PACKET_DATA_LEN(p) + (PVRSRVTL_PACKET_ALIGNMENT-1)) & \
-                       (~(PVRSRVTL_PACKET_ALIGNMENT-1)) \
+                       (GET_PACKET_DATA_LEN(p) + (PVRSRVTL_PACKET_ALIGNMENT-1U)) & \
+                       (~(PVRSRVTL_PACKET_ALIGNMENT-1U)) \
                ) \
        )
 
@@ -209,7 +208,7 @@ typedef enum
 /*! Set PACKETS_DROPPED flag in packet header as a part of uiTypeSize.
  * p is of type PVRSRVTL_PPACKETHDR.
  */
-#define SET_PACKETS_DROPPED(p)         (((p)->uiTypeSize) | (1<<PVRSRVTL_PACKETHDR_OLDEST_DROPPED_OFFSET))
+#define SET_PACKETS_DROPPED(p)         (((p)->uiTypeSize) | (1UL << PVRSRVTL_PACKETHDR_OLDEST_DROPPED_OFFSET))
 
 /*! Check if packets were dropped before this packet.
  * p is of type PVRSRVTL_PPACKETHDR.
index ae7a51f..c62b3f7 100644 (file)
@@ -45,21 +45,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PVRVERSION_H
 
 #define PVRVERSION_MAJ               1U
-#define PVRVERSION_MIN               15U
+#define PVRVERSION_MIN               17U
 
 #define PVRVERSION_FAMILY           "rogueddk"
-#define PVRVERSION_BRANCHNAME       "1.15"
-#define PVRVERSION_BUILD             6052913
+#define PVRVERSION_BRANCHNAME       "1.17"
+#define PVRVERSION_BUILD             6210866
 #define PVRVERSION_BSCONTROL        "Rogue_DDK_Linux_WS"
 
-#define PVRVERSION_STRING           "Rogue_DDK_Linux_WS rogueddk 1.15@6052913"
-#define PVRVERSION_STRING_SHORT     "1.15@6052913"
+#define PVRVERSION_STRING           "Rogue_DDK_Linux_WS rogueddk 1.17@6210866"
+#define PVRVERSION_STRING_SHORT     "1.17@6210866"
 
 #define COPYRIGHT_TXT               "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
 
-#define PVRVERSION_BUILD_HI          605
-#define PVRVERSION_BUILD_LO          2913
-#define PVRVERSION_STRING_NUMERIC   "1.15.605.2913"
+#define PVRVERSION_BUILD_HI          621
+#define PVRVERSION_BUILD_LO          866
+#define PVRVERSION_STRING_NUMERIC   "1.17.621.866"
 
 #define PVRVERSION_PACK(MAJOR,MINOR) (((IMG_UINT32)((IMG_UINT32)(MAJOR) & 0xFFFFU) << 16U) | (((MINOR) & 0xFFFFU) << 0U))
 #define PVRVERSION_UNPACK_MAJ(VERSION) (((VERSION) >> 16U) & 0xFFFFU)
index c195e3e..b6ae150 100644 (file)
@@ -50,22 +50,9 @@ extern "C" {
 #include "img_defs.h"
 
 /* Included to get the BVNC_KM_N defined and other feature defs */
-#include "../hwdefs/rogue/km/rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 
-/*! This macro represents a mask of LSBs that must be zero on data structure
- * sizes and offsets to ensure they are 8-byte granular on types shared between
- * the FW and host driver */
-#define RGX_FW_ALIGNMENT_LSB (7U)
-
-/*! Macro to test structure size alignment */
-#define RGX_FW_STRUCT_SIZE_ASSERT(_a)  \
-       static_assert((sizeof(_a) & RGX_FW_ALIGNMENT_LSB) == 0U,        \
-                                 "Size of " #_a " is not properly aligned")
-
-/*! Macro to test structure member alignment */
-#define RGX_FW_STRUCT_OFFSET_ASSERT(_a, _b)    \
-       static_assert((offsetof(_a, _b) & RGX_FW_ALIGNMENT_LSB) == 0U,  \
-                                 "Offset of " #_a "." #_b " is not properly aligned")
+#include "rgx_common_asserts.h"
 
 
 /* Virtualisation validation builds are meant to test the VZ-related hardware without a fully virtualised platform.
@@ -98,44 +85,27 @@ typedef IMG_UINT32 RGXFWIF_DM;
 #define        RGXFWIF_DM_3D                   IMG_UINT32_C(3)
 #define        RGXFWIF_DM_CDM                  IMG_UINT32_C(4)
 #define        RGXFWIF_DM_RAY                  IMG_UINT32_C(5)
-
-#define        RGXFWIF_DM_LAST RGXFWIF_DM_RAY
-
-typedef enum _RGX_KICK_TYPE_DM_
-{
-       RGX_KICK_TYPE_DM_GP             = 0x001,
-       RGX_KICK_TYPE_DM_TDM_2D         = 0x002,
-       RGX_KICK_TYPE_DM_TA             = 0x004,
-       RGX_KICK_TYPE_DM_3D             = 0x008,
-       RGX_KICK_TYPE_DM_CDM            = 0x010,
-       RGX_KICK_TYPE_DM_RTU            = 0x020,
-       RGX_KICK_TYPE_DM_SHG            = 0x040,
-       RGX_KICK_TYPE_DM_TQ2D           = 0x080,
-       RGX_KICK_TYPE_DM_TQ3D           = 0x100,
-       RGX_KICK_TYPE_DM_RAY            = 0x200,
-       RGX_KICK_TYPE_DM_LAST           = 0x400
-} RGX_KICK_TYPE_DM;
-
-/* Maximum number of DM in use: GP, 2D/TDM, TA, 3D, CDM, SHG, RTU, RDM */
-#define RGXFWIF_DM_DEFAULT_MAX (RGXFWIF_DM_LAST + 1U)
-
-/* Maximum number of DM in use: GP, 2D/TDM, TA, 3D, CDM, RDM*/
-#define RGXFWIF_DM_MAX                 (6U)
-#define RGXFWIF_HWDM_MAX               (RGXFWIF_DM_MAX)
-
-/* Min/Max number of HW DMs (all but GP) */
-#if defined(RGX_FEATURE_TLA)
-#define RGXFWIF_HWDM_MIN               (1U)
-#else
-#if defined(RGX_FEATURE_FASTRENDER_DM)
-#define RGXFWIF_HWDM_MIN               (1U)
-#else
-#define RGXFWIF_HWDM_MIN               (2U)
-#endif
-#endif
-
-#define RGXFWIF_DM_MIN_MTS_CNT         (6)
-#define RGXFWIF_DM_MIN_CNT             (5)
+#define        RGXFWIF_DM_GEOM2                IMG_UINT32_C(6)
+#define        RGXFWIF_DM_GEOM3                IMG_UINT32_C(7)
+#define        RGXFWIF_DM_GEOM4                IMG_UINT32_C(8)
+
+#define        RGXFWIF_DM_LAST                 RGXFWIF_DM_GEOM4
+
+typedef IMG_UINT32 RGX_KICK_TYPE_DM;
+#define RGX_KICK_TYPE_DM_GP            IMG_UINT32_C(0x001)
+#define RGX_KICK_TYPE_DM_TDM_2D        IMG_UINT32_C(0x002)
+#define RGX_KICK_TYPE_DM_TA            IMG_UINT32_C(0x004)
+#define RGX_KICK_TYPE_DM_3D            IMG_UINT32_C(0x008)
+#define RGX_KICK_TYPE_DM_CDM   IMG_UINT32_C(0x010)
+#define RGX_KICK_TYPE_DM_RTU   IMG_UINT32_C(0x020)
+#define RGX_KICK_TYPE_DM_SHG   IMG_UINT32_C(0x040)
+#define RGX_KICK_TYPE_DM_TQ2D  IMG_UINT32_C(0x080)
+#define RGX_KICK_TYPE_DM_TQ3D  IMG_UINT32_C(0x100)
+#define RGX_KICK_TYPE_DM_RAY   IMG_UINT32_C(0x200)
+#define RGX_KICK_TYPE_DM_LAST  IMG_UINT32_C(0x400)
+
+/* Maximum number of DM in use: GP, 2D/TDM, GEOM, 3D, CDM, RDM, GEOM2, GEOM3, GEOM4 */
+#define RGXFWIF_DM_MAX                 (RGXFWIF_DM_LAST + 1U)
 
 /*
  * Data Master Tags to be appended to resources created on behalf of each RGX
@@ -218,10 +188,18 @@ typedef enum _RGX_KICK_TYPE_DM_
 #define RGX_MAX_NUM_REGISTER_PROGRAMMER_WRITES  (128U)
 
 /* FW common context priority. */
-#define RGX_CTX_PRIORITY_REALTIME  (UINT32_MAX)
-#define RGX_CTX_PRIORITY_HIGH      (2U)
-#define RGX_CTX_PRIORITY_MEDIUM    (1U)
-#define RGX_CTX_PRIORITY_LOW       (0)
+/*!
+ * @AddToGroup WorkloadContexts
+ * @{
+ */
+#define RGX_CTX_PRIORITY_REALTIME  (INT32_MAX)
+#define RGX_CTX_PRIORITY_HIGH      (2U) /*!< HIGH priority */
+#define RGX_CTX_PRIORITY_MEDIUM    (1U) /*!< MEDIUM priority */
+#define RGX_CTX_PRIORITY_LOW       (0) /*!< LOW priority */
+/*!
+ * @} End of AddToGroup WorkloadContexts
+ */
+
 
 /*
  *   Use of the 32-bit context property flags mask
@@ -237,6 +215,9 @@ typedef enum _RGX_KICK_TYPE_DM_
  */
 #define RGX_CONTEXT_FLAG_DISABLESLR                                    (1UL << 0) /*!< Disable SLR */
 
+/* Bitmask of context flags allowed to be modified after context create. */
+#define RGX_CONTEXT_FLAGS_WRITEABLE_MASK            (RGX_CONTEXT_FLAG_DISABLESLR)
+
 /* List of attributes that may be set for a context */
 typedef enum _RGX_CONTEXT_PROPERTY_
 {
diff --git a/drivers/gpu/drm/img/img-rogue/include/rgx_common_asserts.h b/drivers/gpu/drm/img/img-rogue/include/rgx_common_asserts.h
new file mode 100644 (file)
index 0000000..c571cc6
--- /dev/null
@@ -0,0 +1,73 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX Common Types and Defines Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Common types and definitions for RGX software
+@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.
+*/ /**************************************************************************/
+#ifndef RGX_COMMON_ASSERTS_H
+#define RGX_COMMON_ASSERTS_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*! This macro represents a mask of LSBs that must be zero on data structure
+ * sizes and offsets to ensure they are 8-byte granular on types shared between
+ * the FW and host driver */
+#define RGX_FW_ALIGNMENT_LSB (7U)
+
+/*! Macro to test structure size alignment */
+#define RGX_FW_STRUCT_SIZE_ASSERT(_a)  \
+       static_assert((sizeof(_a) & RGX_FW_ALIGNMENT_LSB) == 0U,        \
+                                 "Size of " #_a " is not properly aligned")
+
+/*! Macro to test structure member alignment */
+#define RGX_FW_STRUCT_OFFSET_ASSERT(_a, _b)    \
+       static_assert((offsetof(_a, _b) & RGX_FW_ALIGNMENT_LSB) == 0U,  \
+                                 "Offset of " #_a "." #_b " is not properly aligned")
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* RGX_COMMON_ASSERTS_H */
+
+/******************************************************************************
+ End of file
+******************************************************************************/
index 9fa7876..c3e1333 100644 (file)
@@ -110,7 +110,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                                                                        (bvnc) = ((L).ui64BVNC == (R).ui64BVNC);                                                \
                                                                                }                                                                                                                                       \
                                                                                (all) = (version) && (bvnc);                                                                            \
-                                                                       } while (0)
+                                                                       } while (false)
 
 
 /**************************************************************************//**
@@ -121,10 +121,10 @@ static inline IMG_UINT64 rgx_bvnc_pack(IMG_UINT32 ui32B, IMG_UINT32 ui32V, IMG_U
        /*
         * Test for input B, V, N and C exceeding max bit width.
         */
-       PVR_COMPAT_ASSERT((ui32B & (~(RGX_BVNC_PACK_MASK_B >> RGX_BVNC_PACK_SHIFT_B))) == 0);
-       PVR_COMPAT_ASSERT((ui32V & (~(RGX_BVNC_PACK_MASK_V >> RGX_BVNC_PACK_SHIFT_V))) == 0);
-       PVR_COMPAT_ASSERT((ui32N & (~(RGX_BVNC_PACK_MASK_N >> RGX_BVNC_PACK_SHIFT_N))) == 0);
-       PVR_COMPAT_ASSERT((ui32C & (~(RGX_BVNC_PACK_MASK_C >> RGX_BVNC_PACK_SHIFT_C))) == 0);
+       PVR_COMPAT_ASSERT((ui32B & (~(RGX_BVNC_PACK_MASK_B >> RGX_BVNC_PACK_SHIFT_B))) == 0U);
+       PVR_COMPAT_ASSERT((ui32V & (~(RGX_BVNC_PACK_MASK_V >> RGX_BVNC_PACK_SHIFT_V))) == 0U);
+       PVR_COMPAT_ASSERT((ui32N & (~(RGX_BVNC_PACK_MASK_N >> RGX_BVNC_PACK_SHIFT_N))) == 0U);
+       PVR_COMPAT_ASSERT((ui32C & (~(RGX_BVNC_PACK_MASK_C >> RGX_BVNC_PACK_SHIFT_C))) == 0U);
 
        return (((IMG_UINT64)ui32B << RGX_BVNC_PACK_SHIFT_B) |
                        ((IMG_UINT64)ui32V << RGX_BVNC_PACK_SHIFT_V) |
index 3a8d49f..e60bafd 100644 (file)
@@ -48,21 +48,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 typedef struct
 {
-#if defined(RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT) && (RGX_FEATURE_CDM_CONTROL_STREAM_FORMAT == 2)
-       IMG_UINT64      uCDMReg_CDM_CB_QUEUE;
-       IMG_UINT64      uCDMReg_CDM_CB_BASE;
-       IMG_UINT64      uCDMReg_CDM_CB;
-#else
-       IMG_UINT64      uCDMReg_CDM_CTRL_STREAM_BASE;
-#endif
+       union
+       {
+               IMG_UINT64      uCDMReg_CDM_CB_BASE;                    //  defined(RGX_FEATURE_CDM_USER_MODE_QUEUE)
+               IMG_UINT64      uCDMReg_CDM_CTRL_STREAM_BASE;   // !defined(RGX_FEATURE_CDM_USER_MODE_QUEUE)
+       };
+       IMG_UINT64      uCDMReg_CDM_CB_QUEUE;                           // !defined(RGX_FEATURE_CDM_USER_MODE_QUEUE)
+       IMG_UINT64      uCDMReg_CDM_CB;                                         // !defined(RGX_FEATURE_CDM_USER_MODE_QUEUE)
 } RGXFWIF_RF_REGISTERS;
 
-#define RGXFWIF_RF_FLAG_ENABLE 0x00000001U /*!< enables the reset framework in the firmware */
-
 typedef struct
 {
-       IMG_UINT32           ui32Flags;
-
        /* THIS MUST BE THE LAST MEMBER OF THE CONTAINING STRUCTURE */
        RGXFWIF_RF_REGISTERS RGXFW_ALIGN sFWRegisters;
 
index bbc4d64..9238cf8 100644 (file)
@@ -71,6 +71,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        X(RGXFW_GROUP_DMA,DMA)          \
        X(RGXFW_GROUP_DBG,DBG)
 
+/*!
+ * @InGroup SRVAndFWTracing
+ * @Brief FW Trace log groups(GID) list
+ */
 enum RGXFW_LOG_SFGROUPS {
 #define X(A,B) A,
        RGXFW_LOG_SFGROUPLIST
@@ -281,10 +285,10 @@ X(177, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PHR_CONFIG, "Set Periodic Hardware Reset
 X(179, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PHR_TRIG, "PHR mode %d, FW state: 0x%08x, HWR flags: 0x%08x", 3) \
 X(180, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_PHR_RESET_DEPRECATED, "PHR mode %d triggered a reset", 1) \
 X(181, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SIGNAL_UPDATE, "Signal update, Snoop Filter: %u, Signal Id: %u", 2) \
-X(182, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FIXME_SERIES8, "WARNING: Skipping FW KCCB Cmd type %d which is not yet supported on Series8.", 1) \
+X(182, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_DEV_SERIES8_DEPRECATED, "WARNING: Skipping FW KCCB Cmd type %d which is not yet supported on Series8.", 1) \
 X(183, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_INCONSISTENT_MMU_FLAGS, "MMU context cache data NULL, but cache flags=0x%x (sync counter=%u, update value=%u) OSId=%u", 4) \
 X(184, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SLC_FLUSH, "SLC range based flush: Context=%u VAddr=0x%02x%08x, Size=0x%08x, Invalidate=%d", 5) \
-X(185, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FBSC_INVAL, "FBSC invalidate for Context [0x%08x]: Entry mask 0x%08x%08x.", 3) \
+X(185, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FBSC_INVAL, "FBSC invalidate for Context Set [0x%08x]: Entry mask 0x%08x%08x.", 3) \
 X(186, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_BRN66284_UPDATE, "TDM context switch check: Roff %u was not valid for kick starting at %u, moving back to %u", 3) \
 X(187, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SPFILTER_UPDATES, "Signal updates: FIFO: %u, Signals: 0x%08x", 2) \
 X(188, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_INVALID_FBSC_CMD, "Invalid FBSC cmd: FWCtx 0x%08x, MemCtx 0x%08x", 2) \
@@ -318,17 +322,30 @@ X(215, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_USC_TASKS_RANGE, "DM%d USC tasks range li
 X(216, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_GPU_ECC_FAULT, "ECC fault GPU=0x%08x", 1) \
 X(217, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_GPU_SAFETY_RESET, "GPU Hardware units reset to prevent transient faults.", 0) \
 X(218, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ABORTCMD, "Kick Abort cmd: FWCtx 0x%08.8x @ %d", 2) \
-X(219, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RAY, "Kick Ray: FWCtx 0x%08.8x @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 7)\
-X(220, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RAY_FINISHED, "Ray finished", 0) \
+X(219, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RAY_DEPRECATED, "Kick Ray: FWCtx 0x%08.8x @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 7)\
+X(220, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RAY_FINISHED_DEPRECATED, "Ray finished", 0) \
 X(221, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_FWDATA_INIT_STATUS, "State of firmware's private data at boot time: %d (0 = uninitialised, 1 = initialised); Fw State Flags = 0x%08X", 2) \
 X(222, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CFI_TIMEOUT, "CFI Timeout detected (%d increasing to %d)", 2) \
 X(223, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_CFI_TIMEOUT_FBM, "CFI Timeout detected for FBM (%d increasing to %d)", 2) \
 X(224, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_GEOM_OOM_DISALLOWED, "Geom OOM event not allowed", 0) \
 X(225, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_OS_PRIORITY_CHANGE, "Changing OSid %d's priority from %u to %u; Isolation = %u (0 = off; 1 = on)", 4) \
+X(226, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_SKIP_ALREADY_RUN_GEOM, "Skipping already executed TA FWCtx 0x%08.8x @ %d", 2) \
+X(227, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_ATTEMPT_TO_RUN_AHEAD_GEOM, "Attempt to execute TA FWCtx 0x%08.8x @ %d ahead of time on other GEOM", 2) \
+X(228, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TDM_DEPRECATED2, "Kick TDM: Kick ID %u FWCtx 0x%08.8x @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 8) \
+X(229, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TA_PIPELINE, "Kick TA: Kick ID %u FWCtx 0x%08.8x @ %d, RTD 0x%08x, First kick:%d, Last kick:%d, CSW resume:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 12) \
+X(230, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_3D_PIPELINE, "Kick 3D: Kick ID %u FWCtx 0x%08.8x @ %d, RTD 0x%08x, Partial render:%d, CSW resume:%d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 11) \
+X(231, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_COMPUTE_PIPELINE, "Kick Compute: Kick ID %u FWCtx 0x%08.8x @ %d. (PID:%d, prio:%d, ext:0x%08x, int:0x%08x)", 7) \
+X(232, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TDM_FINISHED_PIPELINE, "TDM finished: Kick ID %u ", 1) \
+X(233, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_TA_FINISHED_PIPELINE, "TA finished: Kick ID %u ", 1) \
+X(234, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_3D_FINISHED_PIPELINE, "3D finished: Kick ID %u , HWRTData0State=%x, HWRTData1State=%x", 3) \
+X(235, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_COMPUTE_FINISHED_PIPELINE, "Compute finished: Kick ID %u ", 1) \
+X(236, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_TDM_PIPELINE, "Kick TDM: Kick ID %u FWCtx 0x%08.8x @ %d, Base 0x%08x%08x. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 10) \
+X(237, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_KICK_RAY_PIPELINE, "Kick Ray: Kick ID %u FWCtx 0x%08.8x @ %d. (PID:%d, prio:%d, frame:%d, ext:0x%08x, int:0x%08x)", 8)\
+X(238, RGXFW_GROUP_MAIN, RGXFW_SF_MAIN_RAY_FINISHED_PIPELINE, "Ray finished: Kick ID %u ", 1) \
 \
 X(  1, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_KICK_DEPRECATED, "Bg Task DM = %u, counted = %d", 2) \
 X(  2, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_COMPLETE_DEPRECATED, "Bg Task complete DM = %u", 1) \
-X(  3, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_KICK, "Irq Task DM = %u, Breq = %d, SBIrq = 0x%x", 3) \
+X(  3, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_KICK_DEPRECATED, "Irq Task DM = %u, Breq = %d, SBIrq = 0x%x", 3) \
 X(  4, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_COMPLETE_DEPRECATED, "Irq Task complete DM = %u", 1) \
 X(  5, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KICK_MTS_BG_ALL_DEPRECATED, "Kick MTS Bg task DM=All", 0) \
 X(  6, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KICK_MTS_IRQ, "Kick MTS Irq task DM=%d", 1) \
@@ -345,6 +362,8 @@ X( 16, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KCCBCMD_EXEC_DEPRECATED, "KCCB Slot %u: DM=
 X( 17, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KCCBCMD_RTN_VALUE, "KCCB Slot %u: Return value %u", 2) \
 X( 18, RGXFW_GROUP_MTS, RGXFW_SF_MTS_BG_KICK, "Bg Task OSid = %u", 1) \
 X( 19, RGXFW_GROUP_MTS, RGXFW_SF_MTS_KCCBCMD_EXEC, "KCCB Slot %u: Cmd=0x%08x, OSid=%u", 3) \
+X( 20, RGXFW_GROUP_MTS, RGXFW_SF_MTS_IRQ_KICK, "Irq Task (EVENT_STATUS=0x%08x)", 1) \
+X( 21, RGXFW_GROUP_MTS, RGXFW_SF_MTS_VZ_SIDEBAND, "VZ sideband test, kicked with OSid=%u from MTS, OSid for test=%u", 2) \
 \
 X(  1, RGXFW_GROUP_CLEANUP, RGXFW_SF_CLEANUP_FWCTX_CLEANUP, "FwCommonContext [0x%08x] cleaned", 1) \
 X(  2, RGXFW_GROUP_CLEANUP, RGXFW_SF_CLEANUP_FWCTX_BUSY, "FwCommonContext [0x%08x] is busy: ReadOffset = %d, WriteOffset = %d", 3) \
@@ -422,9 +441,9 @@ X( 54, RGXFW_GROUP_CSW, RGXFW_SF_CSW_RDM_RESUME, "RDM FWCtx 0x%08.8x resume", 1)
 \
 X(  1, RGXFW_GROUP_BIF, RGXFW_SF_BIF_ACTIVATE_BIFREQ_DEPRECATED, "Activate MemCtx=0x%08x BIFreq=%d secure=%d", 3) \
 X(  2, RGXFW_GROUP_BIF, RGXFW_SF_BIF_DEACTIVATE, "Deactivate MemCtx=0x%08x", 1) \
-X(  3, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCREG_ALLOC, "Alloc PC reg %d", 1) \
-X(  4, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCREG_GRAB, "Grab reg %d refcount now %d", 2) \
-X(  5, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCREG_UNGRAB, "Ungrab reg %d refcount now %d", 2) \
+X(  3, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCREG_ALLOC_DEPRECATED, "Alloc PC reg %d", 1) \
+X(  4, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCSET_GRAB, "Grab reg set %d refcount now %d", 2) \
+X(  5, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCSET_UNGRAB, "Ungrab reg set %d refcount now %d", 2) \
 X(  6, RGXFW_GROUP_BIF, RGXFW_SF_BIF_SETUP_REG_BIFREQ_DEPRECATED, "Setup reg=%d BIFreq=%d, expect=0x%08x%08x, actual=0x%08x%08x", 6) \
 X(  7, RGXFW_GROUP_BIF, RGXFW_SF_BIF_TRUST_DEPRECATED, "Trust enabled:%d, for BIFreq=%d", 2) \
 X(  8, RGXFW_GROUP_BIF, RGXFW_SF_BIF_TILECFG_DEPRECATED, "BIF Tiling Cfg %d base 0x%08x%08x len 0x%08x%08x enable %d stride %d --> 0x%08x%08x", 9) \
@@ -434,10 +453,12 @@ X( 11, RGXFW_GROUP_BIF, RGXFW_SF_BIF_OSIDx, "ui32OSid = %u, Catbase = %u, Reg Ad
 X( 12, RGXFW_GROUP_BIF, RGXFW_SF_BIF_MAP_GPU_MEMORY_BIFREQ_DEPRECATED, "Map GPU memory DevVAddr 0x%x%08x, Size %u, Context ID %u, BIFREQ %u", 5) \
 X( 13, RGXFW_GROUP_BIF, RGXFW_SF_BIF_UNMAP_GPU_MEMORY, "Unmap GPU memory (event status 0x%x)", 1) \
 X( 14, RGXFW_GROUP_BIF, RGXFW_SF_BIF_ACTIVATE_DM, "Activate MemCtx=0x%08x DM=%d secure=%d", 3) \
-X( 15, RGXFW_GROUP_BIF, RGXFW_SF_BIF_SETUP_REG_DM, "Setup reg=%d DM=%d, expect=0x%08x%08x, actual=0x%08x%08x", 6) \
+X( 15, RGXFW_GROUP_BIF, RGXFW_SF_BIF_SETUP_REG_DM_DEPRECATED, "Setup reg=%d DM=%d, expect=0x%08x%08x, actual=0x%08x%08x", 6) \
 X( 16, RGXFW_GROUP_BIF, RGXFW_SF_BIF_MAP_GPU_MEMORY, "Map GPU memory DevVAddr 0x%x%08x, Size %u, Context ID %u", 4) \
 X( 17, RGXFW_GROUP_BIF, RGXFW_SF_BIF_TRUST_DM, "Trust enabled:%d, for DM=%d", 2) \
 X( 18, RGXFW_GROUP_BIF, RGXFW_SF_BIF_MAP_GPU_MEMORY_DM, "Map GPU memory DevVAddr 0x%x%08x, Size %u, Context ID %u, DM %u", 5) \
+X( 19, RGXFW_GROUP_BIF, RGXFW_SF_BIF_SETUP_REG_DM, "Setup register set=%d DM=%d, PC address=0x%08x%08x, OSid=%u, NewPCRegRequired=%d", 6) \
+X( 20, RGXFW_GROUP_BIF, RGXFW_SF_BIF_PCSET_ALLOC, "Alloc PC set %d as register range [%u - %u]", 3) \
 \
 X(  1, RGXFW_GROUP_MISC, RGXFW_SF_MISC_GPIO_WRITE, "GPIO write 0x%02x", 1) \
 X(  2, RGXFW_GROUP_MISC, RGXFW_SF_MISC_GPIO_READ, "GPIO read 0x%02x", 1) \
@@ -500,6 +521,10 @@ X( 26, RGXFW_GROUP_PM, RGXFW_SF_PM_DEFER_FL_GROW, "Deferring FL grow for non-loa
 X( 27, RGXFW_GROUP_PM, RGXFW_SF_PM_UFL_SHARED_ALBIORIX, "Is GEOM: %d, finished: %d (HWRTData = 0x%08x, MemCtx = 0x%08x)", 4) \
 X( 28, RGXFW_GROUP_PM, RGXFW_SF_PM_3D_TIMEOUT, "3D Timeout Now for FWCtx 0x%08.8x", 1) \
 X( 29, RGXFW_GROUP_PM, RGXFW_SF_PM_RECYCLE, "GEOM PM Recycle for FWCtx 0x%08.8x", 1) \
+X( 30, RGXFW_GROUP_PM, RGXFW_SF_PM_PRIMARY_CONFIG, "PM running primary config (Core %d)", 1) \
+X( 31, RGXFW_GROUP_PM, RGXFW_SF_PM_SECONDARY_CONFIG, "PM running secondary config (Core %d)", 1) \
+X( 32, RGXFW_GROUP_PM, RGXFW_SF_PM_TERTIARY_CONFIG, "PM running tertiary config (Core %d)", 1) \
+X( 33, RGXFW_GROUP_PM, RGXFW_SF_PM_QUATERNARY_CONFIG, "PM running quaternary config (Core %d)", 1) \
 \
 X(  1, RGXFW_GROUP_RPM, RGXFW_SF_RPM_GLL_DYNAMIC_STATUS_DEPRECATED, "Global link list dynamic page count: vertex 0x%x, varying 0x%x, node 0x%x", 3) \
 X(  2, RGXFW_GROUP_RPM, RGXFW_SF_RPM_GLL_STATIC_STATUS_DEPRECATED, "Global link list static page count: vertex 0x%x, varying 0x%x, node 0x%x", 3) \
@@ -562,7 +587,9 @@ X( 35, RGXFW_GROUP_RTD, RGXFW_SF_RTD_LOAD_FL_V2, "Load  Freelist 0x%x type: %d (
 X( 36, RGXFW_GROUP_RTD, RGXFW_SF_RTD_KILLED_TA, "TA RTData 0x%08x marked as killed.", 1) \
 X( 37, RGXFW_GROUP_RTD, RGXFW_SF_RTD_KILLED_3D, "3D RTData 0x%08x marked as killed.", 1) \
 X( 38, RGXFW_GROUP_RTD, RGXFW_SF_RTD_KILL_TA_AFTER_RESTART, "RTData 0x%08x will be killed after TA restart.", 1) \
-X( 39, RGXFW_GROUP_RTD, RGXFW_SF_RTD_RENDERSTATE_RESET, "RTData 0x%08x Render State Buffer 0x%08x%08x will be reset.", 3) \
+X( 39, RGXFW_GROUP_RTD, RGXFW_SF_RTD_RENDERSTATE_RESET, "RTData 0x%08x Render State Buffer 0x%02x%08x will be reset.", 3) \
+X( 40, RGXFW_GROUP_RTD, RGXFW_SF_RTD_GEOM_RENDERSTATE, "GEOM RTData 0x%08x using Render State Buffer 0x%02x%08x.", 3) \
+X( 41, RGXFW_GROUP_RTD, RGXFW_SF_RTD_FRAG_RENDERSTATE, "FRAG RTData 0x%08x using Render State Buffer 0x%02x%08x.", 3) \
 \
 X(  1, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ZLOAD_DEPRECATED, "Force Z-Load for partial render", 0) \
 X(  2, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ZSTORE_DEPRECATED, "Force Z-Store for partial render", 0) \
@@ -621,6 +648,7 @@ X( 54, RGXFW_GROUP_SPM, RGXFW_SF_SPM_ACK_GROW_UPDATE, "Received grow update, FL
 X( 66, RGXFW_GROUP_SPM, RGXFW_SF_SPM_OOM_TACMD, "OOM TA/3D PR Check: [0x%08.8x] is 0x%08.8x requires 0x%08.8x", 3) \
 X( 67, RGXFW_GROUP_SPM, RGXFW_SF_SPM_RESUMED_TA, "OOM: Resumed TA with ready pages, FL addr: 0x%02x%08x, current pages: %u", 3) \
 X( 68, RGXFW_GROUP_SPM, RGXFW_SF_SPM_PR_DEADLOCK_UNBLOCKED, "OOM TA/3D PR deadlock unblocked reordering DM%d runlist head from Context 0x%08x to 0x%08x", 3) \
+X( 69, RGXFW_GROUP_SPM, RGXFW_SF_SPM_STATE_PR_FORCEFREE, "SPM State = PR force free", 0) \
 \
 X(  1, RGXFW_GROUP_POW, RGXFW_SF_POW_CHECK_DEPRECATED, "Check Pow state DM%d int: 0x%x, ext: 0x%x, pow flags: 0x%x", 4) \
 X(  2, RGXFW_GROUP_POW, RGXFW_SF_POW_GPU_IDLE, "GPU idle (might be powered down). Pow state int: 0x%x, ext: 0x%x, flags: 0x%x", 3) \
@@ -690,6 +718,10 @@ X( 66, RGXFW_GROUP_POW, RGXFW_SF_POW_POWMON_PERF_MODE, "PPA block started in per
 X( 67, RGXFW_GROUP_POW, RGXFW_SF_POW_POWMON_RESET, "Reset PPA block state %u (1=reset, 0=recalculate).", 1) \
 X( 68, RGXFW_GROUP_POW, RGXFW_SF_POW_POWCTRL_ABORT_WITH_CORE, "Power controller returned ABORT for Core-%d last request so retrying.", 1) \
 X( 69, RGXFW_GROUP_POW, RGXFW_SF_POW_HWREQ64BIT, "HW Request On(1)/Off(0): %d, Units: 0x%08x%08x", 3) \
+X( 70, RGXFW_GROUP_POW, RGXFW_SF_POW_SPU_RAC_POW_STATE_CHANGE_REQ, "Request to change SPU power state mask from 0x%x to 0x%x and RAC from 0x%x to 0x%x. Pow flags: 0x%x", 5) \
+X( 71, RGXFW_GROUP_POW, RGXFW_SF_POW_SPU_RAC_POW_STATE_CHANGE, "Changing SPU power state mask from 0x%x to 0x%x and RAC from 0x%x to 0x%x", 4) \
+X( 72, RGXFW_GROUP_POW, RGXFW_SF_POW_REQUESTEDOFF_RAC, "RAC pending? %d, RAC Active? %d", 2) \
+X( 73, RGXFW_GROUP_POW, RGXFW_SF_POW_INIOFF_RAC, "Initiate powoff query for RAC.", 0) \
 \
 X(  1, RGXFW_GROUP_HWR, RGXFW_SF_HWR_LOCKUP_DEPRECATED, "Lockup detected on DM%d, FWCtx: 0x%08.8x", 2) \
 X(  2, RGXFW_GROUP_HWR, RGXFW_SF_HWR_RESET_FW_DEPRECATED, "Reset fw state for DM%d, FWCtx: 0x%08.8x, MemCtx: 0x%08.8x", 3) \
@@ -779,14 +811,15 @@ X( 85, RGXFW_GROUP_HWR, RGXFW_SF_HWR_FULL_CHECK, "Full Signature Check result fo
 X( 86, RGXFW_GROUP_HWR, RGXFW_SF_HWR_USC_SLOTS_CHECK, "USC Slots result for Core%u, DM%u is HWRNeeded=%u USCSlotsUsedByDM=%d", 4) \
 X( 87, RGXFW_GROUP_HWR, RGXFW_SF_HWR_WATCHDOG_CHECK, "USC Watchdog result for Core%u DM%u is HWRNeeded=%u Status=%u USCs={0x%x} with HWRChecksToGo=%u", 6) \
 X( 88, RGXFW_GROUP_HWR, RGXFW_SF_HWR_MMU_RISCV_FAULT, "RISC-V MMU page fault detected (FWCORE MMU Status 0x%08x Req Status 0x%08x%08x)", 3) \
-X( 89, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_TEXAS1_PFS_DEPRECATED, "After FW fault was raised, TEXAS1_PFS poll failed on core %d with value 0x%08x", 2) \
-X( 90, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_PFS, "After FW fault was raised, BIF_PFS poll failed on core %d with value 0x%08x", 2) \
-X( 91, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SET_ABORT_PM_STATUS, "After FW fault was raised, MMU_ABORT_PM_STATUS set poll failed on core %d with value 0x%08x", 2) \
-X( 92, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_UNSET_ABORT_PM_STATUS, "After FW fault was raised, MMU_ABORT_PM_STATUS unset poll failed on core %d with value 0x%08x", 2) \
-X( 93, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SLC_INVAL, "After FW fault was raised, MMU_CTRL_INVAL poll (all but fw) failed on core %d with value 0x%08x", 2) \
-X( 94, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SLCMMU_INVAL, "After FW fault was raised, MMU_CTRL_INVAL poll (all) failed on core %d with value 0x%08x", 2) \
-X( 95, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_TEXAS_PFS, "After FW fault was raised, TEXAS%d_PFS poll failed on core %d with value 0x%08x", 3) \
+X( 89, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_TEXAS1_PFS_DEPRECATED, "TEXAS1_PFS poll failed on core %d with value 0x%08x", 2) \
+X( 90, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_PFS, "BIF_PFS poll failed on core %d with value 0x%08x", 2) \
+X( 91, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SET_ABORT_PM_STATUS, "MMU_ABORT_PM_STATUS set poll failed on core %d with value 0x%08x", 2) \
+X( 92, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_UNSET_ABORT_PM_STATUS, "MMU_ABORT_PM_STATUS unset poll failed on core %d with value 0x%08x", 2) \
+X( 93, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SLC_INVAL, "MMU_CTRL_INVAL poll (all but fw) failed on core %d with value 0x%08x", 2) \
+X( 94, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_SLCMMU_INVAL, "MMU_CTRL_INVAL poll (all) failed on core %d with value 0x%08x", 2) \
+X( 95, RGXFW_GROUP_HWR, RGXFW_SF_HWR_HWR_FAULT_POLL_BIF_TEXAS_PFS, "TEXAS%d_PFS poll failed on core %d with value 0x%08x", 3) \
 X( 96, RGXFW_GROUP_HWR, RGXFW_SF_HWR_EXTRA_CHECK, "Extra Registers Check result for Core%u, DM%u is HWRNeeded=%u", 3) \
+X( 97, RGXFW_GROUP_HWR, RGXFW_SF_HWR_WRITE_TO_GPU_READONLY_ADDR, "FW attempted to write to read-only GPU address 0x%08x", 1) \
 \
 X(  1, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_CFGBLK, "Block 0x%x mapped to Config Idx %u", 2) \
 X(  2, RGXFW_GROUP_HWP, RGXFW_SF_HWP_I_OMTBLK, "Block 0x%x omitted from event - not enabled in HW", 1) \
@@ -881,7 +914,7 @@ X(65535, RGXFW_GROUP_NULL, RGXFW_SF_LAST, "You should not use this string", 15)
 #define RGXFW_LOG_IDMARKER                     (0x70000000U)
 #define RGXFW_LOG_CREATESFID(a,b,e) ((IMG_UINT32)(a) | ((IMG_UINT32)(b)<<12U) | ((IMG_UINT32)(e)<<16U)) | RGXFW_LOG_IDMARKER
 
-#define RGXFW_LOG_IDMASK                       (0xFFF00000)
+#define RGXFW_LOG_IDMASK                       (0xFFF00000U)
 #define RGXFW_LOG_VALIDID(I)           (((I) & RGXFW_LOG_IDMASK) == RGXFW_LOG_IDMARKER)
 
 typedef enum {
index 3615064..db2b90b 100644 (file)
@@ -57,7 +57,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * of the map / unmap functions must take into consideration
  * the entire range (i.e. main and config heap).
  */
-#define RGX_FIRMWARE_NUMBER_OF_FW_HEAPS              (2)
+#define RGX_FIRMWARE_NUMBER_OF_FW_HEAPS              (IMG_UINT32_C(2))
 #define RGX_FIRMWARE_HEAP_SHIFT                      RGX_FW_HEAP_SHIFT
 #define RGX_FIRMWARE_RAW_HEAP_BASE                   (0xE1C0000000ULL)
 #define RGX_FIRMWARE_RAW_HEAP_SIZE                   (IMG_UINT32_C(1) << RGX_FIRMWARE_HEAP_SHIFT)
@@ -73,9 +73,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * 1st PMR: RGXFWIF_CONNECTION_CTL
  * 2nd PMR: RGXFWIF_OSINIT
  * 3rd PMR: RGXFWIF_SYSINIT */
-#define RGX_FIRMWARE_CONFIG_HEAP_SIZE                (3*RGX_FIRMWARE_CONFIG_HEAP_ALLOC_GRANULARITY)
+#define RGX_FIRMWARE_CONFIG_HEAP_SIZE                (IMG_UINT32_C(3)*RGX_FIRMWARE_CONFIG_HEAP_ALLOC_GRANULARITY)
 
-#define RGX_FIRMWARE_META_MAIN_HEAP_SIZE             (RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE)
+#define RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE          (RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE)
 /*
  * MIPS FW needs space in the Main heap to map GPU memory.
  * This space is taken from the MAIN heap, to avoid creating a new heap.
@@ -83,36 +83,30 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_NORMAL       (IMG_UINT32_C(0x100000)) /* 1MB */
 #define RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_BRN65101     (IMG_UINT32_C(0x400000)) /* 4MB */
 
-#define RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL      (RGX_FIRMWARE_RAW_HEAP_SIZE -  RGX_FIRMWARE_CONFIG_HEAP_SIZE - \
-                                                      RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_NORMAL)
+#define RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_NORMAL      (RGX_FIRMWARE_RAW_HEAP_SIZE -  RGX_FIRMWARE_CONFIG_HEAP_SIZE - \
+                                                           RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_NORMAL)
 
-#define RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101    (RGX_FIRMWARE_RAW_HEAP_SIZE -  RGX_FIRMWARE_CONFIG_HEAP_SIZE - \
-                                                      RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_BRN65101)
+#define RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_BRN65101    (RGX_FIRMWARE_RAW_HEAP_SIZE -  RGX_FIRMWARE_CONFIG_HEAP_SIZE - \
+                                                           RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_BRN65101)
 
 #if !defined(__KERNEL__)
 #if defined(FIX_HW_BRN_65101)
 #define RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE      RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_BRN65101
-#define RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE             RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101
+#define RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE        RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_BRN65101
 
 #include "img_defs.h"
 static_assert((RGX_FIRMWARE_RAW_HEAP_SIZE) >= IMG_UINT32_C(0x800000), "MIPS GPU map size cannot be increased due to BRN65101 with a small FW heap");
 
 #else
 #define RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE      RGX_FIRMWARE_MIPS_GPU_MAP_RESERVED_SIZE_NORMAL
-#define RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE             RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL
+#define RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE        RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_NORMAL
 #endif
 #endif /* !defined(__KERNEL__) */
 
-/* Host sub-heap order: MAIN + CONFIG */
-#define RGX_FIRMWARE_HOST_MAIN_HEAP_BASE             RGX_FIRMWARE_RAW_HEAP_BASE
-#define RGX_FIRMWARE_HOST_CONFIG_HEAP_BASE           (RGX_FIRMWARE_HOST_MAIN_HEAP_BASE + \
-                                                      RGX_FIRMWARE_RAW_HEAP_SIZE - \
-                                                      RGX_FIRMWARE_CONFIG_HEAP_SIZE)
-
-/* Guest sub-heap order: CONFIG + MAIN */
-#define RGX_FIRMWARE_GUEST_CONFIG_HEAP_BASE          RGX_FIRMWARE_RAW_HEAP_BASE
-#define RGX_FIRMWARE_GUEST_MAIN_HEAP_BASE            (RGX_FIRMWARE_GUEST_CONFIG_HEAP_BASE + \
-                                                      RGX_FIRMWARE_CONFIG_HEAP_SIZE)
+#define RGX_FIRMWARE_MAIN_HEAP_BASE             RGX_FIRMWARE_RAW_HEAP_BASE
+#define RGX_FIRMWARE_CONFIG_HEAP_BASE           (RGX_FIRMWARE_MAIN_HEAP_BASE + \
+                                                 RGX_FIRMWARE_RAW_HEAP_SIZE - \
+                                                 RGX_FIRMWARE_CONFIG_HEAP_SIZE)
 
 /*
  * The maximum configurable size via RGX_FW_HEAP_SHIFT is 32MiB (1<<25) and
diff --git a/drivers/gpu/drm/img/img-rogue/include/rgx_hwperf_common.h b/drivers/gpu/drm/img/img-rogue/include/rgx_hwperf_common.h
new file mode 100644 (file)
index 0000000..0635a51
--- /dev/null
@@ -0,0 +1,482 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX HWPerf and Debug Types and Defines Header
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Common data types definitions for hardware performance API
+@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.
+*/ /**************************************************************************/
+#ifndef RGX_HWPERF_COMMON_H_
+#define RGX_HWPERF_COMMON_H_
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* These structures are used on both GPU and CPU and must be a size that is a
+ * multiple of 64 bits, 8 bytes to allow the FW to write 8 byte quantities at
+ * 8 byte aligned addresses. RGX_FW_STRUCT_*_ASSERT() is used to check this.
+ */
+
+/******************************************************************************
+ * Includes and Defines
+ *****************************************************************************/
+
+#include "img_types.h"
+#include "img_defs.h"
+
+#include "rgx_common_asserts.h"
+#include "pvrsrv_tlcommon.h"
+
+
+/******************************************************************************
+ * Packet Event Type Enumerations
+ *****************************************************************************/
+
+/*! Type used to encode the event that generated the packet.
+ * NOTE: When this type is updated the corresponding hwperfbin2json tool
+ * source needs to be updated as well. The RGX_HWPERF_EVENT_MASK_* macros will
+ * also need updating when adding new types.
+ *
+ * @par
+ * The event type values are incrementing integers for use as a shift ordinal
+ * in the event filtering process at the point events are generated.
+ * This scheme thus implies a limit of 63 event types.
+ */
+
+typedef IMG_UINT32 RGX_HWPERF_EVENT_TYPE;
+
+#define RGX_HWPERF_INVALID                             0x00U /*!< Invalid. Reserved value. */
+
+/*! FW types 0x01..0x06 */
+#define RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE   0x01U
+
+#define RGX_HWPERF_FW_BGSTART                  0x01U /*!< Background task processing start */
+#define RGX_HWPERF_FW_BGEND                            0x02U /*!< Background task end */
+#define RGX_HWPERF_FW_IRQSTART                 0x03U /*!< IRQ task processing start */
+
+#define RGX_HWPERF_FW_IRQEND                   0x04U /*!< IRQ task end */
+#define RGX_HWPERF_FW_DBGSTART                 0x05U /*!< Debug event start */
+#define RGX_HWPERF_FW_DBGEND                   0x06U /*!< Debug event end */
+
+#define RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE            0x06U
+
+/*! HW types 0x07..0x19 */
+#define RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE  0x07U
+
+#define RGX_HWPERF_HW_PMOOM_TAPAUSE            0x07U /*!< TA Pause at PM Out of Memory */
+
+#define RGX_HWPERF_HW_TAKICK                   0x08U /*!< TA task started */
+#define RGX_HWPERF_HW_TAFINISHED               0x09U /*!< TA task finished */
+#define RGX_HWPERF_HW_3DTQKICK                 0x0AU /*!< 3D TQ started */
+#define RGX_HWPERF_HW_3DKICK                   0x0BU /*!< 3D task started */
+#define RGX_HWPERF_HW_3DFINISHED               0x0CU /*!< 3D task finished */
+#define RGX_HWPERF_HW_CDMKICK                  0x0DU /*!< CDM task started */
+#define RGX_HWPERF_HW_CDMFINISHED              0x0EU /*!< CDM task finished */
+#define RGX_HWPERF_HW_TLAKICK                  0x0FU /*!< TLA task started */
+#define RGX_HWPERF_HW_TLAFINISHED              0x10U /*!< TLS task finished */
+#define RGX_HWPERF_HW_3DSPMKICK                        0x11U /*!< 3D SPM task started */
+#define RGX_HWPERF_HW_PERIODIC                 0x12U /*!< Periodic event with updated HW counters */
+#define RGX_HWPERF_HW_RTUKICK                  0x13U /*!< Reserved, future use */
+#define RGX_HWPERF_HW_RTUFINISHED              0x14U /*!< Reserved, future use */
+#define RGX_HWPERF_HW_SHGKICK                  0x15U /*!< Reserved, future use */
+#define RGX_HWPERF_HW_SHGFINISHED              0x16U /*!< Reserved, future use */
+#define RGX_HWPERF_HW_3DTQFINISHED             0x17U /*!< 3D TQ finished */
+#define RGX_HWPERF_HW_3DSPMFINISHED            0x18U /*!< 3D SPM task finished */
+
+#define RGX_HWPERF_HW_PMOOM_TARESUME   0x19U /*!< TA Resume after PM Out of Memory */
+
+/*! HW_EVENT_RANGE0 used up. Use next empty range below to add new hardware events */
+#define RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE   0x19U
+
+/*! other types 0x1A..0x1F */
+#define RGX_HWPERF_CLKS_CHG                            0x1AU /*!< Clock speed change in GPU */
+#define RGX_HWPERF_GPU_STATE_CHG               0x1BU /*!< GPU work state change */
+
+/*! power types 0x20..0x27 */
+#define RGX_HWPERF_PWR_EST_RANGE_FIRST_TYPE    0x20U
+#define RGX_HWPERF_PWR_EST_REQUEST             0x20U /*!< Power estimate requested (via GPIO) */
+#define RGX_HWPERF_PWR_EST_READY               0x21U /*!< Power estimate inputs ready */
+#define RGX_HWPERF_PWR_EST_RESULT              0x22U /*!< Power estimate result calculated */
+#define RGX_HWPERF_PWR_EST_RANGE_LAST_TYPE     0x22U
+
+#define RGX_HWPERF_PWR_CHG                             0x23U /*!< Power state change */
+
+/*! HW_EVENT_RANGE1 0x28..0x2F, for accommodating new hardware events */
+#define RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE  0x28U
+
+#define RGX_HWPERF_HW_TDMKICK                  0x28U /*!< TDM task started */
+#define RGX_HWPERF_HW_TDMFINISHED              0x29U /*!< TDM task finished */
+#define RGX_HWPERF_HW_NULLKICK                 0x2AU /*!< NULL event */
+
+#define RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE 0x2AU
+
+/*! context switch types 0x30..0x31 */
+#define RGX_HWPERF_CSW_START                   0x30U /*!< HW context store started */
+#define RGX_HWPERF_CSW_FINISHED                        0x31U /*!< HW context store finished */
+
+/*! DVFS events */
+#define RGX_HWPERF_DVFS                                        0x32U /*!< Dynamic voltage/frequency scaling events */
+
+/*! firmware misc 0x38..0x39 */
+#define RGX_HWPERF_UFO                                 0x38U /*!< FW UFO Check / Update */
+#define RGX_HWPERF_FWACT                               0x39U /*!< FW Activity notification */
+
+/*! last */
+#define RGX_HWPERF_LAST_TYPE                   0x3BU
+
+/*! This enumeration must have a value that is a power of two as it is
+ * used in masks and a filter bit field (currently 64 bits long).
+ */
+#define RGX_HWPERF_MAX_TYPE                            0x40U
+
+static_assert(RGX_HWPERF_LAST_TYPE < RGX_HWPERF_MAX_TYPE, "Too many HWPerf event types");
+
+/*! Macro used to check if an event type ID is present in the known set of hardware type events */
+#define HWPERF_PACKET_IS_HW_TYPE(_etype)       (((_etype) >= RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE) || \
+                                                                                        ((_etype) >= RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE))
+
+/*! Macro used to check if an event type ID is present in the known set of firmware type events */
+#define HWPERF_PACKET_IS_FW_TYPE(_etype)                                       \
+       ((_etype) >= RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE &&    \
+        (_etype) <= RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE)
+
+
+typedef enum {
+       RGX_HWPERF_HOST_INVALID   = 0x00,           /*!< Invalid, do not use. */
+       RGX_HWPERF_HOST_ENQ       = 0x01,           /*!< ``0x01`` Kernel driver has queued GPU work.
+                                                    See RGX_HWPERF_HOST_ENQ_DATA */
+       RGX_HWPERF_HOST_UFO       = 0x02,           /*!< ``0x02`` UFO updated by the driver.
+                                                    See RGX_HWPERF_HOST_UFO_DATA */
+       RGX_HWPERF_HOST_ALLOC     = 0x03,           /*!< ``0x03`` Resource allocated.
+                                                    See RGX_HWPERF_HOST_ALLOC_DATA */
+       RGX_HWPERF_HOST_CLK_SYNC  = 0x04,           /*!< ``0x04`` GPU / Host clocks correlation data.
+                                                    See RGX_HWPERF_HOST_CLK_SYNC_DATA */
+       RGX_HWPERF_HOST_FREE      = 0x05,           /*!< ``0x05`` Resource freed,
+                                                    See RGX_HWPERF_HOST_FREE_DATA */
+       RGX_HWPERF_HOST_MODIFY    = 0x06,           /*!< ``0x06`` Resource modified / updated.
+                                                    See RGX_HWPERF_HOST_MODIFY_DATA */
+       RGX_HWPERF_HOST_DEV_INFO  = 0x07,           /*!< ``0x07`` Device Health status.
+                                                    See RGX_HWPERF_HOST_DEV_INFO_DATA */
+       RGX_HWPERF_HOST_INFO      = 0x08,           /*!< ``0x08`` Device memory usage information.
+                                                    See RGX_HWPERF_HOST_INFO_DATA */
+       RGX_HWPERF_HOST_SYNC_FENCE_WAIT = 0x09,     /*!< ``0x09`` Wait for sync event.
+                                                    See RGX_HWPERF_HOST_SYNC_FENCE_WAIT_DATA */
+       RGX_HWPERF_HOST_SYNC_SW_TL_ADVANCE  = 0x0A, /*!< ``0x0A`` Software timeline advanced.
+                                                    See RGX_HWPERF_HOST_SYNC_SW_TL_ADV_DATA */
+       RGX_HWPERF_HOST_CLIENT_INFO = 0x0B,                     /*!< ``0x0B`` Additional client info.
+                                                    See RGX_HWPERF_HOST_CLIENT_INFO_DATA */
+
+       /*! last */
+       RGX_HWPERF_HOST_LAST_TYPE,
+
+       /*! This enumeration must have a value that is a power of two as it is
+        * used in masks and a filter bit field (currently 32 bits long).
+        */
+       RGX_HWPERF_HOST_MAX_TYPE  = 0x20
+} RGX_HWPERF_HOST_EVENT_TYPE;
+
+/*!< The event type values are incrementing integers for use as a shift ordinal
+ * in the event filtering process at the point events are generated.
+ * This scheme thus implies a limit of 31 event types.
+ */
+static_assert(RGX_HWPERF_HOST_LAST_TYPE < RGX_HWPERF_HOST_MAX_TYPE, "Too many HWPerf host event types");
+
+
+/******************************************************************************
+ * Packet Header Format Version 2 Types
+ *****************************************************************************/
+
+/*! Major version number of the protocol in operation
+ */
+#define RGX_HWPERF_V2_FORMAT 2
+
+/*! Signature ASCII pattern 'HWP2' found in the first word of a HWPerfV2 packet
+ */
+#define HWPERF_PACKET_V2_SIG           0x48575032
+
+/*! Signature ASCII pattern 'HWPA' found in the first word of a HWPerfV2a packet
+ */
+#define HWPERF_PACKET_V2A_SIG          0x48575041
+
+/*! Signature ASCII pattern 'HWPB' found in the first word of a HWPerfV2b packet
+ */
+#define HWPERF_PACKET_V2B_SIG          0x48575042
+
+/*! Signature ASCII pattern 'HWPC' found in the first word of a HWPerfV2c packet
+ */
+#define HWPERF_PACKET_V2C_SIG          0x48575043
+
+#define HWPERF_PACKET_ISVALID(_val) (((_val) == HWPERF_PACKET_V2_SIG) || ((_val) == HWPERF_PACKET_V2A_SIG) || ((_val) == HWPERF_PACKET_V2B_SIG) || ((_val) == HWPERF_PACKET_V2C_SIG))
+/*!< Checks that the packet signature is one of the supported versions */
+
+/*! Type defines the HWPerf packet header common to all events. */
+typedef struct
+{
+       IMG_UINT32  ui32Sig;        /*!< Always the value HWPERF_PACKET_SIG */
+       IMG_UINT32  ui32Size;       /*!< Overall packet size in bytes */
+       IMG_UINT32  eTypeId;        /*!< Event type information field */
+       IMG_UINT32  ui32Ordinal;    /*!< Sequential number of the packet */
+       IMG_UINT64  ui64Timestamp;  /*!< Event timestamp */
+} RGX_HWPERF_V2_PACKET_HDR, *RGX_PHWPERF_V2_PACKET_HDR;
+
+RGX_FW_STRUCT_OFFSET_ASSERT(RGX_HWPERF_V2_PACKET_HDR, ui64Timestamp);
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_V2_PACKET_HDR);
+
+
+/*! Mask for use with the IMG_UINT32 ui32Size header field */
+#define RGX_HWPERF_SIZE_MASK         0xFFFFU
+
+/*! This macro defines an upper limit to which the size of the largest variable
+ * length HWPerf packet must fall within, currently 3KB. This constant may be
+ * used to allocate a buffer to hold one packet.
+ * This upper limit is policed by packet producing code.
+ */
+#define RGX_HWPERF_MAX_PACKET_SIZE   0xC00U
+
+/*! Defines an upper limit to the size of a variable length packet payload.
+ */
+#define RGX_HWPERF_MAX_PAYLOAD_SIZE     ((IMG_UINT32)(RGX_HWPERF_MAX_PACKET_SIZE-\
+       sizeof(RGX_HWPERF_V2_PACKET_HDR)))
+
+/*! Macro which takes a structure name and provides the packet size for
+ * a fixed size payload packet, rounded up to 8 bytes to align packets
+ * for 64 bit architectures. */
+#define RGX_HWPERF_MAKE_SIZE_FIXED(_struct)       ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(sizeof(_struct), PVRSRVTL_PACKET_ALIGNMENT))))
+
+/*! Macro which takes the number of bytes written in the data payload of a
+ * packet for a variable size payload packet, rounded up to 8 bytes to
+ * align packets for 64 bit architectures. */
+#define RGX_HWPERF_MAKE_SIZE_VARIABLE(_size)      ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&((IMG_UINT32)sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN((_size), PVRSRVTL_PACKET_ALIGNMENT))))
+
+/*! Macro to obtain the size of the packet */
+#define RGX_HWPERF_GET_SIZE(_packet_addr)         ((IMG_UINT16)(((_packet_addr)->ui32Size) & RGX_HWPERF_SIZE_MASK))
+
+/*! Macro to obtain the size of the packet data */
+#define RGX_HWPERF_GET_DATA_SIZE(_packet_addr)    (RGX_HWPERF_GET_SIZE(_packet_addr) - sizeof(RGX_HWPERF_V2_PACKET_HDR))
+
+/*! Masks for use with the IMG_UINT32 eTypeId header field */
+#define RGX_HWPERF_TYPEID_MASK                 0x0007FFFFU
+#define RGX_HWPERF_TYPEID_EVENT_MASK   0x00007FFFU
+#define RGX_HWPERF_TYPEID_THREAD_MASK  0x00008000U
+#define RGX_HWPERF_TYPEID_STREAM_MASK  0x00070000U
+#define RGX_HWPERF_TYPEID_META_DMA_MASK        0x00080000U
+#define RGX_HWPERF_TYPEID_M_CORE_MASK  0x00100000U
+#define RGX_HWPERF_TYPEID_OSID_MASK            0x07000000U
+
+/*! Meta thread macros for encoding the ID into the type field of a packet */
+#define RGX_HWPERF_META_THREAD_SHIFT   15U
+#define RGX_HWPERF_META_THREAD_ID0             0x0U  /*!< Meta Thread 0 ID */
+#define RGX_HWPERF_META_THREAD_ID1             0x1U  /*!< Meta Thread 1 ID */
+/*! Obsolete, kept for source compatibility */
+#define RGX_HWPERF_META_THREAD_MASK            0x1U
+/*! Stream ID macros for encoding the ID into the type field of a packet */
+#define RGX_HWPERF_STREAM_SHIFT                        16U
+/*! Meta DMA macro for encoding how the packet was generated into the type field of a packet */
+#define RGX_HWPERF_META_DMA_SHIFT              19U
+/*! Bit-shift macro used for encoding multi-core data into the type field of a packet */
+#define RGX_HWPERF_M_CORE_SHIFT                        20U
+/*! OSID bit-shift macro used for encoding OSID into type field of a packet */
+#define RGX_HWPERF_OSID_SHIFT                  24U
+typedef enum {
+       RGX_HWPERF_STREAM_ID0_FW,     /*!< Events from the Firmware/GPU */
+       RGX_HWPERF_STREAM_ID1_HOST,   /*!< Events from the Server host driver component */
+       RGX_HWPERF_STREAM_ID2_CLIENT, /*!< Events from the Client host driver component */
+       RGX_HWPERF_STREAM_ID_LAST,
+} RGX_HWPERF_STREAM_ID;
+
+/* Checks if all stream IDs can fit under RGX_HWPERF_TYPEID_STREAM_MASK. */
+static_assert(((IMG_UINT32)RGX_HWPERF_STREAM_ID_LAST - 1U) < (RGX_HWPERF_TYPEID_STREAM_MASK >> RGX_HWPERF_STREAM_SHIFT),
+               "Too many HWPerf stream IDs.");
+
+/*! Compile-time value used to seed the Multi-Core (MC) bit in the typeID field.
+ *  Only set by RGX_FIRMWARE builds.
+ */
+#if defined(RGX_FIRMWARE)
+# if defined(RGX_FEATURE_GPU_MULTICORE_SUPPORT)
+#define RGX_HWPERF_M_CORE_VALUE 1U  /*!< 1 => Multi-core supported */
+# else
+#define RGX_HWPERF_M_CORE_VALUE 0U  /*!< 0 => Multi-core not supported */
+# endif
+#else
+#define RGX_HWPERF_M_CORE_VALUE 0U  /*!< 0 => Multi-core not supported */
+#endif
+
+/*! Macros used to set the packet type and encode meta thread ID (0|1),
+ * HWPerf stream ID, multi-core capability and OSID within the typeID */
+#define RGX_HWPERF_MAKE_TYPEID(_stream, _type, _thread, _metadma, _osid)\
+               ((IMG_UINT32) ((RGX_HWPERF_TYPEID_STREAM_MASK&((IMG_UINT32)(_stream) << RGX_HWPERF_STREAM_SHIFT)) | \
+               (RGX_HWPERF_TYPEID_THREAD_MASK & ((IMG_UINT32)(_thread) << RGX_HWPERF_META_THREAD_SHIFT)) | \
+               (RGX_HWPERF_TYPEID_EVENT_MASK & (IMG_UINT32)(_type)) | \
+               (RGX_HWPERF_TYPEID_META_DMA_MASK & ((IMG_UINT32)(_metadma) << RGX_HWPERF_META_DMA_SHIFT)) | \
+               (RGX_HWPERF_TYPEID_OSID_MASK & ((IMG_UINT32)(_osid) << RGX_HWPERF_OSID_SHIFT)) | \
+               (RGX_HWPERF_TYPEID_M_CORE_MASK & ((IMG_UINT32)(RGX_HWPERF_M_CORE_VALUE) << RGX_HWPERF_M_CORE_SHIFT))))
+
+/*! Obtains the event type that generated the packet */
+#define RGX_HWPERF_GET_TYPE(_packet_addr)            (((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_EVENT_MASK)
+
+/*! Obtains the META Thread number that generated the packet */
+#define RGX_HWPERF_GET_THREAD_ID(_packet_addr)       (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_THREAD_MASK) >> RGX_HWPERF_META_THREAD_SHIFT))
+
+/*! Determines if the packet generated contains multi-core data */
+#define RGX_HWPERF_GET_M_CORE(_packet_addr)          (((_packet_addr)->eTypeId & RGX_HWPERF_TYPEID_M_CORE_MASK) >> RGX_HWPERF_M_CORE_SHIFT)
+
+/*! Obtains the guest OSID which resulted in packet generation */
+#define RGX_HWPERF_GET_OSID(_packet_addr)            (((_packet_addr)->eTypeId & RGX_HWPERF_TYPEID_OSID_MASK) >> RGX_HWPERF_OSID_SHIFT)
+
+/*! Obtain stream id */
+#define RGX_HWPERF_GET_STREAM_ID(_packet_addr)       (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_STREAM_MASK) >> RGX_HWPERF_STREAM_SHIFT))
+
+/*! Obtain information about how the packet was generated, which might affect payload total size */
+#define RGX_HWPERF_GET_META_DMA_INFO(_packet_addr)   (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_META_DMA_MASK) >> RGX_HWPERF_META_DMA_SHIFT))
+
+/*! Obtains a typed pointer to a packet given a buffer address */
+#define RGX_HWPERF_GET_PACKET(_buffer_addr)            ((RGX_HWPERF_V2_PACKET_HDR *)(void *)  (_buffer_addr))
+/*! Obtains a typed pointer to a data structure given a packet address */
+#define RGX_HWPERF_GET_PACKET_DATA_BYTES(_packet_addr) (IMG_OFFSET_ADDR((_packet_addr), sizeof(RGX_HWPERF_V2_PACKET_HDR)))
+/*! Obtains a typed pointer to the next packet given a packet address */
+#define RGX_HWPERF_GET_NEXT_PACKET(_packet_addr)       ((RGX_HWPERF_V2_PACKET_HDR *)  (IMG_OFFSET_ADDR((_packet_addr), RGX_HWPERF_SIZE_MASK&((_packet_addr)->ui32Size))))
+
+/*! Obtains a typed pointer to a packet header given the packet data address */
+#define RGX_HWPERF_GET_PACKET_HEADER(_packet_addr)     ((RGX_HWPERF_V2_PACKET_HDR *)  (IMG_OFFSET_ADDR((_packet_addr), -(IMG_INT32)sizeof(RGX_HWPERF_V2_PACKET_HDR))))
+
+
+/******************************************************************************
+ * Other Common Defines
+ *****************************************************************************/
+
+/*! This macro is not a real array size, but indicates the array has a variable
+ * length only known at run-time but always contains at least 1 element. The
+ * final size of the array is deduced from the size field of a packet header.
+ */
+#define RGX_HWPERF_ONE_OR_MORE_ELEMENTS  1U
+
+/*! This macro is not a real array size, but indicates the array is optional
+ * and if present has a variable length only known at run-time. The final
+ * size of the array is deduced from the size field of a packet header. */
+#define RGX_HWPERF_ZERO_OR_MORE_ELEMENTS 1U
+
+
+/*! Masks for use with the IMG_UINT32 ui32BlkInfo field */
+#define RGX_HWPERF_BLKINFO_BLKCOUNT_MASK       0xFFFF0000U
+#define RGX_HWPERF_BLKINFO_BLKOFFSET_MASK      0x0000FFFFU
+
+/*! Shift for the NumBlocks and counter block offset field in ui32BlkInfo */
+#define RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT      16U
+#define RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT 0U
+
+/*! Macro used to set the block info word as a combination of two 16-bit integers */
+#define RGX_HWPERF_MAKE_BLKINFO(_numblks, _blkoffset) ((IMG_UINT32) ((RGX_HWPERF_BLKINFO_BLKCOUNT_MASK&((_numblks) << RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT)) | (RGX_HWPERF_BLKINFO_BLKOFFSET_MASK&((_blkoffset) << RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT))))
+
+/*! Macro used to obtain the number of counter blocks present in the packet */
+#define RGX_HWPERF_GET_BLKCOUNT(_blkinfo)            (((_blkinfo) & RGX_HWPERF_BLKINFO_BLKCOUNT_MASK) >> RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT)
+
+/*! Obtains the offset of the counter block stream in the packet */
+#define RGX_HWPERF_GET_BLKOFFSET(_blkinfo)           (((_blkinfo) & RGX_HWPERF_BLKINFO_BLKOFFSET_MASK) >> RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT)
+
+/*! This macro gets the number of blocks depending on the packet version */
+#define RGX_HWPERF_GET_NUMBLKS(_sig, _packet_data, _numblocks) \
+       do { \
+               if (HWPERF_PACKET_V2B_SIG == (_sig) || HWPERF_PACKET_V2C_SIG == (_sig)) \
+               { \
+                       (_numblocks) = RGX_HWPERF_GET_BLKCOUNT((_packet_data)->ui32BlkInfo);\
+               } \
+               else \
+               { \
+                       IMG_UINT32 ui32VersionOffset = (((_sig) == HWPERF_PACKET_V2_SIG) ? 1 : 3);\
+                       (_numblocks) = *(IMG_UINT16 *)(IMG_OFFSET_ADDR(&(_packet_data)->ui32WorkTarget, ui32VersionOffset)); \
+               } \
+       } while (0)
+
+/*! This macro gets the counter stream pointer depending on the packet version */
+#define RGX_HWPERF_GET_CNTSTRM(_sig, _hw_packet_data, _cntstream_ptr) \
+{ \
+       if (HWPERF_PACKET_V2B_SIG == (_sig) || HWPERF_PACKET_V2C_SIG == (_sig)) \
+       { \
+               (_cntstream_ptr) = (IMG_UINT32 *)(IMG_OFFSET_ADDR((_hw_packet_data), RGX_HWPERF_GET_BLKOFFSET((_hw_packet_data)->ui32BlkInfo))); \
+       } \
+       else \
+       { \
+               IMG_UINT32 ui32BlkStreamOffsetInWords = (((_sig) == HWPERF_PACKET_V2_SIG) ? 6 : 8); \
+               (_cntstream_ptr) = (IMG_UINT32 *)(IMG_OFFSET_ADDR_DW((_hw_packet_data), ui32BlkStreamOffsetInWords)); \
+       } \
+}
+
+/*! Masks for use with the IMG_UINT32 ui32KickInfo field */
+#define RGX_HWPERF_KICKINFO_KICKID_MASK        0x000000FFU
+
+/*! Shift for the Kick ID field in ui32KickInfo */
+#define RGX_HWPERF_KICKINFO_KICKID_SHIFT 0U
+
+/*! Macro used to set the kick info field. */
+#define RGX_HWPERF_MAKE_KICKINFO(_kickid) ((IMG_UINT32) (RGX_HWPERF_KICKINFO_KICKID_MASK&((_kickid) << RGX_HWPERF_KICKINFO_KICKID_SHIFT)))
+
+/*! Macro used to obtain the Kick ID if present in the packet */
+#define RGX_HWPERF_GET_KICKID(_kickinfo)            (((_kickinfo) & RGX_HWPERF_KICKINFO_KICKID_MASK) >> RGX_HWPERF_KICKINFO_KICKID_SHIFT)
+
+/*! Masks for use with the RGX_HWPERF_UFO_EV eEvType field */
+#define RGX_HWPERF_UFO_STREAMSIZE_MASK 0xFFFF0000U
+#define RGX_HWPERF_UFO_STREAMOFFSET_MASK 0x0000FFFFU
+
+/*! Shift for the UFO count and data stream fields */
+#define RGX_HWPERF_UFO_STREAMSIZE_SHIFT 16U
+#define RGX_HWPERF_UFO_STREAMOFFSET_SHIFT 0U
+
+/*! Macro used to set UFO stream info word as a combination of two 16-bit integers */
+#define RGX_HWPERF_MAKE_UFOPKTINFO(_ssize, _soff) \
+        ((IMG_UINT32) ((RGX_HWPERF_UFO_STREAMSIZE_MASK&((_ssize) << RGX_HWPERF_UFO_STREAMSIZE_SHIFT)) | \
+        (RGX_HWPERF_UFO_STREAMOFFSET_MASK&((_soff) << RGX_HWPERF_UFO_STREAMOFFSET_SHIFT))))
+
+/*! Macro used to obtain UFO count*/
+#define RGX_HWPERF_GET_UFO_STREAMSIZE(_streaminfo) \
+        (((_streaminfo) & RGX_HWPERF_UFO_STREAMSIZE_MASK) >> RGX_HWPERF_UFO_STREAMSIZE_SHIFT)
+
+/*! Obtains the offset of the UFO stream in the packet */
+#define RGX_HWPERF_GET_UFO_STREAMOFFSET(_streaminfo) \
+        (((_streaminfo) & RGX_HWPERF_UFO_STREAMOFFSET_MASK) >> RGX_HWPERF_UFO_STREAMOFFSET_SHIFT)
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* RGX_HWPERF_COMMON_H_ */
+
+/******************************************************************************
+ End of file
+******************************************************************************/
index 6072700..bdff11f 100644 (file)
@@ -49,7 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 
 #include "img_defs.h"
-#include "rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 
 
 /******************************************************************************
@@ -74,7 +74,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define META_CR_PERF_COUNT_THR_SHIFT                   (24)
 #define META_CR_PERF_COUNT_THR_MASK                            (0x0F000000)
 #define META_CR_PERF_COUNT_THR_0                               (IMG_UINT32_C(0x1) << META_CR_PERF_COUNT_THR_SHIFT)
-#define META_CR_PERF_COUNT_THR_1                               (IMG_UINT32_C(0x2) << META_CR_PERF_COUNT_THR_1)
+#define META_CR_PERF_COUNT_THR_1                               (IMG_UINT32_C(0x2) << META_CR_PERF_COUNT_THR_SHIFT)
 
 #define META_CR_TxVECINT_BHALT                                 (0x04820500)
 #define META_CR_PERF_ICORE0                                            (0x0480FFD0)
@@ -248,11 +248,11 @@ typedef struct
  * The interface has been kept the same to simplify the code changes.
  * The bifdm argument is ignored (no longer relevant) in S7 and volcanic.
  */
-#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(pers, slc_policy, mmu_ctx)      ((((IMG_UINT64) ((pers)    & 0x3))  << 52) | \
-                                                                           (((IMG_UINT64) ((mmu_ctx) & 0xFF)) << 44) | \
-                                                                           (((IMG_UINT64) ((slc_policy) & 0x1))  << 40))
-#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_CACHED(mmu_ctx)      RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(0x3, 0x0, mmu_ctx)
-#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_UNCACHED(mmu_ctx)    RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(0x0, 0x1, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(pers, slc_policy, mmu_ctx)      ((((IMG_UINT64) ((pers)    & 0x3U))  << 52) | \
+                                                                           (((IMG_UINT64) ((mmu_ctx) & 0xFFU)) << 44) | \
+                                                                           (((IMG_UINT64) ((slc_policy) & 0x1U))  << 40))
+#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_CACHED(mmu_ctx)      RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(0x3U, 0x0U, mmu_ctx)
+#define RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_UNCACHED(mmu_ctx)    RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC(0x0U, 0x1U, mmu_ctx)
 
 /* To configure the Page Catalog and BIF-DM fed into the BIF for Garten
  * accesses through this segment
index 4c35851..c2f3818 100644 (file)
@@ -72,7 +72,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* Total number of TLB entries */
 #define RGXMIPSFW_NUMBER_OF_TLB_ENTRIES          (16)
 /* "Uncached" caching policy */
-#define RGXMIPSFW_UNCACHED_CACHE_POLICY          (0X00000002)
+#define RGXMIPSFW_UNCACHED_CACHE_POLICY          (0X00000002U)
 /* "Write-back write-allocate" caching policy */
 #define RGXMIPSFW_WRITEBACK_CACHE_POLICY         (0X00000003)
 /* "Write-through no write-allocate" caching policy */
@@ -91,11 +91,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define RGXMIPSFW_ENTRYLO_READ_INHIBIT_SHIFT     (31U)
 #define RGXMIPSFW_ENTRYLO_READ_INHIBIT_CLRMSK    (0X7FFFFFFF)
-#define RGXMIPSFW_ENTRYLO_READ_INHIBIT_EN        (0X80000000)
+#define RGXMIPSFW_ENTRYLO_READ_INHIBIT_EN        (0X80000000U)
 
 #define RGXMIPSFW_ENTRYLO_EXEC_INHIBIT_SHIFT     (30U)
 #define RGXMIPSFW_ENTRYLO_EXEC_INHIBIT_CLRMSK    (0XBFFFFFFF)
-#define RGXMIPSFW_ENTRYLO_EXEC_INHIBIT_EN        (0X40000000)
+#define RGXMIPSFW_ENTRYLO_EXEC_INHIBIT_EN        (0X40000000U)
 
 /* Page Frame Number */
 #define RGXMIPSFW_ENTRYLO_PFN_SHIFT              (6)
@@ -104,25 +104,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGXMIPSFW_ENTRYLO_PFN_MASK               (0x03FFFFC0)
 #define RGXMIPSFW_ENTRYLO_PFN_SIZE               (20)
 /* Mask used for the MIPS Page Table in case of physical bus on more than 32 bit */
-#define RGXMIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT   (0x3FFFFFC0)
+#define RGXMIPSFW_ENTRYLO_PFN_MASK_ABOVE_32BIT   (0x3FFFFFC0U)
 #define RGXMIPSFW_ENTRYLO_PFN_SIZE_ABOVE_32BIT   (24)
 #define RGXMIPSFW_ADDR_TO_ENTRYLO_PFN_RSHIFT     (RGXMIPSFW_ENTRYLO_PFN_ALIGNSHIFT - \
                                                   RGXMIPSFW_ENTRYLO_PFN_SHIFT)
 
 #define RGXMIPSFW_ENTRYLO_CACHE_POLICY_SHIFT     (3U)
-#define RGXMIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK    (0XFFFFFFC7)
+#define RGXMIPSFW_ENTRYLO_CACHE_POLICY_CLRMSK    (0XFFFFFFC7U)
 
 #define RGXMIPSFW_ENTRYLO_DIRTY_SHIFT            (2U)
 #define RGXMIPSFW_ENTRYLO_DIRTY_CLRMSK           (0XFFFFFFFB)
-#define RGXMIPSFW_ENTRYLO_DIRTY_EN               (0X00000004)
+#define RGXMIPSFW_ENTRYLO_DIRTY_EN               (0X00000004U)
 
 #define RGXMIPSFW_ENTRYLO_VALID_SHIFT            (1U)
 #define RGXMIPSFW_ENTRYLO_VALID_CLRMSK           (0XFFFFFFFD)
-#define RGXMIPSFW_ENTRYLO_VALID_EN               (0X00000002)
+#define RGXMIPSFW_ENTRYLO_VALID_EN               (0X00000002U)
 
 #define RGXMIPSFW_ENTRYLO_GLOBAL_SHIFT           (0U)
 #define RGXMIPSFW_ENTRYLO_GLOBAL_CLRMSK          (0XFFFFFFFE)
-#define RGXMIPSFW_ENTRYLO_GLOBAL_EN              (0X00000001)
+#define RGXMIPSFW_ENTRYLO_GLOBAL_EN              (0X00000001U)
 
 #define RGXMIPSFW_ENTRYLO_DVG                    (RGXMIPSFW_ENTRYLO_DIRTY_EN | \
                                                   RGXMIPSFW_ENTRYLO_VALID_EN | \
@@ -158,14 +158,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #define RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES       (2)
-#define RGXMIPSFW_TRAMPOLINE_NUMPAGES            (1 << RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
+#define RGXMIPSFW_TRAMPOLINE_NUMPAGES            (1U << RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES)
 #define RGXMIPSFW_TRAMPOLINE_SIZE                (RGXMIPSFW_TRAMPOLINE_NUMPAGES << RGXMIPSFW_LOG2_PAGE_SIZE_4K)
 #define RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE   (RGXMIPSFW_TRAMPOLINE_LOG2_NUMPAGES + RGXMIPSFW_LOG2_PAGE_SIZE_4K)
 
 #define RGXMIPSFW_TRAMPOLINE_TARGET_PHYS_ADDR    (RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
 #define RGXMIPSFW_TRAMPOLINE_OFFSET(a)           (a - RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN)
 
-#define RGXMIPSFW_SENSITIVE_ADDR(a)              (RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN == (~((1<<RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE)-1) & a))
+#define RGXMIPSFW_SENSITIVE_ADDR(a)              (RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN == (~((1UL << RGXMIPSFW_TRAMPOLINE_LOG2_SEGMENT_SIZE)-1U) & a))
 
 /*
  * Firmware virtual layout and remap configuration
@@ -183,20 +183,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* Boot remap setup */
 #define RGXMIPSFW_BOOT_REMAP_VIRTUAL_BASE        (0xBFC00000)
-#define RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN        (0x1FC00000)
+#define RGXMIPSFW_BOOT_REMAP_PHYS_ADDR_IN        (0x1FC00000U)
 #define RGXMIPSFW_BOOT_REMAP_LOG2_SEGMENT_SIZE   (12)
 #define RGXMIPSFW_BOOT_NMI_CODE_VIRTUAL_BASE     (RGXMIPSFW_BOOT_REMAP_VIRTUAL_BASE)
 
 /* Data remap setup */
 #define RGXMIPSFW_DATA_REMAP_VIRTUAL_BASE        (0xBFC01000)
 #define RGXMIPSFW_DATA_CACHED_REMAP_VIRTUAL_BASE (0x9FC01000)
-#define RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN        (0x1FC01000)
+#define RGXMIPSFW_DATA_REMAP_PHYS_ADDR_IN        (0x1FC01000U)
 #define RGXMIPSFW_DATA_REMAP_LOG2_SEGMENT_SIZE   (12)
 #define RGXMIPSFW_BOOT_NMI_DATA_VIRTUAL_BASE     (RGXMIPSFW_DATA_REMAP_VIRTUAL_BASE)
 
 /* Code remap setup */
 #define RGXMIPSFW_CODE_REMAP_VIRTUAL_BASE        (0x9FC02000)
-#define RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN        (0x1FC02000)
+#define RGXMIPSFW_CODE_REMAP_PHYS_ADDR_IN        (0x1FC02000U)
 #define RGXMIPSFW_CODE_REMAP_LOG2_SEGMENT_SIZE   (12)
 #define RGXMIPSFW_EXCEPTIONS_VIRTUAL_BASE        (RGXMIPSFW_CODE_REMAP_VIRTUAL_BASE)
 
@@ -211,7 +211,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 /* Bootloader configuration offset (where RGXMIPSFW_BOOT_DATA lives)
  * within the bootloader/NMI data page */
-#define RGXMIPSFW_BOOTLDR_CONF_OFFSET                         (0x0)
+#define RGXMIPSFW_BOOTLDR_CONF_OFFSET                         (0x0U)
 
 
 /*
@@ -241,7 +241,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* The things that follow are excluded when compiling assembly sources */
 #if !defined(RGXMIPSFW_ASSEMBLY_CODE)
 #include "img_types.h"
-#include "rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 
 typedef struct
 {
@@ -292,40 +292,40 @@ typedef struct
 #define RGXMIPSFW_C0_NBHWIRQ   8
 
 /* Macros to decode C0_Cause register */
-#define RGXMIPSFW_C0_CAUSE_EXCCODE(CAUSE)       (((CAUSE) & 0x7c) >> 2)
+#define RGXMIPSFW_C0_CAUSE_EXCCODE(CAUSE)       (((CAUSE) & 0x7cU) >> 2U)
 #define RGXMIPSFW_C0_CAUSE_EXCCODE_FWERROR      9
 /* Use only when Coprocessor Unusable exception */
-#define RGXMIPSFW_C0_CAUSE_UNUSABLE_UNIT(CAUSE) (((CAUSE) >> 28) & 0x3)
+#define RGXMIPSFW_C0_CAUSE_UNUSABLE_UNIT(CAUSE) (((CAUSE) >> 28U) & 0x3U)
 #define RGXMIPSFW_C0_CAUSE_PENDING_HWIRQ(CAUSE) (((CAUSE) & 0x3fc00) >> 10)
-#define RGXMIPSFW_C0_CAUSE_FDCIPENDING          (1 << 21)
-#define RGXMIPSFW_C0_CAUSE_IV                   (1 << 23)
-#define RGXMIPSFW_C0_CAUSE_IC                   (1 << 25)
-#define RGXMIPSFW_C0_CAUSE_PCIPENDING           (1 << 26)
-#define RGXMIPSFW_C0_CAUSE_TIPENDING            (1 << 30)
-#define RGXMIPSFW_C0_CAUSE_BRANCH_DELAY         (1 << 31)
+#define RGXMIPSFW_C0_CAUSE_FDCIPENDING          (1UL << 21)
+#define RGXMIPSFW_C0_CAUSE_IV                   (1UL << 23)
+#define RGXMIPSFW_C0_CAUSE_IC                   (1UL << 25)
+#define RGXMIPSFW_C0_CAUSE_PCIPENDING           (1UL << 26)
+#define RGXMIPSFW_C0_CAUSE_TIPENDING            (1UL << 30)
+#define RGXMIPSFW_C0_CAUSE_BRANCH_DELAY         (1UL << 31)
 
 /* Macros to decode C0_Debug register */
-#define RGXMIPSFW_C0_DEBUG_EXCCODE(DEBUG) (((DEBUG) >> 10) & 0x1f)
-#define RGXMIPSFW_C0_DEBUG_DSS            (1 << 0)
-#define RGXMIPSFW_C0_DEBUG_DBP            (1 << 1)
-#define RGXMIPSFW_C0_DEBUG_DDBL           (1 << 2)
-#define RGXMIPSFW_C0_DEBUG_DDBS           (1 << 3)
-#define RGXMIPSFW_C0_DEBUG_DIB            (1 << 4)
-#define RGXMIPSFW_C0_DEBUG_DINT           (1 << 5)
-#define RGXMIPSFW_C0_DEBUG_DIBIMPR        (1 << 6)
-#define RGXMIPSFW_C0_DEBUG_DDBLIMPR       (1 << 18)
-#define RGXMIPSFW_C0_DEBUG_DDBSIMPR       (1 << 19)
-#define RGXMIPSFW_C0_DEBUG_IEXI           (1 << 20)
-#define RGXMIPSFW_C0_DEBUG_DBUSEP         (1 << 21)
-#define RGXMIPSFW_C0_DEBUG_CACHEEP        (1 << 22)
-#define RGXMIPSFW_C0_DEBUG_MCHECKP        (1 << 23)
-#define RGXMIPSFW_C0_DEBUG_IBUSEP         (1 << 24)
-#define RGXMIPSFW_C0_DEBUG_DM             (1 << 30)
-#define RGXMIPSFW_C0_DEBUG_DBD            (1 << 31)
+#define RGXMIPSFW_C0_DEBUG_EXCCODE(DEBUG) (((DEBUG) >> 10U) & 0x1fU)
+#define RGXMIPSFW_C0_DEBUG_DSS            (1UL << 0)
+#define RGXMIPSFW_C0_DEBUG_DBP            (1UL << 1)
+#define RGXMIPSFW_C0_DEBUG_DDBL           (1UL << 2)
+#define RGXMIPSFW_C0_DEBUG_DDBS           (1UL << 3)
+#define RGXMIPSFW_C0_DEBUG_DIB            (1UL << 4)
+#define RGXMIPSFW_C0_DEBUG_DINT           (1UL << 5)
+#define RGXMIPSFW_C0_DEBUG_DIBIMPR        (1UL << 6)
+#define RGXMIPSFW_C0_DEBUG_DDBLIMPR       (1UL << 18)
+#define RGXMIPSFW_C0_DEBUG_DDBSIMPR       (1UL << 19)
+#define RGXMIPSFW_C0_DEBUG_IEXI           (1UL << 20)
+#define RGXMIPSFW_C0_DEBUG_DBUSEP         (1UL << 21)
+#define RGXMIPSFW_C0_DEBUG_CACHEEP        (1UL << 22)
+#define RGXMIPSFW_C0_DEBUG_MCHECKP        (1UL << 23)
+#define RGXMIPSFW_C0_DEBUG_IBUSEP         (1UL << 24)
+#define RGXMIPSFW_C0_DEBUG_DM             (1UL << 30)
+#define RGXMIPSFW_C0_DEBUG_DBD            (1UL << 31)
 
 /* Macros to decode TLB entries */
 #define RGXMIPSFW_TLB_GET_MASK(PAGE_MASK)       (((PAGE_MASK) >> 13) & 0XFFFFU)
-#define RGXMIPSFW_TLB_GET_PAGE_SIZE(PAGE_MASK)  ((((PAGE_MASK) | 0x1FFF) + 1) >> 11) /* page size in KB */
+#define RGXMIPSFW_TLB_GET_PAGE_SIZE(PAGE_MASK)  ((((PAGE_MASK) | 0x1FFFU) + 1U) >> 11U) /* page size in KB */
 #define RGXMIPSFW_TLB_GET_PAGE_MASK(PAGE_SIZE)  ((((PAGE_SIZE) << 11) - 1) & ~0x7FF) /* page size in KB */
 #define RGXMIPSFW_TLB_GET_VPN2(ENTRY_HI)        ((ENTRY_HI) >> 13)
 #define RGXMIPSFW_TLB_GET_COHERENCY(ENTRY_LO)   (((ENTRY_LO) >> 3) & 0x7U)
index e6e57aa..e5be2a5 100644 (file)
@@ -45,7 +45,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #if !defined(RGX_RISCV_H)
 #define RGX_RISCV_H
 
-#include "rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 
 
 /* Utility defines to convert regions to virtual addresses and remaps */
@@ -76,14 +76,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGXRISCVFW_COREMEM_REGION               IMG_UINT32_C(0x8)
 #define RGXRISCVFW_COREMEM_MAX_SIZE             IMG_UINT32_C(0x10000000) /* 256 MB */
 #define RGXRISCVFW_COREMEM_BASE                 (RGXRISCVFW_GET_REGION_BASE(RGXRISCVFW_COREMEM_REGION))
-#define RGXRISCVFW_COREMEM_END                  (RGXRISCVFW_COREMEM_BASE + RGXRISCVFW_COREMEM_MAX_SIZE - 1)
+#define RGXRISCVFW_COREMEM_END                  (RGXRISCVFW_COREMEM_BASE + RGXRISCVFW_COREMEM_MAX_SIZE - 1U)
 
 
 /*
  * Host-FW shared data defines
  */
-#define RGXRISCVFW_SHARED_CACHED_DATA_REGION    (0x6U)
-#define RGXRISCVFW_SHARED_UNCACHED_DATA_REGION  (0xDU)
+#define RGXRISCVFW_SHARED_CACHED_DATA_REGION    (0x6UL)
+#define RGXRISCVFW_SHARED_UNCACHED_DATA_REGION  (0xDUL)
 #define RGXRISCVFW_SHARED_CACHED_DATA_BASE      (RGXRISCVFW_GET_REGION_BASE(RGXRISCVFW_SHARED_CACHED_DATA_REGION))
 #define RGXRISCVFW_SHARED_UNCACHED_DATA_BASE    (RGXRISCVFW_GET_REGION_BASE(RGXRISCVFW_SHARED_UNCACHED_DATA_REGION))
 #define RGXRISCVFW_SHARED_CACHED_DATA_REMAP     (RGXRISCVFW_GET_REMAP(RGXRISCVFW_SHARED_CACHED_DATA_REGION))
@@ -155,29 +155,29 @@ typedef struct
 #define RGXRISCVFW_MCAUSE_INTERRUPT  (1U << 31)
 
 #define RGXRISCVFW_MCAUSE_TABLE \
-       X(0x00000000, IMG_FALSE, "NMI pin assertion") /* Also reset value */ \
-       X(0x00000001, IMG_TRUE,  "Instruction access fault") \
-       X(0x00000002, IMG_TRUE,  "Illegal instruction") \
-       X(0x00000003, IMG_TRUE,  "Breakpoint") \
-       X(0x00000004, IMG_TRUE,  "Load address misaligned") \
-       X(0x00000005, IMG_TRUE,  "Load access fault") \
-       X(0x00000006, IMG_TRUE,  "Store/AMO address misaligned") \
-       X(0x00000007, IMG_TRUE,  "Store/AMO access fault") \
-       X(0x0000000B, IMG_TRUE,  "Environment call from M-mode (FW assert)") \
-       X(0x80000007, IMG_FALSE, "Machine timer interrupt") \
-       X(0x8000000B, IMG_FALSE, "Machine external interrupt") \
-       X(0x8000001E, IMG_FALSE, "Machine correctable error local interrupt") \
-       X(0xF0000000, IMG_TRUE,  "Machine D-bus store error NMI") \
-       X(0xF0000001, IMG_TRUE,  "Machine D-bus non-blocking load error NMI") \
-       X(0xF0000002, IMG_TRUE,  "dCache unrecoverable NMI")
+       X(0x00000000U, IMG_FALSE, "NMI pin assertion") /* Also reset value */ \
+       X(0x00000001U, IMG_TRUE,  "Instruction access fault") \
+       X(0x00000002U, IMG_TRUE,  "Illegal instruction") \
+       X(0x00000003U, IMG_TRUE,  "Breakpoint") \
+       X(0x00000004U, IMG_TRUE,  "Load address misaligned") \
+       X(0x00000005U, IMG_TRUE,  "Load access fault") \
+       X(0x00000006U, IMG_TRUE,  "Store/AMO address misaligned") \
+       X(0x00000007U, IMG_TRUE,  "Store/AMO access fault") \
+       X(0x0000000BU, IMG_TRUE,  "Environment call from M-mode (FW assert)") \
+       X(0x80000007U, IMG_FALSE, "Machine timer interrupt") \
+       X(0x8000000BU, IMG_FALSE, "Machine external interrupt") \
+       X(0x8000001EU, IMG_FALSE, "Machine correctable error local interrupt") \
+       X(0xF0000000U, IMG_TRUE,  "Machine D-bus store error NMI") \
+       X(0xF0000001U, IMG_TRUE,  "Machine D-bus non-blocking load error NMI") \
+       X(0xF0000002U, IMG_TRUE,  "dCache unrecoverable NMI")
 
 
 /* Debug module HW defines */
 #define RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER (0U)
 #define RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY   (2U)
-#define RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT   (2U << 20)
-#define RGXRISCVFW_DMI_COMMAND_WRITE           (1U << 16)
-#define RGXRISCVFW_DMI_COMMAND_READ            (0U << 16)
+#define RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT   (2UL << 20)
+#define RGXRISCVFW_DMI_COMMAND_WRITE           (1UL << 16)
+#define RGXRISCVFW_DMI_COMMAND_READ            (0UL << 16)
 #define RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT     (2U)
 
 /* Abstract command error codes (descriptions from RISC-V debug spec v0.13) */
index 2ac666d..275b63a 100644 (file)
@@ -48,7 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "rgx_fwif_sf.h"
 
-static IMG_CHAR *const groups[]= {
+static const IMG_CHAR *const groups[]= {
 #define X(A,B) #B,
        RGXFW_LOG_SFGROUPLIST
 #undef X
index 03c0380..7001092 100644 (file)
@@ -58,7 +58,7 @@ typedef struct
        IMG_BOOL                bEnabled;
        IMG_UINT32              eBlockID;
        IMG_UINT32              uiCounterMask;
-       IMG_UINT64  RGXFW_ALIGN aui64CounterCfg[RGX_CNTBLK_COUNTERS_MAX];
+       IMG_UINT64  RGXFW_ALIGN aui64CounterCfg[RGX_CNTBLK_MUX_COUNTERS_MAX];
 }  RGXFWIF_HWPERF_CTL_BLK;
 
 /* Structure used to hold the configuration of the non-mux counters blocks */
@@ -68,6 +68,20 @@ typedef struct
        IMG_UINT32            aui32SelectedCountersIDs[RGX_HWPERF_MAX_CUSTOM_CNTRS];
 } RGXFW_HWPERF_SELECT;
 
+/* Structure used to hold a Direct-Addressable block's parameters for passing
+ * between the BG context and the IRQ context when applying a configuration
+ * request. RGX_FEATURE_HWPERF_OCEANIC use only.
+ */
+typedef struct
+{
+       IMG_UINT32               uiEnabled;
+       IMG_UINT32               uiNumCounters;
+       IMG_UINT32               eBlockID;
+       RGXFWIF_DEV_VIRTADDR     psModel;
+       IMG_UINT32               aui32Counters[RGX_CNTBLK_COUNTERS_MAX];
+} RGXFWIF_HWPERF_DA_BLK;
+
+
 /* Structure to hold the whole configuration request details for all blocks
  * The block masks and counts are used to optimise reading of this data. */
 typedef struct
@@ -77,8 +91,8 @@ typedef struct
        IMG_UINT32                         ui32SelectedCountersBlockMask;
        RGXFW_HWPERF_SELECT RGXFW_ALIGN    SelCntr[RGX_HWPERF_MAX_CUSTOM_BLKS];
 
-       IMG_UINT32                         ui32EnabledBlksCount;
-       RGXFWIF_HWPERF_CTL_BLK RGXFW_ALIGN sBlkCfg[RGX_HWPERF_MAX_DEFINED_BLKS];
+       IMG_UINT32                         ui32EnabledMUXBlksCount;
+       RGXFWIF_HWPERF_CTL_BLK RGXFW_ALIGN sBlkCfg[RGX_HWPERF_MAX_MUX_BLKS];
 } UNCACHED_ALIGN RGXFWIF_HWPERF_CTL;
 
 /* NOTE: The switch statement in this function must be kept in alignment with
@@ -90,7 +104,7 @@ typedef struct
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(rgxfw_hwperf_get_block_ctl)
 #endif
-static INLINE RGXFWIF_HWPERF_CTL_BLKrgxfw_hwperf_get_block_ctl(
+static INLINE RGXFWIF_HWPERF_CTL_BLK *rgxfw_hwperf_get_block_ctl(
                RGX_HWPERF_CNTBLK_ID eBlockID, RGXFWIF_HWPERF_CTL *psHWPerfInitData)
 {
        IMG_UINT32 ui32Idx;
@@ -221,4 +235,18 @@ static INLINE RGXFWIF_HWPERF_CTL_BLK* rgxfw_hwperf_get_block_ctl(
        return &psHWPerfInitData->sBlkCfg[ui32Idx];
 }
 
+/* Stub routine for rgxfw_hwperf_get_da_block_ctl() for non
+ * RGX_FEATURE_HWPERF_OCEANIC systems. Just return a NULL.
+ */
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(rgxfw_hwperf_get_da_block_ctl)
+#endif
+static INLINE RGXFWIF_HWPERF_DA_BLK* rgxfw_hwperf_get_da_block_ctl(
+               RGX_HWPERF_CNTBLK_ID eBlockID, RGXFWIF_HWPERF_CTL *psHWPerfInitData)
+{
+       PVR_UNREFERENCED_PARAMETER(eBlockID);
+       PVR_UNREFERENCED_PARAMETER(psHWPerfInitData);
+
+       return NULL;
+}
 #endif
index 1fc3546..9b665b6 100644 (file)
@@ -46,7 +46,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "img_types.h"
 #include "rgx_fwif_shared.h"
-#include "rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 #include "dllist.h"
 #include "rgx_hwperf.h"
 
@@ -109,21 +109,21 @@ typedef struct {
 #define RGXFWIF_LOG_ENABLED_GROUPS_LIST_PFSPEC  "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
 
 /* Used in a print statement to display log group state, one per group */
-#define RGXFWIF_LOG_ENABLED_GROUPS_LIST(types)  (((types) & RGXFWIF_LOG_TYPE_GROUP_MAIN)       ?("main ")              :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_MTS)                ?("mts ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_CLEANUP)    ?("cleanup ")   :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_CSW)                ?("csw ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_BIF)                ?("bif ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_PM)         ?("pm ")                :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_RTD)                ?("rtd ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_SPM)                ?("spm ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_POW)                ?("pow ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_HWR)                ?("hwr ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_HWP)                ?("hwp ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_RPM)                ?("rpm ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_DMA)                ?("dma ")               :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_MISC)       ?("misc ")              :("")),         \
-                                                (((types) & RGXFWIF_LOG_TYPE_GROUP_DEBUG)      ?("debug ")             :(""))
+#define RGXFWIF_LOG_ENABLED_GROUPS_LIST(types)  ((((types) & RGXFWIF_LOG_TYPE_GROUP_MAIN) != 0U)       ?("main ")              :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_MTS) != 0U)                ?("mts ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_CLEANUP) != 0U)    ?("cleanup ")   :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_CSW) != 0U)                ?("csw ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_BIF) != 0U)                ?("bif ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_PM) != 0U)         ?("pm ")                :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_RTD) != 0U)                ?("rtd ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_SPM) != 0U)                ?("spm ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_POW) != 0U)                ?("pow ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_HWR) != 0U)                ?("hwr ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_HWP) != 0U)                ?("hwp ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_RPM) != 0U)                ?("rpm ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_DMA) != 0U)                ?("dma ")               :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_MISC) != 0U)       ?("misc ")              :("")),         \
+                                                ((((types) & RGXFWIF_LOG_TYPE_GROUP_DEBUG) != 0U)      ?("debug ")             :(""))
 
 
 /************************************************************************
@@ -156,20 +156,31 @@ typedef struct
        IMG_UINT32      ui32LineNum;
 } UNCACHED_ALIGN RGXFWIF_FILE_INFO_BUF;
 
+/*!
+ * @Defgroup SRVAndFWTracing Services and Firmware Tracing data interface
+ * @Brief The document groups/lists the data structures and the interfaces related to Services and Firmware Tracing
+ * @{
+ */
+
+/*!
+ * @Brief Firmware trace buffer details
+ */
 typedef struct
 {
-       IMG_UINT32                      ui32TracePointer;
+       IMG_UINT32            ui32TracePointer;          /*!< Trace pointer (write index into Trace Buffer)*/
 
 #if defined(RGX_FIRMWARE)
-       IMG_UINT32 *pui32RGXFWIfTraceBuffer;            /* To be used by firmware for writing into trace buffer */
+       IMG_UINT32            *pui32RGXFWIfTraceBuffer;  /*!< Trace buffer address (FW address), to be used by firmware for writing into trace buffer */
 #else
-       RGXFWIF_DEV_VIRTADDR pui32RGXFWIfTraceBuffer;
+       RGXFWIF_DEV_VIRTADDR  pui32RGXFWIfTraceBuffer;   /*!< Trace buffer address (FW address)*/
 #endif
-       IMG_PUINT32             pui32TraceBuffer;       /* To be used by host when reading from trace buffer */
+       IMG_PUINT32           pui32TraceBuffer;          /*!< Trace buffer address (Host address), to be used by host when reading from trace buffer */
 
-       RGXFWIF_FILE_INFO_BUF   sAssertBuf;
+       RGXFWIF_FILE_INFO_BUF sAssertBuf;
 } UNCACHED_ALIGN RGXFWIF_TRACEBUF_SPACE;
 
+/*! @} End of Defgroup SRVAndFWTracing */
+
 #define RGXFWIF_FWFAULTINFO_MAX                (8U)                    /* Total number of FW fault logs stored */
 
 typedef struct
@@ -229,14 +240,12 @@ typedef IMG_UINT32 RGXFWIF_HWR_STATEFLAGS;
 #define RGXFWIF_DM_STATE_GPU_ECC_HWR                           (IMG_UINT32_C(0x1) << 10)       /*!< DM was forced into HWR due to an uncorrected GPU ECC error */
 
 /* Firmware's connection state */
-typedef enum
-{
-       RGXFW_CONNECTION_FW_OFFLINE = 0,        /*!< Firmware is offline */
-       RGXFW_CONNECTION_FW_READY,                      /*!< Firmware is initialised */
-       RGXFW_CONNECTION_FW_ACTIVE,                     /*!< Firmware connection is fully established */
-       RGXFW_CONNECTION_FW_OFFLOADING,         /*!< Firmware is clearing up connection data */
-       RGXFW_CONNECTION_FW_STATE_COUNT
-} RGXFWIF_CONNECTION_FW_STATE;
+typedef IMG_UINT32 RGXFWIF_CONNECTION_FW_STATE;
+#define RGXFW_CONNECTION_FW_OFFLINE            0U      /*!< Firmware is offline */
+#define RGXFW_CONNECTION_FW_READY              1U      /*!< Firmware is initialised */
+#define RGXFW_CONNECTION_FW_ACTIVE             2U      /*!< Firmware connection is fully established */
+#define RGXFW_CONNECTION_FW_OFFLOADING 3U      /*!< Firmware is clearing up connection data */
+#define RGXFW_CONNECTION_FW_STATE_COUNT        4U
 
 /* OS' connection state */
 typedef enum
@@ -259,7 +268,7 @@ typedef struct
 typedef IMG_UINT32 RGXFWIF_HWR_RECOVERYFLAGS;
 
 #if defined(PVRSRV_STALLED_CCB_ACTION)
-#define PVR_SLR_LOG_ENTRIES 10
+#define PVR_SLR_LOG_ENTRIES 10U
 #define PVR_SLR_LOG_STRLEN  30 /*!< MAX_CLIENT_CCB_NAME not visible to this header */
 
 typedef struct
@@ -271,14 +280,17 @@ typedef struct
 } UNCACHED_ALIGN RGXFWIF_SLR_ENTRY;
 #endif
 
-/* firmware trace control data */
+/*!
+ * @InGroup SRVAndFWTracing
+ * @Brief Firmware trace control data
+ */
 typedef struct
 {
-       IMG_UINT32              ui32LogType;
-       RGXFWIF_TRACEBUF_SPACE  sTraceBuf[RGXFW_THREAD_NUM];
-       IMG_UINT32              ui32TraceBufSizeInDWords; /*!< Member initialised only when sTraceBuf is actually allocated
-                                                       * (in RGXTraceBufferInitOnDemandResources) */
-       IMG_UINT32              ui32TracebufFlags;        /*!< Compatibility and other flags */
+       IMG_UINT32              ui32LogType;                  /*!< FW trace log group configuration */
+       RGXFWIF_TRACEBUF_SPACE  sTraceBuf[RGXFW_THREAD_NUM];  /*!< FW Trace buffer */
+       IMG_UINT32              ui32TraceBufSizeInDWords;     /*!< FW Trace buffer size in dwords, Member initialised only when sTraceBuf is actually allocated
+                                                                                                                       (in RGXTraceBufferInitOnDemandResources) */
+       IMG_UINT32              ui32TracebufFlags;            /*!< Compatibility and other flags */
 } UNCACHED_ALIGN RGXFWIF_TRACEBUF;
 
 /*! @Brief Firmware system data shared with the Host driver */
@@ -318,11 +330,15 @@ typedef struct
        IMG_UINT32 RGXFW_ALIGN     aui32FWStatsBuf[RGXFWIF_STATS_FRAMEWORK_MAX];
 #endif
        RGXFWIF_HWR_STATEFLAGS     ui32HWRStateFlags; /*!< Firmware's Current HWR state */
-       RGXFWIF_HWR_RECOVERYFLAGS  aui32HWRRecoveryFlags[RGXFWIF_DM_DEFAULT_MAX]; /*!< Each DM's HWR state */
+       RGXFWIF_HWR_RECOVERYFLAGS  aui32HWRRecoveryFlags[RGXFWIF_DM_MAX]; /*!< Each DM's HWR state */
        IMG_UINT32                 ui32FwSysDataFlags;                      /*!< Compatibility and other flags */
+       IMG_UINT32                 ui32McConfig;                            /*!< Identify whether MC config is P-P or P-S */
 } UNCACHED_ALIGN RGXFWIF_SYSDATA;
 
-/*! @Brief Firmware per-os data shared with the Host driver */
+/*!
+ * @InGroup ContextSwitching
+ * @Brief Firmware per-os data and configuration
+ */
 typedef struct
 {
        IMG_UINT32                 ui32FwOsConfigFlags;                   /*!< Configuration flags from an OS */
@@ -497,10 +513,10 @@ typedef struct
        IMG_UINT32  ui32WriteIndex; /*!< Index for updating recovery information in sHWRInfo */
        IMG_UINT32  ui32DDReqCount; /*!< Count of DebugDump requested to the host after recovery */
        IMG_UINT32  ui32HWRInfoBufFlags; /* Compatibility and other flags */
-       IMG_UINT32  aui32HwrDmLockedUpCount[RGXFWIF_DM_DEFAULT_MAX]; /*!< Lockup count for each DM */
-       IMG_UINT32  aui32HwrDmOverranCount[RGXFWIF_DM_DEFAULT_MAX]; /*!< Overrun count for each DM */
-       IMG_UINT32  aui32HwrDmRecoveredCount[RGXFWIF_DM_DEFAULT_MAX]; /*!< Lockup + Overrun count for each DM */
-       IMG_UINT32  aui32HwrDmFalseDetectCount[RGXFWIF_DM_DEFAULT_MAX]; /*!< False lockup detection count for each DM */
+       IMG_UINT32  aui32HwrDmLockedUpCount[RGXFWIF_DM_MAX]; /*!< Lockup count for each DM */
+       IMG_UINT32  aui32HwrDmOverranCount[RGXFWIF_DM_MAX]; /*!< Overrun count for each DM */
+       IMG_UINT32  aui32HwrDmRecoveredCount[RGXFWIF_DM_MAX]; /*!< Lockup + Overrun count for each DM */
+       IMG_UINT32  aui32HwrDmFalseDetectCount[RGXFWIF_DM_MAX]; /*!< False lockup detection count for each DM */
 } UNCACHED_ALIGN RGXFWIF_HWRINFOBUF;
 
 /*! @} End of HWRInfo */
@@ -530,18 +546,13 @@ typedef struct
 #define RGXFWIF_INICFG_FBCDC_V3_1_EN                                   (IMG_UINT32_C(0x1) << 6)
 #define RGXFWIF_INICFG_CHECK_MLIST_EN                                  (IMG_UINT32_C(0x1) << 7)
 #define RGXFWIF_INICFG_DISABLE_CLKGATING_EN                            (IMG_UINT32_C(0x1) << 8)
-#define RGXFWIF_INICFG_POLL_COUNTERS_EN                                        (IMG_UINT32_C(0x1) << 9)
-#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT                        (10)
-#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX                        (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INDEX << RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT)
-#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE             (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_INSTANCE << RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT)
-#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST                 (RGX_CR_VDM_CONTEXT_STORE_MODE_MODE_LIST << RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT)
-#define RGXFWIF_INICFG_VDM_CTX_STORE_MODE_MASK                 (RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX |\
-                                                         RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE |\
-                                                         RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST)
+/* 9 unused */
+/* 10 unused */
+/* 11 unused */
 #define RGXFWIF_INICFG_REGCONFIG_EN                                            (IMG_UINT32_C(0x1) << 12)
 #define RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY                   (IMG_UINT32_C(0x1) << 13)
 #define RGXFWIF_INICFG_HWP_DISABLE_FILTER                              (IMG_UINT32_C(0x1) << 14)
-#define RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN                            (IMG_UINT32_C(0x1) << 15)
+/* 15 unused */
 #define RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT                 (16)
 #define RGXFWIF_INICFG_CTXSWITCH_PROFILE_FAST                  (RGXFWIF_CTXSWITCH_PROFILE_FAST_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
 #define RGXFWIF_INICFG_CTXSWITCH_PROFILE_MEDIUM                        (RGXFWIF_CTXSWITCH_PROFILE_MEDIUM_EN << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT)
@@ -571,23 +582,37 @@ typedef struct
 #define RGXFWIF_INICFG_ALL                                                             (0xFFFFFFFFU)
 
 /* Extended Flag definitions affecting the firmware globally */
-#define RGXFWIF_INICFG_EXT_ALL                                                         (0x0U)
+#define RGXFWIF_INICFG_EXT_TFBC_CONTROL_SHIFT                  (0)
+/* [7]   YUV10 override
+ * [6:4] Quality
+ * [3]   Quality enable
+ * [2:1] Compression scheme
+ * [0]   Lossy group */
+#define RGXFWIF_INICFG_EXT_TFBC_CONTROL_MASK                   (IMG_UINT32_C(0xFF)) /* RGX_CR_TFBC_COMPRESSION_CONTROL_MASKFULL */
+#define RGXFWIF_INICFG_EXT_ALL                                                 (RGXFWIF_INICFG_EXT_TFBC_CONTROL_MASK)
 
 #define RGXFWIF_INICFG_SYS_CTXSWITCH_CLRMSK                            ~(RGXFWIF_INICFG_CTXSWITCH_MODE_RAND | \
                                                                                                                  RGXFWIF_INICFG_CTXSWITCH_SRESET_EN)
 
 /* Flag definitions affecting only workloads submitted by a particular OS */
-#define RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN                             (IMG_UINT32_C(0x1) << 0)
-#define RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN                            (IMG_UINT32_C(0x1) << 1)
-#define RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN                              (IMG_UINT32_C(0x1) << 2)
-#define RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN                             (IMG_UINT32_C(0x1) << 3)
+
+/*!
+ * @AddToGroup ContextSwitching
+ * @{
+ * @Name Per-OS DM context switch configuration flags
+ * @{
+ */
+#define RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN                             (IMG_UINT32_C(0x1) << 0) /*!< Enables TDM context switch */
+#define RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN                            (IMG_UINT32_C(0x1) << 1) /*!< Enables GEOM DM context switch */
+#define RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN                              (IMG_UINT32_C(0x1) << 2) /*!< Enables FRAG DM context switch */
+#define RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN                             (IMG_UINT32_C(0x1) << 3) /*!< Enables CDM context switch */
 
 #define RGXFWIF_INICFG_OS_LOW_PRIO_CS_TDM                              (IMG_UINT32_C(0x1) << 4)
 #define RGXFWIF_INICFG_OS_LOW_PRIO_CS_GEOM                             (IMG_UINT32_C(0x1) << 5)
 #define RGXFWIF_INICFG_OS_LOW_PRIO_CS_3D                               (IMG_UINT32_C(0x1) << 6)
 #define RGXFWIF_INICFG_OS_LOW_PRIO_CS_CDM                              (IMG_UINT32_C(0x1) << 7)
 
-#define RGXFWIF_INICFG_OS_ALL                                                  (0xFF)
+#define RGXFWIF_INICFG_OS_ALL                                                  (0xFFU)
 
 #define RGXFWIF_INICFG_OS_CTXSWITCH_DM_ALL                             (RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN | \
                                                                                                                 RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN | \
@@ -596,16 +621,19 @@ typedef struct
 
 #define RGXFWIF_INICFG_OS_CTXSWITCH_CLRMSK                             ~(RGXFWIF_INICFG_OS_CTXSWITCH_DM_ALL)
 
+/*!
+ * @} End of Per-OS Context switch configuration flags
+ * @} End of AddToGroup ContextSwitching
+ */
+
 #define RGXFWIF_FILTCFG_TRUNCATE_HALF                                  (IMG_UINT32_C(0x1) << 3)
 #define RGXFWIF_FILTCFG_TRUNCATE_INT                                   (IMG_UINT32_C(0x1) << 2)
 #define RGXFWIF_FILTCFG_NEW_FILTER_MODE                                        (IMG_UINT32_C(0x1) << 1)
 
-typedef enum
-{
-       RGX_ACTIVEPM_FORCE_OFF = 0,
-       RGX_ACTIVEPM_FORCE_ON = 1,
-       RGX_ACTIVEPM_DEFAULT = 2
-} RGX_ACTIVEPM_CONF;
+typedef IMG_UINT32 RGX_ACTIVEPM_CONF;
+#define RGX_ACTIVEPM_FORCE_OFF 0U
+#define RGX_ACTIVEPM_FORCE_ON  1U
+#define RGX_ACTIVEPM_DEFAULT   2U
 
 typedef enum
 {
@@ -657,6 +685,7 @@ typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_RUNTIME_CFG;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_GPU_UTIL_FWCB;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_REG_CFG;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_HWPERF_CTL;
+typedef RGXFWIF_DEV_VIRTADDR  PRGX_HWPERF_CONFIG_MUX_CNTBLK;
 typedef RGXFWIF_DEV_VIRTADDR  PRGX_HWPERF_CONFIG_CNTBLK;
 typedef RGXFWIF_DEV_VIRTADDR  PRGX_HWPERF_SELECT_CUSTOM_CNTRS;
 typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_CCB_CTL;
@@ -684,7 +713,7 @@ typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_RF_CMD;
 /*!
  * This number is used to represent unallocated page catalog base register
  */
-#define RGXFW_BIF_INVALID_PCREG 0xFFFFFFFFU
+#define RGXFW_BIF_INVALID_PCSET 0xFFFFFFFFU
 
 /*!
     Firmware memory context.
@@ -692,7 +721,7 @@ typedef RGXFWIF_DEV_VIRTADDR  PRGXFWIF_RF_CMD;
 typedef struct
 {
        IMG_DEV_PHYADDR                 RGXFW_ALIGN sPCDevPAddr;        /*!< device physical address of context's page catalogue */
-       IMG_UINT32                              uiPageCatBaseRegID;     /*!< associated page catalog base register (RGXFW_BIF_INVALID_PCREG == unallocated) */
+       IMG_UINT32                              uiPageCatBaseRegSet;    /*!< associated page catalog base register (RGXFW_BIF_INVALID_PCSET == unallocated) */
        IMG_UINT32                              uiBreakpointAddr; /*!< breakpoint address */
        IMG_UINT32                              uiBPHandlerAddr; /*!< breakpoint handler address */
        IMG_UINT32                              uiBreakpointCtl; /*!< DM and enable control for BP */
@@ -711,32 +740,46 @@ typedef struct
 #define RGXFWIF_CONTEXT_FLAGS_NEED_RESUME                              (0x00000001U)
 #define RGXFWIF_CONTEXT_FLAGS_MC_NEED_RESUME_MASKFULL  (0x000000FFU)
 #define RGXFWIF_CONTEXT_FLAGS_TDM_HEADER_STALE                 (0x00000100U)
+#define RGXFWIF_CONTEXT_FLAGS_LAST_KICK_SECURE                 (0x00000200U)
 
+/*!
+ * @InGroup ContextSwitching
+ * @Brief Firmware GEOM/TA context suspend state
+ */
 typedef struct
 {
        /* FW-accessible TA state which must be written out to memory on context store */
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER;               /* To store in mid-TA */
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER_Init;  /* Initial value (in case is 'lost' due to a lock-up */
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VDM_BATCH;
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VBS_SO_PRIM0;
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VBS_SO_PRIM1;
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VBS_SO_PRIM2;
-       IMG_UINT64      RGXFW_ALIGN uTAReg_VBS_SO_PRIM3;
+       IMG_UINT64      RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER;               /*!< VDM control stream stack pointer, to store in mid-TA */
+       IMG_UINT64      RGXFW_ALIGN uTAReg_VDM_CALL_STACK_POINTER_Init;  /*!< Initial value of VDM control stream stack pointer (in case is 'lost' due to a lock-up) */
+       IMG_UINT32      uTAReg_VBS_SO_PRIM[4];
        IMG_UINT16      ui16TACurrentIdx;
+} UNCACHED_ALIGN RGXFWIF_TACTX_STATE_PER_GEOM;
+
+typedef struct
+{
+       /* FW-accessible TA state which must be written out to memory on context store */
+       RGXFWIF_TACTX_STATE_PER_GEOM asGeomCore[RGX_NUM_GEOM_CORES];
 } UNCACHED_ALIGN RGXFWIF_TACTX_STATE;
 
+/*!
+ * @InGroup ContextSwitching
+ * @Brief Firmware FRAG/3D context suspend state
+ */
 typedef struct
 {
        /* FW-accessible ISP state which must be written out to memory on context store */
-       IMG_UINT32      RGXFW_ALIGN u3DReg_PM_DEALLOCATED_MASK_STATUS;
-       IMG_UINT32      RGXFW_ALIGN u3DReg_PM_PDS_MTILEFREE_STATUS;
+       IMG_UINT32      u3DReg_PM_DEALLOCATED_MASK_STATUS; /*!< PM deallocation status */
+       IMG_UINT32      u3DReg_PM_PDS_MTILEFREE_STATUS; /*!< Macro-tiles (MTs) finished status */
        IMG_UINT32      ui32CtxStateFlags;      /*!< Compatibility and other flags */
        /* au3DReg_ISP_STORE should be the last element of the structure
         * as this is an array whose size is determined at runtime
         * after detecting the RGX core */
-       IMG_UINT32      au3DReg_ISP_STORE[];
+       IMG_UINT32      au3DReg_ISP_STORE[]; /*!< ISP state (per-pipe) */
 } UNCACHED_ALIGN RGXFWIF_3DCTX_STATE;
 
+static_assert(sizeof(RGXFWIF_3DCTX_STATE) <= 16U,
+              "Size of structure RGXFWIF_3DCTX_STATE exceeds maximum expected size.");
+
 #define RGXFWIF_CTX_USING_BUFFER_A             (0)
 #define RGXFWIF_CTX_USING_BUFFER_B             (1U)
 
@@ -745,7 +788,10 @@ typedef struct
        IMG_UINT32      ui32CtxStateFlags; /*!< Target buffer and other flags */
 } RGXFWIF_COMPUTECTX_STATE;
 
-
+/*!
+ * @InGroup WorkloadContexts
+ * @Brief Firmware Common Context (or FWCC)
+ */
 typedef struct RGXFWIF_FWCOMMONCONTEXT_
 {
        /* CCB details for this firmware context */
@@ -753,31 +799,16 @@ typedef struct RGXFWIF_FWCOMMONCONTEXT_
        PRGXFWIF_CCCB                   psCCB;                                  /*!< CCB base */
        RGXFWIF_DMA_ADDR                sCCBMetaDMAAddr;
 
-       RGXFWIF_DLLIST_NODE             RGXFW_ALIGN sWaitingNode;               /*!< List entry for the waiting list */
-       RGXFWIF_DLLIST_NODE             RGXFW_ALIGN sRunNode;                   /*!< List entry for the run list */
-       RGXFWIF_UFO                             sLastFailedUFO;                 /*!< UFO that last failed (or NULL) */
-
-       PRGXFWIF_FWMEMCONTEXT   psFWMemContext;                                 /*!< Memory context */
-
        /* Context suspend state */
        PRGXFWIF_COMMONCTX_STATE        RGXFW_ALIGN psContextState;             /*!< TA/3D context suspend state, read/written by FW */
 
-       /* Framework state
-        */
-       PRGXFWIF_RF_CMD         RGXFW_ALIGN psRFCmd;                            /*!< Register updates for Framework */
-
-       /*
-        * Flags e.g. for context switching
-        */
+       /* Flags e.g. for context switching */
        IMG_UINT32                              ui32FWComCtxFlags;
-       IMG_UINT32                              ui32Priority;
+       IMG_INT32                               i32Priority;  /*!< Priority level */
        IMG_UINT32                              ui32PrioritySeqNum;
 
-       /* References to the host side originators */
-       IMG_UINT32                              ui32ServerCommonContextID;      /*!< the Server Common Context */
-       IMG_UINT32                              ui32PID;                        /*!< associated process ID */
-
-       IMG_BOOL                                bGeomOOMDisabled;               /*!< True when Geom DM OOM is not allowed */
+       /* Framework state */
+       PRGXFWIF_RF_CMD                 RGXFW_ALIGN psRFCmd;            /*!< Register updates for Framework */
 
        /* Statistic updates waiting to be passed back to the host... */
        IMG_BOOL                                bStatsPending;                  /*!< True when some stats are pending */
@@ -793,16 +824,33 @@ typedef struct RGXFWIF_FWCOMMONCONTEXT_
        IMG_UINT64                              RGXFW_ALIGN  ui64RobustnessAddress;
        IMG_UINT32                              ui32MaxDeadlineMS;                      /*!< Max HWR deadline limit in ms */
        bool                                    bReadOffsetNeedsReset;                  /*!< Following HWR circular buffer read-offset needs resetting */
+
+       RGXFWIF_DLLIST_NODE             RGXFW_ALIGN sWaitingNode;               /*!< List entry for the waiting list */
+       RGXFWIF_DLLIST_NODE             RGXFW_ALIGN sRunNode;                   /*!< List entry for the run list */
+       RGXFWIF_UFO                             sLastFailedUFO;                 /*!< UFO that last failed (or NULL) */
+
+       PRGXFWIF_FWMEMCONTEXT   psFWMemContext;                                 /*!< Memory context */
+
+       /* References to the host side originators */
+       IMG_UINT32                              ui32ServerCommonContextID;      /*!< the Server Common Context */
+       IMG_UINT32                              ui32PID;                        /*!< associated process ID */
+
+       IMG_BOOL                                bGeomOOMDisabled;               /*!< True when Geom DM OOM is not allowed */
+
 } UNCACHED_ALIGN RGXFWIF_FWCOMMONCONTEXT;
 
+static_assert(sizeof(RGXFWIF_FWCOMMONCONTEXT) <= 256U,
+              "Size of structure RGXFWIF_FWCOMMONCONTEXT exceeds maximum expected size.");
+
 typedef IMG_UINT64 RGXFWIF_TRP_CHECKSUM_TQ[RGX_TRP_MAX_NUM_CORES][1];
 typedef IMG_UINT64 RGXFWIF_TRP_CHECKSUM_2D[RGX_TRP_MAX_NUM_CORES][2];
 typedef IMG_UINT64 RGXFWIF_TRP_CHECKSUM_3D[RGX_TRP_MAX_NUM_CORES][4];
 typedef IMG_UINT64 RGXFWIF_TRP_CHECKSUM_GEOM[RGX_TRP_MAX_NUM_CORES][2];
 
 /*!
-       Firmware render context.
-*/
+ * @InGroup WorkloadContexts
+ * @Brief Firmware render context.
+ */
 typedef struct
 {
        RGXFWIF_FWCOMMONCONTEXT sTAContext;                             /*!< Firmware context for the TA */
@@ -814,6 +862,10 @@ typedef struct
 
        IMG_UINT32                      ui32FwRenderCtxFlags; /*!< Compatibility and other flags */
 
+#if defined(SUPPORT_TRP)
+       RGXFWIF_TRP_CHECKSUM_3D         aui64TRPChecksums3D;
+       RGXFWIF_TRP_CHECKSUM_GEOM       aui64TRPChecksumsGeom;
+#endif
 } UNCACHED_ALIGN RGXFWIF_FWRENDERCONTEXT;
 
 /*!
@@ -847,12 +899,17 @@ typedef struct
 } UNCACHED_ALIGN RGXFWIF_FWTDMCONTEXT;
 
 /*!
-       Firmware TQ3D context.
-*/
+ * @InGroup WorkloadContexts
+ * @Brief Firmware transfer context.
+ */
 typedef struct
 {
        RGXFWIF_FWCOMMONCONTEXT sTQContext;                      /*!< Firmware context for TQ3D */
 
+#if defined(SUPPORT_TRP)
+       IMG_UINT32                              ui32TRPState;
+       RGXFWIF_TRP_CHECKSUM_TQ aui64TRPChecksumsTQ;
+#endif
 } UNCACHED_ALIGN RGXFWIF_FWTRANSFERCONTEXT;
 
 /*!
@@ -873,13 +930,8 @@ typedef struct
 #define RGX_CMD_MAGIC_DWORD_SHIFTED    (RGX_CMD_MAGIC_DWORD << RGX_CMD_MAGIC_DWORD_SHIFT)
 
 /*!
- * @Defgroup KCCBTypes Kernel CCB data interface
- * @Brief Types grouping data structures and defines used in realising the KCCB functionality
- * @{
- */
-
-/*!
- * @Brief Kernel CCB control for RGX
+ * @InGroup KCCBTypes ClientCCBTypes
+ * @Brief Generic CCB control structure
  */
 typedef struct
 {
@@ -889,6 +941,12 @@ typedef struct
        IMG_UINT32                              ui32CmdSize;                    /*!< size of each command in bytes */
 } UNCACHED_ALIGN RGXFWIF_CCB_CTL;
 
+/*!
+ * @Defgroup KCCBTypes Kernel CCB data interface
+ * @Brief Types grouping data structures and defines used in realising the KCCB functionality
+ * @{
+ */
+
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PT      (0x1U) /* MMU_CTRL_INVAL_PT_EN */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PD      (0x2U) /* MMU_CTRL_INVAL_PD_EN */
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PC      (0x4U) /* MMU_CTRL_INVAL_PC_EN */
@@ -897,7 +955,11 @@ typedef struct
 
 #if !defined(RGX_FEATURE_SLC_VIVT)
 #define RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB   (0x10U) /* can't use PM_TLB0 bit from BIFPM_CTRL reg because it collides with PT bit from BIF_CTRL reg */
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE < 2)
 #define RGXFWIF_MMUCACHEDATA_FLAGS_TLB     (RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB | 0x8U) /* BIF_CTRL_INVAL_TLB1_EN */
+#else
+#define RGXFWIF_MMUCACHEDATA_FLAGS_TLB     (RGXFWIF_MMUCACHEDATA_FLAGS_PMTLB)
+#endif
 #define RGXFWIF_MMUCACHEDATA_FLAGS_CTX_ALL (0x0U) /* not used */
 
 #else /* RGX_FEATURE_SLC_VIVT */
@@ -957,12 +1019,12 @@ typedef struct
 } RGXFWIF_KCCB_CMD_KICK_DATA;
 
 /*!
- * @Brief Command data for \ref RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK type command
+ * @Brief Command data for @Ref RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK type command
  */
 typedef struct
 {
-       RGXFWIF_KCCB_CMD_KICK_DATA      sTACmdKickData;
-       RGXFWIF_KCCB_CMD_KICK_DATA      s3DCmdKickData;
+       RGXFWIF_KCCB_CMD_KICK_DATA      sTACmdKickData; /*!< GEOM DM kick command data */
+       RGXFWIF_KCCB_CMD_KICK_DATA      s3DCmdKickData; /*!< FRAG DM kick command data */
 } RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK_DATA;
 
 /*!
@@ -1064,9 +1126,15 @@ typedef struct
 
 typedef struct
 {
+       IMG_UINT32                ui32NumBlocks;    /*!< Number of RGX_HWPERF_CONFIG_MUX_CNTBLK in the array */
+       PRGX_HWPERF_CONFIG_MUX_CNTBLK sBlockConfigs;    /*!< Address of the RGX_HWPERF_CONFIG_MUX_CNTBLK array */
+} RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS;
+
+typedef struct
+{
        IMG_UINT32                ui32NumBlocks;    /*!< Number of RGX_HWPERF_CONFIG_CNTBLK in the array */
        PRGX_HWPERF_CONFIG_CNTBLK sBlockConfigs;    /*!< Address of the RGX_HWPERF_CONFIG_CNTBLK array */
-} RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS;
+} RGXFWIF_HWPERF_CONFIG_DA_BLKS;
 
 /*!
  * @Brief Command data for \ref RGXFWIF_KCCB_CMD_CORECLKSPEEDCHANGE type command
@@ -1076,7 +1144,7 @@ typedef struct
        IMG_UINT32      ui32NewClockSpeed;                      /*!< New clock speed */
 } RGXFWIF_CORECLKSPEEDCHANGE_DATA;
 
-#define RGXFWIF_HWPERF_CTRL_BLKS_MAX   16
+#define RGXFWIF_HWPERF_CTRL_BLKS_MAX   16U
 
 /*!
  * @Brief Command data for \ref RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS type command
@@ -1113,6 +1181,13 @@ typedef struct
        IMG_UINT32 ui32RegAddr;
        IMG_UINT64 RGXFW_ALIGN ui64RegVal;
 } RGXFWIF_RGXREG_DATA;
+
+typedef struct
+{
+       IMG_UINT64 ui64BaseAddress;
+       PRGXFWIF_FWCOMMONCONTEXT psContext;
+       IMG_UINT32 ui32Size;
+} RGXFWIF_GPUMAP_DATA;
 #endif
 
 /*!
@@ -1139,15 +1214,6 @@ typedef struct
 } RGXFWIF_FREELISTS_RECONSTRUCTION_DATA;
 
 /*!
- * @Brief Command data for \ref RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE type command
- */
-typedef struct
-{
-       IMG_DEV_VIRTADDR RGXFW_ALIGN       sDevSignalAddress; /*!< device virtual address of the updated signal */
-       PRGXFWIF_FWMEMCONTEXT              psFWMemContext; /*!< Memory context */
-} UNCACHED_ALIGN RGXFWIF_SIGNAL_UPDATE_DATA;
-
-/*!
  * @Brief Command data for \ref RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE type command
  */
 typedef struct
@@ -1281,12 +1347,13 @@ typedef enum
        RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE                      = 109U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Unbacking for on-demand ZS-Buffer done */
        RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE                           = 110U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Freelist Grow done */
        RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE        = 112U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Freelists Reconstruction done */
-       RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE                           = 113U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Informs the firmware that the host has performed a signal update */
+       /* RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE */
        RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE                     = 114U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Informs the firmware that the host has added more data to a CDM2 Circular Buffer */
        RGXFWIF_KCCB_CMD_HEALTH_CHECK                                           = 115U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Health check request */
        RGXFWIF_KCCB_CMD_FORCE_UPDATE                                           = 116U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Forcing signalling of all unmet UFOs for a given CCB offset */
 
        RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK                            = 117U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< There is a TA and a 3D command in this single kick */
+       RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE                      = 118U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Informs the FW that a Guest OS has come online / offline. */
 
        /* Commands only permitted to the native or host OS */
        RGXFWIF_KCCB_CMD_REGCONFIG                                                      = 200U | RGX_CMD_MAGIC_DWORD_SHIFTED,
@@ -1300,7 +1367,7 @@ typedef enum
        RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE                           = 208U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Changes the relative scheduling priority for a particular OSid. It can only be serviced for the Host DDK */
        RGXFWIF_KCCB_CMD_STATEFLAGS_CTRL                                        = 209U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Set or clear firmware state flags */
        /* RGXFWIF_KCCB_CMD_HCS_SET_DEADLINE */
-       RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE                      = 211U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Informs the FW that a Guest OS has come online / offline. It can only be serviced for the Host DDK */
+       /*RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE */
        RGXFWIF_KCCB_CMD_PDVFS_LIMIT_MIN_FREQ                           = 212U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Set a minimum frequency/OPP point */
        RGXFWIF_KCCB_CMD_PHR_CFG                                                        = 213U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Configure Periodic Hardware Reset behaviour */
 #if defined(SUPPORT_VALIDATION)
@@ -1310,6 +1377,10 @@ typedef enum
        RGXFWIF_KCCB_CMD_COUNTER_DUMP                                           = 216U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Controls counter dumping in the FW */
        RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS                      = 217U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Configure, clear and enable multiple HWPerf blocks */
        RGXFWIF_KCCB_CMD_HWPERF_SELECT_CUSTOM_CNTRS                     = 218U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Configure the custom counters for HWPerf */
+#if defined(SUPPORT_VALIDATION)
+       RGXFWIF_KCCB_CMD_GPUMAP                                                         = 219U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Request a FW GPU mapping which is written into by the FW with a pattern */
+#endif
+       RGXFWIF_KCCB_CMD_HWPERF_CONFIG_BLKS                 = 220U | RGX_CMD_MAGIC_DWORD_SHIFTED, /*!< Configure directly addressable counters for HWPerf */
 } RGXFWIF_KCCB_CMD_TYPE;
 
 #define RGXFWIF_LAST_ALLOWED_GUEST_KCCB_CMD (RGXFWIF_KCCB_CMD_REGCONFIG - 1)
@@ -1336,13 +1407,13 @@ typedef struct
                RGXFWIF_HWPERF_CTRL                                     sHWPerfCtrl;                    /*!< Data for HWPerf control command */
                RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS       sHWPerfCfgEnableBlks;   /*!< Data for HWPerf configure, clear and enable performance counter block command */
                RGXFWIF_HWPERF_CTRL_BLKS                        sHWPerfCtrlBlks;                /*!< Data for HWPerf enable or disable performance counter block commands */
-               RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS  sHWPerfSelectCstmCntrs; /*!< Data for HWPerf configure the custom counters to read */
+               RGXFWIF_HWPERF_SELECT_CUSTOM_CNTRS      sHWPerfSelectCstmCntrs; /*!< Data for HWPerf configure the custom counters to read */
+               RGXFWIF_HWPERF_CONFIG_DA_BLKS           sHWPerfCfgDABlks;               /*!< Data for HWPerf configure Directly Addressable blocks */
                RGXFWIF_CORECLKSPEEDCHANGE_DATA         sCoreClkSpeedChangeData;/*!< Data for core clock speed change */
                RGXFWIF_ZSBUFFER_BACKING_DATA           sZSBufferBackingData;   /*!< Feedback for Z/S Buffer backing/unbacking */
                RGXFWIF_FREELIST_GS_DATA                        sFreeListGSData;                /*!< Feedback for Freelist grow/shrink */
                RGXFWIF_FREELISTS_RECONSTRUCTION_DATA   sFreeListsReconstructionData;   /*!< Feedback for Freelists reconstruction */
                RGXFWIF_REGCONFIG_DATA                          sRegConfigData;                 /*!< Data for custom register configuration */
-               RGXFWIF_SIGNAL_UPDATE_DATA          sSignalUpdateData;      /*!< Data for informing the FW about the signal update */
                RGXFWIF_WRITE_OFFSET_UPDATE_DATA    sWriteOffsetUpdateData; /*!< Data for informing the FW about the write offset update */
                RGXFWIF_PDVFS_MAX_FREQ_DATA                     sPDVFSMaxFreqData;              /*!< Data for setting the max frequency/OPP */
                RGXFWIF_PDVFS_MIN_FREQ_DATA                     sPDVFSMinFreqData;              /*!< Data for setting the min frequency/OPP */
@@ -1352,6 +1423,7 @@ typedef struct
                RGXFWIF_KCCB_CMD_FORCE_UPDATE_DATA  sForceUpdateData;       /*!< Data for signalling all unmet fences for a given CCB */
 #if defined(SUPPORT_VALIDATION)
                RGXFWIF_RGXREG_DATA                 sFwRgxData;             /*!< Data for reading off an RGX register */
+               RGXFWIF_GPUMAP_DATA                 sGPUMapData;            /*!< Data for requesting a FW GPU mapping which is written into by the FW with a pattern */
 #endif
        } UNCACHED_ALIGN uCmdData;
 } UNCACHED_ALIGN RGXFWIF_KCCB_CMD;
@@ -1545,8 +1617,8 @@ RGX_FW_STRUCT_SIZE_ASSERT(RGXFWIF_FWCCB_CMD);
  *****************************************************************************/
 typedef struct
 {
-       IMG_UINT64 RGXFW_ALIGN ui64ReturnDataIndex; /*!< Index for return data array */
-       IMG_UINT64 RGXFW_ALIGN ui64CyclesTaken;     /*!< The cycles the workload took on the hardware */
+       IMG_UINT16 ui16ReturnDataIndex; /*!< Index for return data array */
+       IMG_UINT32 ui32CyclesTaken;     /*!< The cycles the workload took on the hardware */
 } RGXFWIF_WORKEST_FWCCB_CMD;
 
 /*!
@@ -1562,10 +1634,14 @@ typedef struct
 #define RGXFWIF_FWALLOC_ALIGN  sizeof(IMG_UINT64)
 
 #define RGX_CCB_TYPE_TASK                      (IMG_UINT32_C(1) << 15)
-#define RGX_CCB_FWALLOC_ALIGN(size)    (((size) + (RGXFWIF_FWALLOC_ALIGN-1)) & ~(RGXFWIF_FWALLOC_ALIGN - 1))
+#define RGX_CCB_FWALLOC_ALIGN(size)    (((size) + (RGXFWIF_FWALLOC_ALIGN-1U)) & ~(RGXFWIF_FWALLOC_ALIGN - 1U))
 
 typedef IMG_UINT32 RGXFWIF_CCB_CMD_TYPE;
 
+/*!
+ * @Name Client CCB command types
+ * @{
+ */
 #define RGXFWIF_CCB_CMD_TYPE_GEOM                      (201U | RGX_CMD_MAGIC_DWORD_SHIFTED | RGX_CCB_TYPE_TASK) /*!< TA DM command */
 #define RGXFWIF_CCB_CMD_TYPE_TQ_3D                     (202U | RGX_CMD_MAGIC_DWORD_SHIFTED | RGX_CCB_TYPE_TASK) /*!< 3D DM command for TQ operation */
 #define RGXFWIF_CCB_CMD_TYPE_3D                                (203U | RGX_CMD_MAGIC_DWORD_SHIFTED | RGX_CCB_TYPE_TASK) /*!< 3D DM command */
@@ -1597,15 +1673,16 @@ typedef IMG_UINT32 RGXFWIF_CCB_CMD_TYPE;
 #endif
 
 #define RGXFWIF_CCB_CMD_TYPE_PADDING   (221U | RGX_CMD_MAGIC_DWORD_SHIFTED) /*!< Skip without action type command */
+/*! @} End of Client CCB command types */
 
 typedef struct
 {
        /* Index for the KM Workload estimation return data array */
-       IMG_UINT64 RGXFW_ALIGN                    ui64ReturnDataIndex;
-       /* Deadline for the workload */
-       IMG_UINT64 RGXFW_ALIGN                    ui64Deadline;
+       IMG_UINT16 RGXFW_ALIGN         ui16ReturnDataIndex;
        /* Predicted time taken to do the work in cycles */
-       IMG_UINT64 RGXFW_ALIGN                    ui64CyclesPrediction;
+       IMG_UINT32 RGXFW_ALIGN         ui32CyclesPrediction;
+       /* Deadline for the workload (in usecs) */
+       IMG_UINT64 RGXFW_ALIGN         ui64Deadline;
 } RGXFWIF_WORKEST_KICK_DATA;
 
 /*! @Brief Command header of a command in the client CCB buffer.
@@ -1630,7 +1707,7 @@ typedef struct
 /*! @Brief Command data for \ref RGXFWIF_CCB_CMD_TYPE_PRIORITY type client CCB command */
 typedef struct
 {
-       IMG_UINT32             ui32Priority;
+       IMG_INT32              i32Priority; /*!< Priority level */
 } RGXFWIF_CMD_PRIORITY;
 
 /*! @} End of ClientCCBTypes */
@@ -1687,7 +1764,7 @@ typedef struct
        do { \
                (name).ui32LayoutVersion = RGXFWIF_COMPCHECKS_LAYOUT_VERSION; \
                (name).ui64BVNC = 0; \
-       } while (0)
+       } while (false)
 
 typedef struct
 {
@@ -1785,6 +1862,10 @@ typedef enum
        RGXFWIF_GPIO_VAL_SR_COMPLEX    = 4, /*!< Strip Rendering AP based complex test.*/
 #endif
        RGXFWIF_GPIO_VAL_TESTBENCH     = 5, /*!< Validates the GPIO Testbench. */
+       RGXFWIF_GPIO_VAL_LOOPBACK      = 6, /*!< Send and then receive each byte
+                                                in the range 0-255. */
+       RGXFWIF_GPIO_VAL_LOOPBACK_LITE = 7, /*!< Send and then receive each power-of-2
+                                                byte in the range 0-255. */
        RGXFWIF_GPIO_VAL_LAST
 } RGXFWIF_GPIO_VAL_MODE;
 
@@ -1793,8 +1874,6 @@ typedef enum
        FW_PERF_CONF_NONE = 0,
        FW_PERF_CONF_ICACHE = 1,
        FW_PERF_CONF_DCACHE = 2,
-       FW_PERF_CONF_POLLS = 3,
-       FW_PERF_CONF_CUSTOM_TIMER = 4,
        FW_PERF_CONF_JTLB_INSTR = 5,
        FW_PERF_CONF_INSTRUCTIONS = 6
 } FW_PERF_CONF;
@@ -1812,15 +1891,24 @@ typedef enum
        FW_BOOT_INIT_DONE,
 } FW_BOOT_STAGE;
 
-/*
- * Kernel CCB return slot responses. Usage of bit-fields instead of bare integers
+/*!
+ * @AddToGroup KCCBTypes
+ * @{
+ * @Name Kernel CCB return slot responses
+ * @{
+ * Usage of bit-fields instead of bare integers
  * allows FW to possibly pack-in several responses for each single kCCB command.
  */
-#define RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED   (1U << 0) /* Command executed (return status from FW) */
-#define RGXFWIF_KCCB_RTN_SLOT_CLEANUP_BUSY   (1U << 1) /* A cleanup was requested but resource busy */
-#define RGXFWIF_KCCB_RTN_SLOT_POLL_FAILURE   (1U << 2) /* Poll failed in FW for a HW operation to complete */
 
-#define RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE            0x0U      /* Reset value of a kCCB return slot (set by host) */
+#define RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED   (1U << 0) /*!< Command executed (return status from FW) */
+#define RGXFWIF_KCCB_RTN_SLOT_CLEANUP_BUSY   (1U << 1) /*!< A cleanup was requested but resource busy */
+#define RGXFWIF_KCCB_RTN_SLOT_POLL_FAILURE   (1U << 2) /*!< Poll failed in FW for a HW operation to complete */
+
+#define RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE            0x0U      /*!< Reset value of a kCCB return slot (set by host) */
+/*!
+ * @} End of Name Kernel CCB return slot responses
+ * @} End of AddToGroup KCCBTypes
+ */
 
 typedef struct
 {
@@ -1868,10 +1956,29 @@ typedef struct
 
        IMG_DEV_VIRTADDR        RGXFW_ALIGN sPDSExecBase; /*!< PDS execution base */
        IMG_DEV_VIRTADDR        RGXFW_ALIGN sUSCExecBase; /*!< USC execution base */
+       IMG_DEV_VIRTADDR        RGXFW_ALIGN sFBCDCStateTableBase; /*!< FBCDC bindless texture state table base */
+       IMG_DEV_VIRTADDR        RGXFW_ALIGN sFBCDCLargeStateTableBase;
+       IMG_DEV_VIRTADDR        RGXFW_ALIGN sTextureHeapBase; /*!< Texture state base */
 
-       IMG_UINT32              ui32FilterFlags;
+       IMG_UINT64              RGXFW_ALIGN ui64HWPerfFilter; /*! Event filter for Firmware events */
 
-       RGXFWIF_SIGBUF_CTL      asSigBufCtl[RGXFWIF_DM_DEFAULT_MAX]; /*!< Signature and Checksum Buffers for DMs */
+       IMG_DEV_VIRTADDR        RGXFW_ALIGN sSLC3FenceDevVAddr;
+
+       IMG_UINT32              RGXFW_ALIGN aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_LAST];
+
+       RGXFWIF_SIGBUF_CTL      asSigBufCtl[RGXFWIF_DM_MAX]; /*!< Signature and Checksum Buffers for DMs */
+
+       RGXFWIF_PDVFS_OPP       sPDVFSOPPInfo;
+
+       RGXFWIF_DMA_ADDR        sCorememDataStore; /*!< Firmware coremem data */
+
+       RGXFWIF_COUNTER_DUMP_CTL sCounterDumpCtl;
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+       RGXFWIF_FIRMWARE_GCOV_CTL sFirmwareGcovCtl; /*!< Firmware gcov buffer control */
+#endif
+
+       IMG_UINT32              ui32FilterFlags;
 
        PRGXFWIF_RUNTIME_CFG    sRuntimeCfg; /*!<  Firmware Runtime configuration */
 
@@ -1880,18 +1987,11 @@ typedef struct
 #if defined(SUPPORT_TBI_INTERFACE)
        PRGXFWIF_TBIBUF         sTBIBuf; /*!< Tbi log buffer */
 #endif
-       IMG_UINT64              RGXFW_ALIGN ui64HWPerfFilter; /*! Event filter for Firmware events */
 
        PRGXFWIF_GPU_UTIL_FWCB  sGpuUtilFWCbCtl; /*!< GPU utilization buffer */
        PRGXFWIF_REG_CFG        sRegCfg; /*!< Firmware register user configuration */
        PRGXFWIF_HWPERF_CTL     sHWPerfCtl; /*!< HWPerf counter block configuration.*/
 
-       RGXFWIF_COUNTER_DUMP_CTL sCounterDumpCtl;
-
-#if defined(SUPPORT_FIRMWARE_GCOV)
-       RGXFWIF_FIRMWARE_GCOV_CTL sFirmwareGcovCtl; /*!< Firmware gcov buffer control */
-#endif
-
        RGXFWIF_DEV_VIRTADDR    sAlignChecks; /*!< Array holding Server structures alignment data */
 
        IMG_UINT32              ui32InitialCoreClockSpeed; /*!< Core clock speed at FW boot time */
@@ -1906,14 +2006,8 @@ typedef struct
 
        IMG_UINT32              ui32JonesDisableMask;
 
-       RGXFWIF_DMA_ADDR        sCorememDataStore; /*!< Firmware coremem data */
-
        FW_PERF_CONF            eFirmwarePerf; /*!< Firmware performance counter config */
 
-       IMG_DEV_VIRTADDR        RGXFW_ALIGN sSLC3FenceDevVAddr;
-
-       RGXFWIF_PDVFS_OPP       sPDVFSOPPInfo;
-
        /**
         * FW Pointer to memory containing core clock rate in Hz.
         * Firmware (PDVFS) updates the memory when running on non primary FW thread
@@ -1926,7 +2020,6 @@ typedef struct
 #endif
 
        RGXFWIF_GPIO_VAL_MODE   eGPIOValidationMode;
-       IMG_UINT32              RGXFW_ALIGN aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_LAST];
 
        RGX_HWPERF_BVNC         sBvncKmFeatureFlags; /*!< Used in HWPerf for decoding BVNC Features*/
 
@@ -1950,6 +2043,13 @@ typedef struct
        IMG_UINT32              ui32OSKickTest;
 #endif
 
+       /* Value to write into RGX_CR_TFBC_COMPRESSION_CONTROL */
+       IMG_UINT32              ui32TFBCCompressionControl;
+
+#if defined(SUPPORT_AUTOVZ)
+       IMG_UINT32              ui32VzWdgPeriod;
+#endif
+
 } UNCACHED_ALIGN RGXFWIF_SYSINIT;
 
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
@@ -2054,19 +2154,19 @@ static_assert((RGXFWIF_TIME_CORR_ARRAY_SIZE & (RGXFWIF_TIME_CORR_ARRAY_SIZE - 1U
 
 typedef struct
 {
-       RGXFWIF_TIME_CORR sTimeCorr[RGXFWIF_TIME_CORR_ARRAY_SIZE];
-       IMG_UINT32        ui32TimeCorrSeqCount;
+       RGXFWIF_TIME_CORR      sTimeCorr[RGXFWIF_TIME_CORR_ARRAY_SIZE];
+       IMG_UINT32             ui32TimeCorrSeqCount;
+
+       /* Compatibility and other flags */
+       IMG_UINT32             ui32GpuUtilFlags;
 
        /* Last GPU state + OS time of the last state update */
        IMG_UINT64 RGXFW_ALIGN ui64LastWord;
 
        /* Counters for the amount of time the GPU was active/idle/blocked */
        IMG_UINT64 RGXFW_ALIGN aui64StatsCounters[RGXFWIF_GPU_UTIL_STATE_NUM];
-
-       IMG_UINT32 ui32GpuUtilFlags; /* Compatibility and other flags */
 } UNCACHED_ALIGN RGXFWIF_GPU_UTIL_FWCB;
 
-
 typedef struct
 {
        IMG_UINT32           ui32RenderTargetIndex;             //Render number
@@ -2079,74 +2179,53 @@ typedef struct
        IMG_UINT32           ui32RTACtlFlags; /* Compatibility and other flags */
 } UNCACHED_ALIGN RGXFWIF_RTA_CTL;
 
+/*!
+ * @InGroup RenderTarget
+ * @Brief Firmware Freelist holding usage state of the Parameter Buffers
+ */
 typedef struct
 {
-       IMG_DEV_VIRTADDR                RGXFW_ALIGN psFreeListDevVAddr;
-       IMG_UINT64                              RGXFW_ALIGN ui64CurrentDevVAddr;
-       IMG_UINT32                              ui32CurrentStackTop;
-       IMG_UINT32                              ui32MaxPages;
-       IMG_UINT32                              ui32GrowPages;
-       IMG_UINT32                              ui32CurrentPages; /* HW pages */
-       IMG_UINT32                              ui32AllocatedPageCount;
-       IMG_UINT32                              ui32AllocatedMMUPageCount;
+       IMG_DEV_VIRTADDR        RGXFW_ALIGN psFreeListDevVAddr; /*!< Freelist page table base */
+       IMG_UINT64              RGXFW_ALIGN ui64CurrentDevVAddr;/*!< Freelist page table entry for current free page  */
+       IMG_UINT32              ui32CurrentStackTop;            /*!< Freelist current free page  */
+       IMG_UINT32              ui32MaxPages;                   /*!< Max no. of pages can be added to the freelist */
+       IMG_UINT32              ui32GrowPages;                  /*!< No pages to add in each freelist grow */
+       IMG_UINT32              ui32CurrentPages;               /*!< Total no. of pages made available to the PM HW */
+       IMG_UINT32              ui32AllocatedPageCount;         /*!< No. of pages allocated by PM HW */
+       IMG_UINT32              ui32AllocatedMMUPageCount;      /*!< No. of pages allocated for GPU MMU for PM*/
 #if defined(SUPPORT_SHADOW_FREELISTS)
-       IMG_UINT32                              ui32HWRCounter;
+       IMG_UINT32              ui32HWRCounter;
        PRGXFWIF_FWMEMCONTEXT   psFWMemContext;
 #endif
-       IMG_UINT32                              ui32FreeListID;
-       IMG_BOOL                                bGrowPending;
-       IMG_UINT32                              ui32ReadyPages; /* Pages that should be used only when OOM is reached */
-       IMG_UINT32                              ui32FreelistFlags; /* Compatibility and other flags */
+       IMG_UINT32              ui32FreeListID;                 /*!< Unique Freelist ID */
+       IMG_BOOL                bGrowPending;                   /*!< Freelist grow is pending */
+       IMG_UINT32              ui32ReadyPages;                 /*!< Reserved pages to be used only on PM OOM event */
+       IMG_UINT32              ui32FreelistFlags;              /*!< Compatibility and other flags */
+#if defined(SUPPORT_AGP)
+       IMG_UINT32              ui32PmGlobalPb;                 /*!< PM Global PB on which Freelist is loaded */
+#endif
 } UNCACHED_ALIGN RGXFWIF_FREELIST;
 
 /*!
  ******************************************************************************
- * Parameter Management (PM) control data for RGX
- *****************************************************************************/
-
-/* Used only by Firmware but defined here for similarity with Volcanic where it's required for SW TRP */
-
-typedef enum
-{
-       RGXFW_SPM_STATE_NONE = 0,
-       RGXFW_SPM_STATE_PR_BLOCKED,
-       RGXFW_SPM_STATE_WAIT_FOR_GROW,
-       RGXFW_SPM_STATE_WAIT_FOR_HW,
-       RGXFW_SPM_STATE_PR_RUNNING,
-       RGXFW_SPM_STATE_PR_AVOIDED,
-       RGXFW_SPM_STATE_PR_EXECUTED,
-} RGXFW_SPM_STATE;
-
-/*!
- ******************************************************************************
- * @Brief RGX firmware SPM Control Data:
- *  This structure holds all the internal SPM control Data of the firmware.
- *****************************************************************************/
-typedef struct
-{
-       RGXFW_SPM_STATE                 eSPMState; /*!< Current state of TA OOM event */                                                        /*!< Current owner of this PM data structure */
-       RGXFWIF_UFO                             sPartialRenderTA3DFence;                        /*!< TA/3D fence object holding the value to let through the 3D partial command */
-       RGXFWIF_FWCOMMONCONTEXT *ps3dContext;                                           /*!< Pointer to the 3D Context holding the partial render */
-       RGXFWIF_CCB_CMD_HEADER  *psCmdHeader;                                           /*!< Pointer to the header of the command holding the partial render */
-       struct RGXFWIF_CMD3D_STRUCT                     *ps3DCmd;                                                       /*!< Pointer to the 3D command holding the partial render register info */
-       RGXFWIF_PRBUFFER                *apsPRBuffer[RGXFWIF_PRBUFFER_MAXSUPPORTED];    /*!< Array of pointers to PR Buffers which may be used if partial render is needed */
-       RGXFW_FREELIST_TYPE             eOOMFreeListType;                                       /*!< Indicates the freelist type that went out of memory */
-       bool                                    b3DMemFreeDetected;                                     /*!< Indicates if a 3D Memory Free has been detected, which resolves OOM */
-} RGXFW_SPMCTL;
-
-/*!
- ******************************************************************************
  * HWRTData
  *****************************************************************************/
 
 /* HWRTData flags */
 /* Deprecated flags 1:0 */
-#define HWRTDATA_HAS_LAST_TA              (1U << 2)
-#define HWRTDATA_PARTIAL_RENDERED         (1U << 3)
-#define HWRTDATA_DISABLE_TILE_REORDERING  (1U << 4)
-#define HWRTDATA_NEED_BRN65101_BLIT       (1U << 5)
-#define HWRTDATA_FIRST_BRN65101_STRIP     (1U << 6)
-#define HWRTDATA_NEED_BRN67182_2ND_RENDER (1U << 7)
+#define HWRTDATA_HAS_LAST_TA              (1UL << 2)
+#define HWRTDATA_PARTIAL_RENDERED         (1UL << 3)
+#define HWRTDATA_DISABLE_TILE_REORDERING  (1UL << 4)
+#define HWRTDATA_NEED_BRN65101_BLIT       (1UL << 5)
+#define HWRTDATA_FIRST_BRN65101_STRIP     (1UL << 6)
+#define HWRTDATA_NEED_BRN67182_2ND_RENDER (1UL << 7)
+#if defined(SUPPORT_AGP)
+#define HWRTDATA_GLOBAL_PB_NUMBER_BIT0    (1UL << 8)
+#if defined(SUPPORT_AGP4)
+#define HWRTDATA_GLOBAL_PB_NUMBER_BIT1    (1UL << 9)
+#endif
+#define HWRTDATA_GEOM_NEEDS_RESUME        (1UL << 10)
+#endif
 
 typedef enum
 {
@@ -2170,41 +2249,10 @@ typedef struct
 {
        IMG_BOOL                                                        bTACachesNeedZeroing;
 
-} UNCACHED_ALIGN RGXFWIF_HWRTDATA_COMMON;
-
-typedef struct
-{
-       RGXFWIF_DEV_VIRTADDR                            sHWRTDataCommonFwAddr;
-
-       IMG_UINT32                                                      ui32HWRTDataFlags;
-       RGXFWIF_RTDATA_STATE                            eState;
-
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN psPMMListDevVAddr; /*!< MList Data Store */
-
-       IMG_UINT64                                                      RGXFW_ALIGN ui64VCECatBase[4];
-       IMG_UINT64                                                      RGXFW_ALIGN ui64VCELastCatBase[4];
-       IMG_UINT64                                                      RGXFW_ALIGN ui64TECatBase[4];
-       IMG_UINT64                                                      RGXFW_ALIGN ui64TELastCatBase[4];
-       IMG_UINT64                                                      RGXFW_ALIGN ui64AlistCatBase;
-       IMG_UINT64                                                      RGXFW_ALIGN ui64AlistLastCatBase;
-
-       IMG_UINT64                                                      RGXFW_ALIGN ui64PMAListStackPointer;
-       IMG_UINT32                                                      ui32PMMListStackPointer;
-
-       PRGXFWIF_FREELIST                                       RGXFW_ALIGN apsFreeLists[RGXFW_MAX_FREELISTS];
-       IMG_UINT32                                                      aui32FreeListHWRSnapshot[RGXFW_MAX_FREELISTS];
-
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN psVHeapTableDevVAddr;
-
-       RGXFWIF_CLEANUP_CTL                                     sCleanupState;
-
-       RGXFWIF_RTA_CTL                                         sRTACtl;
-
        IMG_UINT32                                                      ui32ScreenPixelMax;
        IMG_UINT64                                                      RGXFW_ALIGN ui64MultiSampleCtl;
        IMG_UINT64                                                      ui64FlippedMultiSampleCtl;
        IMG_UINT32                                                      ui32TPCStride;
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN sTailPtrsDevVAddr;
        IMG_UINT32                                                      ui32TPCSize;
        IMG_UINT32                                                      ui32TEScreen;
        IMG_UINT32                                                      ui32MTileStride;
@@ -2217,15 +2265,59 @@ typedef struct
        IMG_UINT32                                                      ui32ISPMergeUpperY;
        IMG_UINT32                                                      ui32ISPMergeScaleX;
        IMG_UINT32                                                      ui32ISPMergeScaleY;
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN sMacrotileArrayDevVAddr;
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN sRgnHeaderDevVAddr;
-       IMG_DEV_VIRTADDR                                        RGXFW_ALIGN sRTCDevVAddr;
-       IMG_UINT64                                                      RGXFW_ALIGN uiRgnHeaderSize;
+       IMG_UINT32                                                      uiRgnHeaderSize;
        IMG_UINT32                                                      ui32ISPMtileSize;
+} UNCACHED_ALIGN RGXFWIF_HWRTDATA_COMMON;
+
+/*!
+ * @InGroup RenderTarget
+ * @Brief Firmware Render Target data i.e. HWRTDATA used to hold the PM context
+ */
+typedef struct
+{
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN psPMMListDevVAddr;                  /*!< MList Data Store */
+
+       IMG_UINT64                      RGXFW_ALIGN ui64VCECatBase[4];                  /*!< VCE Page Catalogue base */
+       IMG_UINT64                      RGXFW_ALIGN ui64VCELastCatBase[4];
+       IMG_UINT64                      RGXFW_ALIGN ui64TECatBase[4];                   /*!< TE Page Catalogue base */
+       IMG_UINT64                      RGXFW_ALIGN ui64TELastCatBase[4];
+       IMG_UINT64                      RGXFW_ALIGN ui64AlistCatBase;                   /*!< Alist Page Catalogue base */
+       IMG_UINT64                      RGXFW_ALIGN ui64AlistLastCatBase;
+
+       IMG_UINT64                      RGXFW_ALIGN ui64PMAListStackPointer;            /*!< Freelist page table entry for current Mlist page  */
+       IMG_UINT32                      ui32PMMListStackPointer;                        /*!< Current Mlist page */
+
+       RGXFWIF_DEV_VIRTADDR            sHWRTDataCommonFwAddr;                          /*!< Render target dimension dependent data */
+
+       IMG_UINT32                      ui32HWRTDataFlags;
+       RGXFWIF_RTDATA_STATE            eState;                                         /*!< Current workload processing state of HWRTDATA */
+
+       PRGXFWIF_FREELIST               RGXFW_ALIGN apsFreeLists[RGXFW_MAX_FREELISTS];  /*!< Freelist to use */
+       IMG_UINT32                      aui32FreeListHWRSnapshot[RGXFW_MAX_FREELISTS];
+
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN psVHeapTableDevVAddr;               /*!< VHeap table base */
+
+       RGXFWIF_CLEANUP_CTL             sCleanupState;                                  /*!< Render target clean up state */
+
+       RGXFWIF_RTA_CTL                 sRTACtl;                                        /*!< Render target array data */
+
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN sTailPtrsDevVAddr;                  /*!< Tail pointers base */
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN sMacrotileArrayDevVAddr;            /*!< Macrotiling array base */
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN sRgnHeaderDevVAddr;                 /*!< Region headers base */
+       IMG_DEV_VIRTADDR                RGXFW_ALIGN sRTCDevVAddr;                       /*!< Render target cache base */
 #if defined(RGX_FIRMWARE)
-       struct RGXFWIF_FWCOMMONCONTEXT_*        RGXFW_ALIGN psOwnerGeom;
+       struct RGXFWIF_FWCOMMONCONTEXT_* RGXFW_ALIGN psOwnerGeom;
 #else
-       RGXFWIF_DEV_VIRTADDR                            RGXFW_ALIGN pui32OwnerGeomNotUsedByHost;
+       RGXFWIF_DEV_VIRTADDR            RGXFW_ALIGN pui32OwnerGeomNotUsedByHost;
+#endif
+#if defined(SUPPORT_TRP)
+       IMG_UINT32                      ui32KickFlagsCopy;
+       IMG_UINT32                      ui32TRPState;
+       IMG_UINT32                      ui32TEPageCopy;
+       IMG_UINT32                      ui32VCEPageCopy;
+#endif
+#if defined(SUPPORT_AGP)
+       IMG_BOOL                        bTACachesNeedZeroing;
 #endif
 } UNCACHED_ALIGN RGXFWIF_HWRTDATA;
 
index e595094..13844ad 100644 (file)
@@ -50,6 +50,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgx_common.h"
 #include "powervr/mem_types.h"
 
+/* Indicates the number of RTDATAs per RTDATASET */
+#if defined(SUPPORT_AGP)
+#define RGXMKIF_NUM_RTDATAS           4U
+#define RGXMKIF_NUM_GEOMDATAS         4U
+#define RGXMKIF_NUM_RTDATA_FREELISTS  12U /* RGXMKIF_NUM_RTDATAS * RGXFW_MAX_FREELISTS */
+#define RGX_NUM_GEOM_CORES           (2U)
+#else
+#define RGXMKIF_NUM_RTDATAS           2U
+#define RGXMKIF_NUM_GEOMDATAS         1U
+#define RGXMKIF_NUM_RTDATA_FREELISTS  2U  /* RGXMKIF_NUM_RTDATAS * RGXFW_MAX_FREELISTS */
+#define RGX_NUM_GEOM_CORES           (1U)
+#endif
+
 /* Maximum number of UFOs in a CCB command.
  * The number is based on having 32 sync prims (as originally), plus 32 sync
  * checkpoints.
@@ -118,13 +131,17 @@ typedef enum
        RGXFWIF_PRBUFFER_UNBACKING_PENDING,
 }RGXFWIF_PRBUFFER_STATE;
 
+/*!
+ * @InGroup RenderTarget
+ * @Brief OnDemand Z/S/MSAA Buffers
+ */
 typedef struct
 {
-       IMG_UINT32                              ui32BufferID;                           /*!< Buffer ID*/
-       IMG_BOOL                                bOnDemand;                                      /*!< Needs On-demand Z/S/MSAA Buffer allocation */
-       RGXFWIF_PRBUFFER_STATE  eState;                                         /*!< Z/S/MSAA -Buffer state */
-       RGXFWIF_CLEANUP_CTL             sCleanupState;                          /*!< Cleanup state */
-       IMG_UINT32                              ui32PRBufferFlags;              /*!< Compatibility and other flags */
+       IMG_UINT32              ui32BufferID;           /*!< Buffer ID*/
+       IMG_BOOL                bOnDemand;              /*!< Needs On-demand Z/S/MSAA Buffer allocation */
+       RGXFWIF_PRBUFFER_STATE  eState;                 /*!< Z/S/MSAA -Buffer state */
+       RGXFWIF_CLEANUP_CTL     sCleanupState;          /*!< Cleanup state */
+       IMG_UINT32              ui32PRBufferFlags;      /*!< Compatibility and other flags */
 } UNCACHED_ALIGN RGXFWIF_PRBUFFER;
 
 /*
@@ -185,7 +202,15 @@ typedef struct
                                         *    Points to commands not ready, i.e.
                                         *    fence dependencies are not met. */
        IMG_UINT32  ui32WrapMask;       /*!< Offset wrapping mask, total capacity
-                                        *    in bytes of the CCB-1 */
+                                             in bytes of the CCB-1 */
+#if defined(SUPPORT_AGP)
+       IMG_UINT32  ui32ReadOffset2;
+#if defined(SUPPORT_AGP4)
+       IMG_UINT32  ui32ReadOffset3;
+       IMG_UINT32  ui32ReadOffset4;
+#endif
+#endif
+
 } UNCACHED_ALIGN RGXFWIF_CCCB_CTL;
 
 
@@ -193,25 +218,39 @@ typedef IMG_UINT32 RGXFW_FREELIST_TYPE;
 
 #define RGXFW_LOCAL_FREELIST     IMG_UINT32_C(0)
 #define RGXFW_GLOBAL_FREELIST    IMG_UINT32_C(1)
+#if defined(SUPPORT_AGP)
+#define RGXFW_GLOBAL2_FREELIST   IMG_UINT32_C(2)
+#define RGXFW_MAX_FREELISTS      (RGXFW_GLOBAL2_FREELIST + 1U)
+#else
 #define RGXFW_MAX_FREELISTS      (RGXFW_GLOBAL_FREELIST + 1U)
+#endif
+#define RGXFW_MAX_HWFREELISTS    (2U)
 
+/*!
+ * @Defgroup ContextSwitching Context switching data interface
+ * @Brief Types grouping data structures and defines used in realising the Context Switching (CSW) functionality
+ * @{
+ */
 
+/*!
+ * @Brief GEOM DM or TA register controls for context switch
+ */
 typedef struct
 {
-       IMG_UINT64      uTAReg_VDM_CONTEXT_STATE_BASE_ADDR;
+       IMG_UINT64      uTAReg_VDM_CONTEXT_STATE_BASE_ADDR; /*!< The base address of the VDM's context state buffer */
        IMG_UINT64      uTAReg_VDM_CONTEXT_STATE_RESUME_ADDR;
-       IMG_UINT64      uTAReg_TA_CONTEXT_STATE_BASE_ADDR;
+       IMG_UINT64      uTAReg_TA_CONTEXT_STATE_BASE_ADDR; /*!< The base address of the TA's context state buffer */
 
        struct
        {
-               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK0;
-               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK1;
-               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK2;
+               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK0; /*!< VDM context store task 0 */
+               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK1; /*!< VDM context store task 1 */
+               IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK2; /*!< VDM context store task 2 */
 
                /* VDM resume state update controls */
-               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK0;
-               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK1;
-               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK2;
+               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK0; /*!< VDM context resume task 0 */
+               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK1; /*!< VDM context resume task 1 */
+               IMG_UINT64      uTAReg_VDM_CONTEXT_RESUME_TASK2; /*!< VDM context resume task 2 */
 
                IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK3;
                IMG_UINT64      uTAReg_VDM_CONTEXT_STORE_TASK4;
@@ -221,6 +260,7 @@ typedef struct
        } asTAState[2];
 
 } RGXFWIF_TAREGISTERS_CSWITCH;
+/*! @} End of Defgroup ContextSwitching */
 
 #define RGXFWIF_TAREGISTERS_CSWITCH_SIZE sizeof(RGXFWIF_TAREGISTERS_CSWITCH)
 
@@ -238,9 +278,13 @@ typedef struct
 
 } RGXFWIF_CDM_REGISTERS_CSWITCH;
 
+/*!
+ * @InGroup ContextSwitching
+ * @Brief Render context static register controls for context switch
+ */
 typedef struct
 {
-       RGXFWIF_TAREGISTERS_CSWITCH     RGXFW_ALIGN sCtxSwitch_Regs;    /*!< Geom registers for ctx switch */
+       RGXFWIF_TAREGISTERS_CSWITCH     RGXFW_ALIGN asCtxSwitch_GeomRegs[RGX_NUM_GEOM_CORES];   /*!< Geom registers for ctx switch */
 } RGXFWIF_STATIC_RENDERCONTEXT_STATE;
 
 #define RGXFWIF_STATIC_RENDERCONTEXT_SIZE sizeof(RGXFWIF_STATIC_RENDERCONTEXT_STATE)
index d66adf8..e41e400 100644 (file)
@@ -53,8 +53,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGX_USCCODE_HEAP_IDENT              "USC Code"                  /*!< RGX USC Code Heap Identifier */
 #define RGX_VK_CAPT_REPLAY_HEAP_IDENT       "Vulkan Capture Replay"     /*!< RGX Vulkan capture replay buffer Heap Identifier */
 #define RGX_SIGNALS_HEAP_IDENT              "Signals"                   /*!< Signals Heap Identifier */
+#define RGX_FBCDC_HEAP_IDENT                "FBCDC"                     /*!< RGX FBCDC State Table Heap Identifier */
+#define RGX_FBCDC_LARGE_HEAP_IDENT          "Large FBCDC"               /*!< RGX Large FBCDC State Table Heap Identifier */
 #define RGX_CMP_MISSION_RMW_HEAP_IDENT      "Compute Mission RMW"       /*!< Compute Mission RMW Heap Identifier */
 #define RGX_CMP_SAFETY_RMW_HEAP_IDENT       "Compute Safety RMW"        /*!< Compute Safety RMW Heap Identifier */
+#define RGX_TEXTURE_STATE_HEAP_IDENT        "Texture State"             /*!< Texture State Heap Identifier */
 #define RGX_VISIBILITY_TEST_HEAP_IDENT      "Visibility Test"           /*!< Visibility Test Heap Identifier */
 
 /* Services client internal heap identification */
index d64a0b5..fa711b0 100644 (file)
@@ -60,6 +60,7 @@ extern "C" {
 #include "img_defs.h"
 
 #include "rgx_common.h"
+#include "rgx_hwperf_common.h"
 #include "pvrsrv_tlcommon.h"
 #include "pvrsrv_sync_km.h"
 
@@ -141,402 +142,8 @@ static_assert(RGX_FEATURE_NUM_CLUSTERS <= 16U, "Cluster count too large for HWPe
 /*! The number of counters supported in each non-mux counter block */
 #define RGX_HWPERF_MAX_CUSTOM_CNTRS 8U
 
-
-/******************************************************************************
- * Packet Event Type Enumerations
- *****************************************************************************/
-
-/*! Type used to encode the event that generated the packet.
- * NOTE: When this type is updated the corresponding hwperfbin2json tool
- * source needs to be updated as well. The RGX_HWPERF_EVENT_MASK_* macros will
- * also need updating when adding new types.
- *
- * @par
- * The event type values are incrementing integers for use as a shift ordinal
- * in the event filtering process at the point events are generated.
- * This scheme thus implies a limit of 63 event types.
- */
-
-typedef IMG_UINT32 RGX_HWPERF_EVENT_TYPE;
-
-#define RGX_HWPERF_INVALID                             0x00U /*!< Invalid. Reserved value. */
-
-/*! FW types 0x01..0x06 */
-#define RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE   0x01U
-
-#define RGX_HWPERF_FW_BGSTART                  0x01U /*!< Background task processing start */
-#define RGX_HWPERF_FW_BGEND                            0x02U /*!< Background task end */
-#define RGX_HWPERF_FW_IRQSTART                 0x03U /*!< IRQ task processing start */
-
-#define RGX_HWPERF_FW_IRQEND                   0x04U /*!< IRQ task end */
-#define RGX_HWPERF_FW_DBGSTART                 0x05U /*!< Debug event start */
-#define RGX_HWPERF_FW_DBGEND                   0x06U /*!< Debug event end */
-
-#define RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE            0x06U
-
-/*! HW types 0x07..0x19 */
-#define RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE  0x07U
-
-#define RGX_HWPERF_HW_PMOOM_TAPAUSE            0x07U /*!< TA Pause at PM Out of Memory */
-
-#define RGX_HWPERF_HW_TAKICK                   0x08U /*!< TA task started */
-#define RGX_HWPERF_HW_TAFINISHED               0x09U /*!< TA task finished */
-#define RGX_HWPERF_HW_3DTQKICK                 0x0AU /*!< 3D TQ started */
-#define RGX_HWPERF_HW_3DKICK                   0x0BU /*!< 3D task started */
-#define RGX_HWPERF_HW_3DFINISHED               0x0CU /*!< 3D task finished */
-#define RGX_HWPERF_HW_CDMKICK                  0x0DU /*!< CDM task started */
-#define RGX_HWPERF_HW_CDMFINISHED              0x0EU /*!< CDM task finished */
-#define RGX_HWPERF_HW_TLAKICK                  0x0FU /*!< TLA task started */
-#define RGX_HWPERF_HW_TLAFINISHED              0x10U /*!< TLS task finished */
-#define RGX_HWPERF_HW_3DSPMKICK                        0x11U /*!< 3D SPM task started */
-#define RGX_HWPERF_HW_PERIODIC                 0x12U /*!< Periodic event with updated HW counters */
-#define RGX_HWPERF_HW_RTUKICK                  0x13U /*!< Reserved, future use */
-#define RGX_HWPERF_HW_RTUFINISHED              0x14U /*!< Reserved, future use */
-#define RGX_HWPERF_HW_SHGKICK                  0x15U /*!< Reserved, future use */
-#define RGX_HWPERF_HW_SHGFINISHED              0x16U /*!< Reserved, future use */
-#define RGX_HWPERF_HW_3DTQFINISHED             0x17U /*!< 3D TQ finished */
-#define RGX_HWPERF_HW_3DSPMFINISHED            0x18U /*!< 3D SPM task finished */
-
-#define RGX_HWPERF_HW_PMOOM_TARESUME   0x19U /*!< TA Resume after PM Out of Memory */
-
-/*! HW_EVENT_RANGE0 used up. Use next empty range below to add new hardware events */
-#define RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE   0x19U
-
-/*! other types 0x1A..0x1F */
-#define RGX_HWPERF_CLKS_CHG                            0x1AU /*!< Clock speed change in GPU */
-#define RGX_HWPERF_GPU_STATE_CHG               0x1BU /*!< GPU work state change */
-
-/*! power types 0x20..0x27 */
-#define RGX_HWPERF_PWR_EST_RANGE_FIRST_TYPE    0x20U
-#define RGX_HWPERF_PWR_EST_REQUEST             0x20U /*!< Power estimate requested (via GPIO) */
-#define RGX_HWPERF_PWR_EST_READY               0x21U /*!< Power estimate inputs ready */
-#define RGX_HWPERF_PWR_EST_RESULT              0x22U /*!< Power estimate result calculated */
-#define RGX_HWPERF_PWR_EST_RANGE_LAST_TYPE     0x22U
-
-#define RGX_HWPERF_PWR_CHG                             0x23U /*!< Power state change */
-
-/*! HW_EVENT_RANGE1 0x28..0x2F, for accommodating new hardware events */
-#define RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE  0x28U
-
-#define RGX_HWPERF_HW_TDMKICK                  0x28U /*!< TDM task started */
-#define RGX_HWPERF_HW_TDMFINISHED              0x29U /*!< TDM task finished */
-#define RGX_HWPERF_HW_NULLKICK                 0x2AU /*!< NULL event */
-
-#define RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE 0x2AU
-
-/*! context switch types 0x30..0x31 */
-#define RGX_HWPERF_CSW_START                   0x30U /*!< HW context store started */
-#define RGX_HWPERF_CSW_FINISHED                        0x31U /*!< HW context store finished */
-
-/*! DVFS events */
-#define RGX_HWPERF_DVFS                                        0x32U /*!< Dynamic voltage/frequency scaling events */
-
-/*! firmware misc 0x38..0x39 */
-#define RGX_HWPERF_UFO                                 0x38U /*!< FW UFO Check / Update */
-#define RGX_HWPERF_FWACT                               0x39U /*!< FW Activity notification */
-
-/*! last */
-#define RGX_HWPERF_LAST_TYPE                   0x3BU
-
-/*! This enumeration must have a value that is a power of two as it is
- * used in masks and a filter bit field (currently 64 bits long).
- */
-#define RGX_HWPERF_MAX_TYPE                            0x40U
-
-static_assert(RGX_HWPERF_LAST_TYPE < RGX_HWPERF_MAX_TYPE, "Too many HWPerf event types");
-
-/*! Macro used to check if an event type ID is present in the known set of hardware type events */
-#define HWPERF_PACKET_IS_HW_TYPE(_etype)       (((_etype) >= RGX_HWPERF_HW_EVENT_RANGE0_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE0_LAST_TYPE) || \
-                                                                                        ((_etype) >= RGX_HWPERF_HW_EVENT_RANGE1_FIRST_TYPE && (_etype) <= RGX_HWPERF_HW_EVENT_RANGE1_LAST_TYPE))
-
-/*! Macro used to check if an event type ID is present in the known set of firmware type events */
-#define HWPERF_PACKET_IS_FW_TYPE(_etype)                                       \
-       ((_etype) >= RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE &&    \
-        (_etype) <= RGX_HWPERF_FW_EVENT_RANGE_LAST_TYPE)
-
-
-typedef enum {
-       RGX_HWPERF_HOST_INVALID   = 0x00,           /*!< Invalid, do not use. */
-       RGX_HWPERF_HOST_ENQ       = 0x01,           /*!< ``0x01`` Kernel driver has queued GPU work.
-                                                    See RGX_HWPERF_HOST_ENQ_DATA */
-       RGX_HWPERF_HOST_UFO       = 0x02,           /*!< ``0x02`` UFO updated by the driver.
-                                                    See RGX_HWPERF_HOST_UFO_DATA */
-       RGX_HWPERF_HOST_ALLOC     = 0x03,           /*!< ``0x03`` Resource allocated.
-                                                    See RGX_HWPERF_HOST_ALLOC_DATA */
-       RGX_HWPERF_HOST_CLK_SYNC  = 0x04,           /*!< ``0x04`` GPU / Host clocks correlation data.
-                                                    See RGX_HWPERF_HOST_CLK_SYNC_DATA */
-       RGX_HWPERF_HOST_FREE      = 0x05,           /*!< ``0x05`` Resource freed,
-                                                    See RGX_HWPERF_HOST_FREE_DATA */
-       RGX_HWPERF_HOST_MODIFY    = 0x06,           /*!< ``0x06`` Resource modified / updated.
-                                                    See RGX_HWPERF_HOST_MODIFY_DATA */
-       RGX_HWPERF_HOST_DEV_INFO  = 0x07,           /*!< ``0x07`` Device Health status.
-                                                    See RGX_HWPERF_HOST_DEV_INFO_DATA */
-       RGX_HWPERF_HOST_INFO      = 0x08,           /*!< ``0x08`` Device memory usage information.
-                                                    See RGX_HWPERF_HOST_INFO_DATA */
-       RGX_HWPERF_HOST_SYNC_FENCE_WAIT = 0x09,     /*!< ``0x09`` Wait for sync event.
-                                                    See RGX_HWPERF_HOST_SYNC_FENCE_WAIT_DATA */
-       RGX_HWPERF_HOST_SYNC_SW_TL_ADVANCE  = 0x0A, /*!< ``0x0A`` Software timeline advanced.
-                                                    See RGX_HWPERF_HOST_SYNC_SW_TL_ADV_DATA */
-
-       /*! last */
-       RGX_HWPERF_HOST_LAST_TYPE,
-
-       /*! This enumeration must have a value that is a power of two as it is
-        * used in masks and a filter bit field (currently 32 bits long).
-        */
-       RGX_HWPERF_HOST_MAX_TYPE  = 0x20
-} RGX_HWPERF_HOST_EVENT_TYPE;
-
-/*!< The event type values are incrementing integers for use as a shift ordinal
- * in the event filtering process at the point events are generated.
- * This scheme thus implies a limit of 31 event types.
- */
-static_assert(RGX_HWPERF_HOST_LAST_TYPE < RGX_HWPERF_HOST_MAX_TYPE, "Too many HWPerf host event types");
-
-
-/******************************************************************************
- * Packet Header Format Version 2 Types
- *****************************************************************************/
-
-/*! Major version number of the protocol in operation
- */
-#define RGX_HWPERF_V2_FORMAT 2
-
-/*! Signature ASCII pattern 'HWP2' found in the first word of a HWPerfV2 packet
- */
-#define HWPERF_PACKET_V2_SIG           0x48575032
-
-/*! Signature ASCII pattern 'HWPA' found in the first word of a HWPerfV2a packet
- */
-#define HWPERF_PACKET_V2A_SIG          0x48575041
-
-/*! Signature ASCII pattern 'HWPB' found in the first word of a HWPerfV2b packet
- */
-#define HWPERF_PACKET_V2B_SIG          0x48575042
-
-#define HWPERF_PACKET_ISVALID(_ptr) (((_ptr) == HWPERF_PACKET_V2_SIG) || ((_ptr) == HWPERF_PACKET_V2A_SIG)|| ((_ptr) == HWPERF_PACKET_V2B_SIG))
-/*!< Checks that the packet signature is one of the supported versions */
-
-/*! Type defines the HWPerf packet header common to all events. */
-typedef struct
-{
-       IMG_UINT32  ui32Sig;        /*!< Always the value HWPERF_PACKET_SIG */
-       IMG_UINT32  ui32Size;       /*!< Overall packet size in bytes */
-       IMG_UINT32  eTypeId;        /*!< Event type information field */
-       IMG_UINT32  ui32Ordinal;    /*!< Sequential number of the packet */
-       IMG_UINT64  ui64Timestamp;  /*!< Event timestamp */
-} RGX_HWPERF_V2_PACKET_HDR, *RGX_PHWPERF_V2_PACKET_HDR;
-
-#ifndef __CHECKER__
-RGX_FW_STRUCT_OFFSET_ASSERT(RGX_HWPERF_V2_PACKET_HDR, ui64Timestamp);
-
-RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_V2_PACKET_HDR);
-#endif
-
-
-/*! Mask for use with the IMG_UINT32 ui32Size header field */
-#define RGX_HWPERF_SIZE_MASK         0xFFFFU
-
-/*! This macro defines an upper limit to which the size of the largest variable
- * length HWPerf packet must fall within, currently 3KB. This constant may be
- * used to allocate a buffer to hold one packet.
- * This upper limit is policed by packet producing code.
- */
-#define RGX_HWPERF_MAX_PACKET_SIZE   0xC00U
-
-/*! Defines an upper limit to the size of a variable length packet payload.
- */
-#define RGX_HWPERF_MAX_PAYLOAD_SIZE     ((IMG_UINT32)(RGX_HWPERF_MAX_PACKET_SIZE-\
-       sizeof(RGX_HWPERF_V2_PACKET_HDR)))
-
-/*! Macro which takes a structure name and provides the packet size for
- * a fixed size payload packet, rounded up to 8 bytes to align packets
- * for 64 bit architectures. */
-#define RGX_HWPERF_MAKE_SIZE_FIXED(_struct)       ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN(sizeof(_struct), PVRSRVTL_PACKET_ALIGNMENT))))
-
-/*! Macro which takes the number of bytes written in the data payload of a
- * packet for a variable size payload packet, rounded up to 8 bytes to
- * align packets for 64 bit architectures. */
-#define RGX_HWPERF_MAKE_SIZE_VARIABLE(_size)      ((IMG_UINT32)(RGX_HWPERF_SIZE_MASK&(sizeof(RGX_HWPERF_V2_PACKET_HDR)+PVR_ALIGN((_size), PVRSRVTL_PACKET_ALIGNMENT))))
-
-/*! Macro to obtain the size of the packet */
-#define RGX_HWPERF_GET_SIZE(_packet_addr)         ((IMG_UINT16)(((_packet_addr)->ui32Size) & RGX_HWPERF_SIZE_MASK))
-
-/*! Macro to obtain the size of the packet data */
-#define RGX_HWPERF_GET_DATA_SIZE(_packet_addr)    (RGX_HWPERF_GET_SIZE(_packet_addr) - sizeof(RGX_HWPERF_V2_PACKET_HDR))
-
-/*! Masks for use with the IMG_UINT32 eTypeId header field */
-#define RGX_HWPERF_TYPEID_MASK                 0x0007FFFFU
-#define RGX_HWPERF_TYPEID_EVENT_MASK   0x00007FFFU
-#define RGX_HWPERF_TYPEID_THREAD_MASK  0x00008000U
-#define RGX_HWPERF_TYPEID_STREAM_MASK  0x00070000U
-#define RGX_HWPERF_TYPEID_META_DMA_MASK        0x00080000U
-#define RGX_HWPERF_TYPEID_M_CORE_MASK  0x00100000U
-#define RGX_HWPERF_TYPEID_OSID_MASK            0x07000000U
-
-/*! Meta thread macros for encoding the ID into the type field of a packet */
-#define RGX_HWPERF_META_THREAD_SHIFT   15U
-#define RGX_HWPERF_META_THREAD_ID0             0x0U  /*!< Meta Thread 0 ID */
-#define RGX_HWPERF_META_THREAD_ID1             0x1U  /*!< Meta Thread 1 ID */
-/*! Obsolete, kept for source compatibility */
-#define RGX_HWPERF_META_THREAD_MASK            0x1U
-/*! Stream ID macros for encoding the ID into the type field of a packet */
-#define RGX_HWPERF_STREAM_SHIFT                        16U
-/*! Meta DMA macro for encoding how the packet was generated into the type field of a packet */
-#define RGX_HWPERF_META_DMA_SHIFT              19U
-/*! Bit-shift macro used for encoding multi-core data into the type field of a packet */
-#define RGX_HWPERF_M_CORE_SHIFT                        20U
-/*! OSID bit-shift macro used for encoding OSID into type field of a packet */
-#define RGX_HWPERF_OSID_SHIFT                  24U
-typedef enum {
-       RGX_HWPERF_STREAM_ID0_FW,     /*!< Events from the Firmware/GPU */
-       RGX_HWPERF_STREAM_ID1_HOST,   /*!< Events from the Server host driver component */
-       RGX_HWPERF_STREAM_ID2_CLIENT, /*!< Events from the Client host driver component */
-       RGX_HWPERF_STREAM_ID_LAST,
-} RGX_HWPERF_STREAM_ID;
-
-/* Checks if all stream IDs can fit under RGX_HWPERF_TYPEID_STREAM_MASK. */
-static_assert(((IMG_UINT32)RGX_HWPERF_STREAM_ID_LAST - 1U) < (RGX_HWPERF_TYPEID_STREAM_MASK >> RGX_HWPERF_STREAM_SHIFT),
-               "Too many HWPerf stream IDs.");
-
-/*! Compile-time value used to seed the Multi-Core (MC) bit in the typeID field.
- *  Only set by RGX_FIRMWARE builds.
- */
-#if defined(RGX_FIRMWARE)
-# if defined(RGX_FEATURE_GPU_MULTICORE_SUPPORT)
-#define RGX_HWPERF_M_CORE_VALUE 1U  /*!< 1 => Multi-core supported */
-# else
-#define RGX_HWPERF_M_CORE_VALUE 0U  /*!< 0 => Multi-core not supported */
-# endif
-#else
-#define RGX_HWPERF_M_CORE_VALUE 0U  /*!< 0 => Multi-core not supported */
-#endif
-
-/*! Macros used to set the packet type and encode meta thread ID (0|1),
- * HWPerf stream ID, multi-core capability and OSID within the typeID */
-#define RGX_HWPERF_MAKE_TYPEID(_stream, _type, _thread, _metadma, _osid)\
-               ((IMG_UINT32) ((RGX_HWPERF_TYPEID_STREAM_MASK&((IMG_UINT32)(_stream) << RGX_HWPERF_STREAM_SHIFT)) | \
-               (RGX_HWPERF_TYPEID_THREAD_MASK & ((IMG_UINT32)(_thread) << RGX_HWPERF_META_THREAD_SHIFT)) | \
-               (RGX_HWPERF_TYPEID_EVENT_MASK & (IMG_UINT32)(_type)) | \
-               (RGX_HWPERF_TYPEID_META_DMA_MASK & ((IMG_UINT32)(_metadma) << RGX_HWPERF_META_DMA_SHIFT)) | \
-               (RGX_HWPERF_TYPEID_OSID_MASK & ((IMG_UINT32)(_osid) << RGX_HWPERF_OSID_SHIFT)) | \
-               (RGX_HWPERF_TYPEID_M_CORE_MASK & ((IMG_UINT32)(RGX_HWPERF_M_CORE_VALUE) << RGX_HWPERF_M_CORE_SHIFT))))
-
-/*! Obtains the event type that generated the packet */
-#define RGX_HWPERF_GET_TYPE(_packet_addr)            (((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_EVENT_MASK)
-
-/*! Obtains the META Thread number that generated the packet */
-#define RGX_HWPERF_GET_THREAD_ID(_packet_addr)       (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_THREAD_MASK) >> RGX_HWPERF_META_THREAD_SHIFT))
-
-/*! Determines if the packet generated contains multi-core data */
-#define RGX_HWPERF_GET_M_CORE(_packet_addr)          (((_packet_addr)->eTypeId & RGX_HWPERF_TYPEID_M_CORE_MASK) >> RGX_HWPERF_M_CORE_SHIFT)
-
-/*! Obtains the guest OSID which resulted in packet generation */
-#define RGX_HWPERF_GET_OSID(_packet_addr)            (((_packet_addr)->eTypeId & RGX_HWPERF_TYPEID_OSID_MASK) >> RGX_HWPERF_OSID_SHIFT)
-
-/*! Obtain stream id */
-#define RGX_HWPERF_GET_STREAM_ID(_packet_addr)       (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_STREAM_MASK) >> RGX_HWPERF_STREAM_SHIFT))
-
-/*! Obtain information about how the packet was generated, which might affect payload total size */
-#define RGX_HWPERF_GET_META_DMA_INFO(_packet_addr)   (((((_packet_addr)->eTypeId) & RGX_HWPERF_TYPEID_META_DMA_MASK) >> RGX_HWPERF_META_DMA_SHIFT))
-
-/*! Obtains a typed pointer to a packet given a buffer address */
-#define RGX_HWPERF_GET_PACKET(_buffer_addr)            ((RGX_HWPERF_V2_PACKET_HDR *)(void *)  (_buffer_addr))
-/*! Obtains a typed pointer to a data structure given a packet address */
-#define RGX_HWPERF_GET_PACKET_DATA_BYTES(_packet_addr) (IMG_OFFSET_ADDR((_packet_addr), sizeof(RGX_HWPERF_V2_PACKET_HDR)))
-/*! Obtains a typed pointer to the next packet given a packet address */
-#define RGX_HWPERF_GET_NEXT_PACKET(_packet_addr)       ((RGX_HWPERF_V2_PACKET_HDR *)  (IMG_OFFSET_ADDR((_packet_addr), RGX_HWPERF_SIZE_MASK&((_packet_addr)->ui32Size))))
-
-/*! Obtains a typed pointer to a packet header given the packet data address */
-#define RGX_HWPERF_GET_PACKET_HEADER(_packet_addr)     ((RGX_HWPERF_V2_PACKET_HDR *)  (IMG_OFFSET_ADDR((_packet_addr), -(IMG_INT32)sizeof(RGX_HWPERF_V2_PACKET_HDR))))
-
-
-/******************************************************************************
- * Other Common Defines
- *****************************************************************************/
-
-/*! This macro is not a real array size, but indicates the array has a variable
- * length only known at run-time but always contains at least 1 element. The
- * final size of the array is deduced from the size field of a packet header.
- */
-#define RGX_HWPERF_ONE_OR_MORE_ELEMENTS  1U
-
-/*! This macro is not a real array size, but indicates the array is optional
- * and if present has a variable length only known at run-time. The final
- * size of the array is deduced from the size field of a packet header. */
-#define RGX_HWPERF_ZERO_OR_MORE_ELEMENTS 1U
-
-
-/*! Masks for use with the IMG_UINT32 ui32BlkInfo field */
-#define RGX_HWPERF_BLKINFO_BLKCOUNT_MASK       0xFFFF0000U
-#define RGX_HWPERF_BLKINFO_BLKOFFSET_MASK      0x0000FFFFU
-
-/*! Shift for the NumBlocks and counter block offset field in ui32BlkInfo */
-#define RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT      16U
-#define RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT 0U
-
-/*! Macro used to set the block info word as a combination of two 16-bit integers */
-#define RGX_HWPERF_MAKE_BLKINFO(_numblks, _blkoffset) ((IMG_UINT32) ((RGX_HWPERF_BLKINFO_BLKCOUNT_MASK&((_numblks) << RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT)) | (RGX_HWPERF_BLKINFO_BLKOFFSET_MASK&((_blkoffset) << RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT))))
-
-/*! Macro used to obtain the number of counter blocks present in the packet */
-#define RGX_HWPERF_GET_BLKCOUNT(_blkinfo)            (((_blkinfo) & RGX_HWPERF_BLKINFO_BLKCOUNT_MASK) >> RGX_HWPERF_BLKINFO_BLKCOUNT_SHIFT)
-
-/*! Obtains the offset of the counter block stream in the packet */
-#define RGX_HWPERF_GET_BLKOFFSET(_blkinfo)           (((_blkinfo) & RGX_HWPERF_BLKINFO_BLKOFFSET_MASK) >> RGX_HWPERF_BLKINFO_BLKOFFSET_SHIFT)
-
-/*! This macro gets the number of blocks depending on the packet version */
-#define RGX_HWPERF_GET_NUMBLKS(_sig, _packet_data, _numblocks) \
-       do { \
-               if (HWPERF_PACKET_V2B_SIG == (_sig)) \
-               { \
-                       (_numblocks) = RGX_HWPERF_GET_BLKCOUNT((_packet_data)->ui32BlkInfo);\
-               } \
-               else \
-               { \
-                       IMG_UINT32 ui32VersionOffset = (((_sig) == HWPERF_PACKET_V2_SIG) ? 1 : 3);\
-                       (_numblocks) = *(IMG_UINT16 *)(IMG_OFFSET_ADDR(&(_packet_data)->ui32WorkTarget, ui32VersionOffset)); \
-               } \
-       } while (0)
-
-/*! This macro gets the counter stream pointer depending on the packet version */
-#define RGX_HWPERF_GET_CNTSTRM(_sig, _hw_packet_data, _cntstream_ptr) \
-{ \
-       if (HWPERF_PACKET_V2B_SIG == (_sig)) \
-       { \
-               (_cntstream_ptr) = (IMG_UINT32 *)(IMG_OFFSET_ADDR((_hw_packet_data), RGX_HWPERF_GET_BLKOFFSET((_hw_packet_data)->ui32BlkInfo))); \
-       } \
-       else \
-       { \
-               IMG_UINT32 ui32BlkStreamOffsetInWords = (((_sig) == HWPERF_PACKET_V2_SIG) ? 6 : 8); \
-               (_cntstream_ptr) = (IMG_UINT32 *)(IMG_OFFSET_ADDR_DW((_hw_packet_data), ui32BlkStreamOffsetInWords)); \
-       } \
-}
-
-/*! This is the maximum number of frame contexts that are supported in the
- * driver at the moment */
-#define RGX_HWPERF_HW_MAX_WORK_CONTEXT               2
-
-/*! Masks for use with the RGX_HWPERF_UFO_EV eEvType field */
-#define RGX_HWPERF_UFO_STREAMSIZE_MASK 0xFFFF0000U
-#define RGX_HWPERF_UFO_STREAMOFFSET_MASK 0x0000FFFFU
-
-/*! Shift for the UFO count and data stream fields */
-#define RGX_HWPERF_UFO_STREAMSIZE_SHIFT 16U
-#define RGX_HWPERF_UFO_STREAMOFFSET_SHIFT 0U
-
-/*! Macro used to set UFO stream info word as a combination of two 16-bit integers */
-#define RGX_HWPERF_MAKE_UFOPKTINFO(_ssize, _soff) \
-        ((IMG_UINT32) ((RGX_HWPERF_UFO_STREAMSIZE_MASK&((_ssize) << RGX_HWPERF_UFO_STREAMSIZE_SHIFT)) | \
-        (RGX_HWPERF_UFO_STREAMOFFSET_MASK&((_soff) << RGX_HWPERF_UFO_STREAMOFFSET_SHIFT))))
-
-/*! Macro used to obtain UFO count*/
-#define RGX_HWPERF_GET_UFO_STREAMSIZE(_streaminfo) \
-        (((_streaminfo) & RGX_HWPERF_UFO_STREAMSIZE_MASK) >> RGX_HWPERF_UFO_STREAMSIZE_SHIFT)
-
-/*! Obtains the offset of the UFO stream in the packet */
-#define RGX_HWPERF_GET_UFO_STREAMOFFSET(_streaminfo) \
-        (((_streaminfo) & RGX_HWPERF_UFO_STREAMOFFSET_MASK) >> RGX_HWPERF_UFO_STREAMOFFSET_SHIFT)
-
+/*! The number of directly-addressable counters allowed in non-mux counter blocks */
+#define RGX_CNTBLK_COUNTERS_MAX ((IMG_UINT32)PVRSRV_HWPERF_COUNTERS_PERBLK + 0U)
 
 
 /******************************************************************************
@@ -563,18 +170,20 @@ typedef enum {
        RGX_HWPERF_DM_INVALID = 0x1FFFFFFF
 } RGX_HWPERF_DM;
 
-/*! Enum containing bit position for 32bit feature flags used in hwperf and api */
-typedef enum {
-       RGX_HWPERF_FEATURE_PERFBUS_FLAG                = 0x001,
-       RGX_HWPERF_FEATURE_S7_TOP_INFRASTRUCTURE_FLAG  = 0x002,
-       RGX_HWPERF_FEATURE_XT_TOP_INFRASTRUCTURE_FLAG  = 0x004,
-       RGX_HWPERF_FEATURE_PERF_COUNTER_BATCH_FLAG     = 0x008,
-       RGX_HWPERF_FEATURE_ROGUEXE_FLAG                = 0x010,
-       RGX_HWPERF_FEATURE_DUST_POWER_ISLAND_S7_FLAG   = 0x020,
-       RGX_HWPERF_FEATURE_PBE2_IN_XE_FLAG             = 0x040,
-       RGX_HWPERF_FEATURE_WORKLOAD_ESTIMATION         = 0x080,
-       RGX_HWPERF_FEATURE_MULTICORE_FLAG              = 0x100
-} RGX_HWPERF_FEATURE_FLAGS;
+/*! Define containing bit position for 32bit feature flags used in hwperf and api */
+typedef IMG_UINT32 RGX_HWPERF_FEATURE_FLAGS;
+#define RGX_HWPERF_FEATURE_PERFBUS_FLAG                0x0001U
+#define RGX_HWPERF_FEATURE_S7_TOP_INFRASTRUCTURE_FLAG  0x0002U
+#define RGX_HWPERF_FEATURE_XT_TOP_INFRASTRUCTURE_FLAG  0x0004U
+#define RGX_HWPERF_FEATURE_PERF_COUNTER_BATCH_FLAG     0x0008U
+#define RGX_HWPERF_FEATURE_ROGUEXE_FLAG                0x0010U
+#define RGX_HWPERF_FEATURE_DUST_POWER_ISLAND_S7_FLAG   0x0020U
+#define RGX_HWPERF_FEATURE_PBE2_IN_XE_FLAG             0x0040U
+#define RGX_HWPERF_FEATURE_WORKLOAD_ESTIMATION         0x0080U
+#define RGX_HWPERF_FEATURE_MULTICORE_FLAG              0x0100U
+#define RGX_HWPERF_FEATURE_VOLCANIC_FLAG               0x0800U
+#define RGX_HWPERF_FEATURE_ROGUE_FLAG                  0x1000U
+#define RGX_HWPERF_FEATURE_OCEANIC_FLAG                0x2000U
 
 /*! This structure holds the data of a firmware packet. */
 typedef struct
@@ -604,11 +213,14 @@ typedef struct
        IMG_UINT32 ui32WorkCtx;       /*!< Work context: Render Context for TA/3D; RayTracing Context for RTU/SHG; 0x0 otherwise */
        IMG_UINT32 ui32CtxPriority;   /*!< Context priority */
        IMG_UINT32 ui32GPUIdMask;     /*!< GPU IDs active within this event */
-       IMG_UINT32 aui32CountBlksStream[RGX_HWPERF_ZERO_OR_MORE_ELEMENTS]; /*!< Counter data */
-       IMG_UINT32 ui32Padding2;      /*!< Reserved. To ensure correct alignment */
+       IMG_UINT32 ui32KickInfo;      /*!< <31..8> Reserved <7..0> GPU Pipeline DM kick ID, 0 if not using Pipeline DMs */
+       IMG_UINT32 ui32Padding;       /*!< Reserved. To ensure correct alignment */
+       IMG_UINT32 aui32CountBlksStream[RGX_HWPERF_ZERO_OR_MORE_ELEMENTS]; /*!< Optional variable length Counter data */
+       IMG_UINT32 ui32Padding2;      /*!< Reserved. To ensure correct alignment (not written in the packet) */
 } RGX_HWPERF_HW_DATA;
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_HW_DATA);
+RGX_FW_STRUCT_OFFSET_ASSERT(RGX_HWPERF_HW_DATA, aui32CountBlksStream);
 
 typedef struct
 {
@@ -822,8 +434,8 @@ typedef union
        /*! This structure holds the data of a work estimation packet. */
        struct
        {
-               IMG_UINT64     ui64CyclesPrediction;     /*!< Predicted cycle count for this workload */
-               IMG_UINT64     ui64CyclesTaken;          /*!< Actual cycle count for this workload */
+               IMG_UINT32     ui32CyclesPrediction;     /*!< Predicted cycle count for this workload */
+               IMG_UINT32     ui32CyclesTaken;          /*!< Actual cycle count for this workload */
                RGXFWIF_DM     eDM;                      /*!< Target DM */
                IMG_UINT32     ui32ReturnDataIndex;      /*!< Index into workload estimation table */
                IMG_UINT32     ui32TxtActCyc;            /*!< Meta TXTACTCYC register value */
@@ -878,7 +490,7 @@ typedef enum
 /* Fixed size for BVNC string so it does not alter packet data format
  * Check it is large enough against official BVNC string length maximum
  */
-#define RGX_HWPERF_MAX_BVNC_LEN (24)
+#define RGX_HWPERF_MAX_BVNC_LEN (24U)
 static_assert((RGX_HWPERF_MAX_BVNC_LEN >= RGX_BVNC_STR_SIZE_MAX),
                          "Space inside HWPerf packet data for BVNC string insufficient");
 
@@ -912,6 +524,26 @@ typedef struct
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_BVNC);
 
+/*! Performance Counter Configuration data element. */
+typedef struct
+{
+       IMG_UINT32 ui32BlockID;               /*!< Counter Block ID. See RGX_HWPERF_CNTBLK_ID */
+       IMG_UINT32 ui32NumCounters;           /*!< Number of counters configured */
+       IMG_UINT32 ui32CounterVals[RGX_CNTBLK_COUNTERS_MAX];  /*!< Counters configured (ui32NumCounters worth of entries) */
+} RGX_HWPERF_COUNTER_CFG_DATA_EL;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_COUNTER_CFG_DATA_EL);
+
+/*! Performance Counter Configuration data. */
+typedef struct
+{
+       IMG_UINT32 ui32EnabledBlocks;          /*!< Number of Enabled Blocks. */
+       RGX_HWPERF_COUNTER_CFG_DATA_EL uData;  /*!< Start of variable length data. See RGX_HWPERF_COUNTER_CFG_DATA_EL */
+       IMG_UINT32 ui32Padding;                /*!< reserved */
+} RGX_HWPERF_COUNTER_CFG;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_COUNTER_CFG);
+
 /*! Sub-event's data. */
 typedef union
 {
@@ -928,7 +560,7 @@ typedef union
                IMG_UINT32 ui32EvMaskLo;                /*!< Low order 32 bits of Filter Mask */
                IMG_UINT32 ui32EvMaskHi;                /*!< High order 32 bits of Filter Mask */
        } sEvMsk;                                                       /*!< HW Filter Mask */
-
+       RGX_HWPERF_COUNTER_CFG sPCC;        /*!< Performance Counter Config. See RGX_HWPERF_COUNTER_CFG */
 } RGX_HWPERF_FWACT_DETAIL;
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_FWACT_DETAIL);
@@ -1043,12 +675,12 @@ typedef struct
        IMG_UINT64 ui64CheckFence_UID;    /*!< ID of fence gating work execution on GPU */
        IMG_UINT64 ui64UpdateFence_UID;   /*!< ID of fence triggered after work completes on GPU */
        IMG_UINT64 ui64DeadlineInus;      /*!< Workload deadline in system monotonic time */
-       IMG_UINT64 ui64CycleEstimate;     /*!< Estimated cycle time for the workload */
+       IMG_UINT32 ui32CycleEstimate;     /*!< Estimated cycle time for the workload */
        PVRSRV_FENCE hCheckFence;         /*!< Fence this enqueue task waits for, before starting */
        PVRSRV_FENCE hUpdateFence;        /*!< Fence this enqueue task signals, on completion */
        PVRSRV_TIMELINE hUpdateTimeline;  /*!< Timeline on which the above hUpdateFence is created */
 
-       IMG_UINT32 ui32Pad;               /* Align structure size to 8 bytes */
+       /* Align structure size to 8 bytes */
 } RGX_HWPERF_HOST_ENQ_DATA;
 
 /* Payload size must be multiple of 8 bytes to align start of next packet. */
@@ -1456,6 +1088,49 @@ static_assert((sizeof(RGX_HWPERF_HOST_SYNC_SW_TL_ADV_DATA) & (PVRSRVTL_PACKET_AL
 
 typedef enum
 {
+       RGX_HWPERF_HOST_CLIENT_INFO_TYPE_INVALID = 0,  /*!< Invalid */
+       RGX_HWPERF_HOST_CLIENT_INFO_TYPE_PROCESS_NAME, /*!< Process Name */
+
+       RGX_HWPERF_HOST_CLIENT_INFO_TYPE_LAST,         /*!< Do not use */
+} RGX_HWPERF_HOST_CLIENT_INFO_TYPE;
+
+typedef struct
+{
+       IMG_PID uiClientPID; /*!< Client process identifier */
+       IMG_UINT32 ui32Length;  /*!< Number of bytes present in ``acName`` */
+       IMG_CHAR acName[RGX_HWPERF_ONE_OR_MORE_ELEMENTS]; /*!< Process name string, null terminated */
+} RGX_HWPERF_HOST_CLIENT_PROC_NAME;
+
+#define RGX_HWPERF_HOST_CLIENT_PROC_NAME_SIZE(ui32NameLen) \
+       ((IMG_UINT32)(offsetof(RGX_HWPERF_HOST_CLIENT_PROC_NAME, acName) + (ui32NameLen)))
+
+typedef union
+{
+       struct
+       {
+               IMG_UINT32 ui32Count; /*!< Number of elements in ``asProcNames`` */
+               RGX_HWPERF_HOST_CLIENT_PROC_NAME asProcNames[RGX_HWPERF_ONE_OR_MORE_ELEMENTS];
+       } sProcName;
+} RGX_HWPERF_HOST_CLIENT_INFO_DETAIL;
+
+typedef struct
+{
+       IMG_UINT32 uiReserved1; /*!< Reserved. Align structure size to 8 bytes */
+       RGX_HWPERF_HOST_CLIENT_INFO_TYPE eType;
+                               /*!< Type of the subevent, see
+                                RGX_HWPERF_HOST_CLIENT_INFO_TYPE */
+       RGX_HWPERF_HOST_CLIENT_INFO_DETAIL uDetail;
+                               /*!< Union of structures. Size of data
+                                varies with union member that is present,
+                                check ``eType`` value to decode */
+
+} RGX_HWPERF_HOST_CLIENT_INFO_DATA;
+
+static_assert((sizeof(RGX_HWPERF_HOST_CLIENT_INFO_DATA) & (PVRSRVTL_PACKET_ALIGNMENT-1U)) == 0U,
+                         "sizeof(RGX_HWPERF_HOST_CLIENT_INFO_DATA) must be a multiple PVRSRVTL_PACKET_ALIGNMENT");
+
+typedef enum
+{
        RGX_HWPERF_RESOURCE_CAPTURE_TYPE_NONE,
        RGX_HWPERF_RESOURCE_CAPTURE_TYPE_DEFAULT_FRAMEBUFFER,
        RGX_HWPERF_RESOURCE_CAPTURE_TYPE_OFFSCREEN_FB_ATTACHMENTS,
@@ -1579,6 +1254,9 @@ typedef union
                                                       events ``0x09`` (Host) */
        RGX_HWPERF_HOST_SYNC_SW_TL_ADV_DATA sSWTLADV; /*!< Host SW-timeline advance
                                                       data, events ``0x0A`` (Host) */
+       RGX_HWPERF_HOST_CLIENT_INFO_DATA sHClientInfo; /*!< Host client info,
+                                                      events ``0x0B`` (Host) */
+
 } RGX_HWPERF_V2_PACKET_DATA, *RGX_PHWPERF_V2_PACKET_DATA;
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_V2_PACKET_DATA);
@@ -1610,7 +1288,11 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_ID;
 #define        RGX_CNTBLK_ID_HUB                        0x0002U /*!< Non-cluster grouping cores */
 #define        RGX_CNTBLK_ID_TORNADO            0x0003U /*!< XT cores */
 #define        RGX_CNTBLK_ID_JONES                      0x0004U /*!< S7 cores */
+#if defined(RGX_FEATURE_HWPERF_OCEANIC)
+#define        RGX_CNTBLK_ID_DIRECT_LAST        0x0003U /*!< Indirect blocks start from here */
+#else
 #define        RGX_CNTBLK_ID_DIRECT_LAST        0x0005U /*!< Indirect blocks start from here */
+#endif /* defined(RGX_FEATURE_HWPERF_OCEANIC) */
 
 #define        RGX_CNTBLK_ID_BF_DEPRECATED      0x0005U /*!< Doppler unit (DEPRECATED) */
 #define        RGX_CNTBLK_ID_BT_DEPRECATED      0x0006U /*!< Doppler unit (DEPRECATED) */
@@ -1618,34 +1300,62 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_ID;
 #define        RGX_CNTBLK_ID_SH_DEPRECATED      0x0008U /*!< Ray tracing unit (DEPRECATED) */
 
 
-/*! Indirectly addressable counter blocks */
+/*! Indirectly addressable counter blocks. DA blocks indicate counter blocks
+ *  where the counter registers are directly accessible
+ */
 #define        RGX_CNTBLK_ID_TPU_MCU0           0x0010U /*!< Addressable by Dust */
+#define RGX_CNTBLK_ID_TPU_MCU0_DA       0x8010U
 #define        RGX_CNTBLK_ID_TPU_MCU1           0x0011U
+#define RGX_CNTBLK_ID_TPU_MCU1_DA       0x8011U
 #define        RGX_CNTBLK_ID_TPU_MCU2           0x0012U
+#define RGX_CNTBLK_ID_TPU_MCU2_DA       0x8012U
 #define        RGX_CNTBLK_ID_TPU_MCU3           0x0013U
+#define RGX_CNTBLK_ID_TPU_MCU3_DA       0x8013U
 #define        RGX_CNTBLK_ID_TPU_MCU4           0x0014U
+#define RGX_CNTBLK_ID_TPU_MCU4_DA       0x8014U
 #define        RGX_CNTBLK_ID_TPU_MCU5           0x0015U
+#define RGX_CNTBLK_ID_TPU_MCU5_DA       0x8015U
 #define        RGX_CNTBLK_ID_TPU_MCU6           0x0016U
+#define RGX_CNTBLK_ID_TPU_MCU6_DA       0x8016U
 #define        RGX_CNTBLK_ID_TPU_MCU7           0x0017U
+#define RGX_CNTBLK_ID_TPU_MCU7_DA       0x8017U
 #define        RGX_CNTBLK_ID_TPU_MCU_ALL        0x4010U
+#define        RGX_CNTBLK_ID_TPU_MCU_ALL_DA     0xC010U
 
 #define        RGX_CNTBLK_ID_USC0                       0x0020U /*!< Addressable by Cluster */
+#define RGX_CNTBLK_ID_USC0_DA           0x8020U
 #define        RGX_CNTBLK_ID_USC1                       0x0021U
+#define RGX_CNTBLK_ID_USC1_DA           0x8021U
 #define        RGX_CNTBLK_ID_USC2                       0x0022U
+#define RGX_CNTBLK_ID_USC2_DA           0x8022U
 #define        RGX_CNTBLK_ID_USC3                       0x0023U
+#define RGX_CNTBLK_ID_USC3_DA           0x8023U
 #define        RGX_CNTBLK_ID_USC4                       0x0024U
+#define RGX_CNTBLK_ID_USC4_DA           0x8024U
 #define        RGX_CNTBLK_ID_USC5                       0x0025U
+#define RGX_CNTBLK_ID_USC5_DA           0x8025U
 #define        RGX_CNTBLK_ID_USC6                       0x0026U
+#define RGX_CNTBLK_ID_USC6_DA           0x8026U
 #define        RGX_CNTBLK_ID_USC7                       0x0027U
+#define RGX_CNTBLK_ID_USC7_DA           0x8027U
 #define        RGX_CNTBLK_ID_USC8                       0x0028U
+#define RGX_CNTBLK_ID_USC8_DA           0x8028U
 #define        RGX_CNTBLK_ID_USC9                       0x0029U
+#define RGX_CNTBLK_ID_USC9_DA           0x8029U
 #define        RGX_CNTBLK_ID_USC10                      0x002AU
+#define RGX_CNTBLK_ID_USC10_DA          0x802AU
 #define        RGX_CNTBLK_ID_USC11                      0x002BU
+#define RGX_CNTBLK_ID_USC11_DA          0x802BU
 #define        RGX_CNTBLK_ID_USC12                      0x002CU
+#define RGX_CNTBLK_ID_USC12_DA          0x802CU
 #define        RGX_CNTBLK_ID_USC13                      0x002DU
+#define RGX_CNTBLK_ID_USC13_DA          0x802DU
 #define        RGX_CNTBLK_ID_USC14                      0x002EU
+#define RGX_CNTBLK_ID_USC14_DA          0x802EU
 #define        RGX_CNTBLK_ID_USC15                      0x002FU
+#define RGX_CNTBLK_ID_USC15_DA          0x802FU
 #define        RGX_CNTBLK_ID_USC_ALL            0x4020U
+#define        RGX_CNTBLK_ID_USC_ALL_DA         0xC020U
 
 #define        RGX_CNTBLK_ID_TEXAS0             0x0030U /*!< Addressable by Phantom in XT, Dust in S7 */
 #define        RGX_CNTBLK_ID_TEXAS1             0x0031U
@@ -1700,22 +1410,36 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_ID;
 #define        RGX_CNTBLK_ID_CUSTOM2            0x70F2U
 #define        RGX_CNTBLK_ID_CUSTOM3            0x70F3U
 #define        RGX_CNTBLK_ID_CUSTOM4_FW         0x70F4U /*!< Custom block used for getting statistics held in the FW */
-#define RGX_CNTBLK_ID_CUSTOM_MASK       0x70FFU
+#define        RGX_CNTBLK_ID_CUSTOM_MASK        0x70FFU
 
 
 /* Masks for the counter block ID*/
-#define RGX_CNTBLK_ID_UNIT_MASK      (0x000FU)
-#define RGX_CNTBLK_ID_GROUP_MASK     (0x00F0U)
-#define RGX_CNTBLK_ID_GROUP_SHIFT    (4U)
-#define RGX_CNTBLK_ID_MC_GPU_MASK    (0x0F00U)
-#define RGX_CNTBLK_ID_MC_GPU_SHIFT   (8U)
-#define RGX_CNTBLK_ID_UNIT_ALL_MASK  (0x4000U)
+#define        RGX_CNTBLK_ID_UNIT_MASK      (0x000FU)
+#define        RGX_CNTBLK_ID_GROUP_MASK     (0x00F0U)
+#define        RGX_CNTBLK_ID_GROUP_SHIFT    (4U)
+#define        RGX_CNTBLK_ID_MC_GPU_MASK    (0x0F00U)
+#define        RGX_CNTBLK_ID_MC_GPU_SHIFT   (8U)
+#define        RGX_CNTBLK_ID_UNIT_ALL_MASK  (0x4000U)
+#define        RGX_CNTBLK_ID_DA_MASK        (0x8000U) /*!< Block with directly accessible counter registers */
 
 #define RGX_CNTBLK_INDIRECT_COUNT(_class, _n) ((IMG_UINT32)(RGX_CNTBLK_ID_ ## _class ## _n) - (IMG_UINT32)(RGX_CNTBLK_ID_ ## _class ## 0) + 1u)
 
 /*! The number of layout blocks defined with configurable multiplexed
  * performance counters, hence excludes custom counter blocks.
  */
+#if defined(RGX_FEATURE_HWPERF_OCEANIC)
+#define RGX_HWPERF_MAX_MUX_BLKS (\
+       (IMG_UINT32)RGX_CNTBLK_ID_DIRECT_LAST    +\
+       RGX_CNTBLK_INDIRECT_COUNT(PBE,         0) )
+
+#define RGX_HWPERF_MAX_DA_BLKS (\
+       (IMG_UINT32)RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU,     0)+\
+       RGX_CNTBLK_INDIRECT_COUNT(USC,                     0) )
+
+#define RGX_HWPERF_MAX_DEFINED_BLKS (\
+       (IMG_UINT32)RGX_HWPERF_MAX_MUX_BLKS     +\
+       RGX_HWPERF_MAX_DA_BLKS                   )
+#else
 #define RGX_HWPERF_MAX_DEFINED_BLKS  (\
        (IMG_UINT32)RGX_CNTBLK_ID_DIRECT_LAST    +\
        RGX_CNTBLK_INDIRECT_COUNT(TPU_MCU,     7)+\
@@ -1724,12 +1448,15 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_ID;
        RGX_CNTBLK_INDIRECT_COUNT(RASTER,      3)+\
        RGX_CNTBLK_INDIRECT_COUNT(BLACKPEARL,  3)+\
        RGX_CNTBLK_INDIRECT_COUNT(PBE,        15) )
+#define RGX_HWPERF_MAX_MUX_BLKS      (\
+    RGX_HWPERF_MAX_DEFINED_BLKS      )
+#endif
 
 static_assert(
        ((RGX_CNTBLK_ID_DIRECT_LAST + ((RGX_CNTBLK_ID_LAST & RGX_CNTBLK_ID_GROUP_MASK) >> RGX_CNTBLK_ID_GROUP_SHIFT)) <= RGX_HWPERF_MAX_BVNC_BLOCK_LEN),
        "RGX_HWPERF_MAX_BVNC_BLOCK_LEN insufficient");
 
-#define RGX_HWPERF_EVENT_MASK_VALUE(e)      (IMG_UINT64_C(1) << (e))
+#define RGX_HWPERF_EVENT_MASK_VALUE(e)      (IMG_UINT64_C(1) << (IMG_UINT32)(e))
 
 #define RGX_CUSTOM_FW_CNTRS    \
                 X(TA_LOCAL_FL_SIZE,    0x0, RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_HW_TAKICK) |         \
@@ -1772,7 +1499,7 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_COUNTER_ID;
 #define        RGX_CNTBLK_COUNTER4_ID 4U
 #define        RGX_CNTBLK_COUNTER5_ID 5U
        /* MAX value used in server handling of counter config arrays */
-#define        RGX_CNTBLK_COUNTERS_MAX 6U
+#define        RGX_CNTBLK_MUX_COUNTERS_MAX 6U
 
 
 /* sets all the bits from bit _b1 to _b2, in a IMG_UINT64 type */
@@ -1824,7 +1551,7 @@ typedef IMG_UINT32 RGX_HWPERF_CNTBLK_COUNTER_ID;
 #define RGX_HWPERF_EVENT_MASK_HOST_ALL_PWR   (RGX_HWPERF_HOST_EVENT_MASK_VALUE(RGX_HWPERF_HOST_CLK_SYNC))
 
 
-/*! Type used in the RGX API RGXConfigureAndEnableHWPerfCounters() */
+/*! Type used in the RGX API RGXConfigMuxHWPerfCounters() */
 typedef struct
 {
        /*! Counter block ID, see RGX_HWPERF_CNTBLK_ID */
@@ -1837,21 +1564,38 @@ typedef struct
        IMG_UINT8  ui8Mode;
 
        /*! 5 or 6 LSBs used as the GROUP_SELECT value for the counter. */
-       IMG_UINT8  aui8GroupSelect[RGX_CNTBLK_COUNTERS_MAX];
+       IMG_UINT8  aui8GroupSelect[RGX_CNTBLK_MUX_COUNTERS_MAX];
 
        /*! 16 LSBs used as the BIT_SELECT value for the counter. */
-       IMG_UINT16 aui16BitSelect[RGX_CNTBLK_COUNTERS_MAX];
+       IMG_UINT16 aui16BitSelect[RGX_CNTBLK_MUX_COUNTERS_MAX];
 
        /*! 14 LSBs used as the BATCH_MAX value for the counter. */
-       IMG_UINT32 aui32BatchMax[RGX_CNTBLK_COUNTERS_MAX];
+       IMG_UINT32 aui32BatchMax[RGX_CNTBLK_MUX_COUNTERS_MAX];
 
        /*! 14 LSBs used as the BATCH_MIN value for the counter. */
-       IMG_UINT32 aui32BatchMin[RGX_CNTBLK_COUNTERS_MAX];
+       IMG_UINT32 aui32BatchMin[RGX_CNTBLK_MUX_COUNTERS_MAX];
+} UNCACHED_ALIGN RGX_HWPERF_CONFIG_MUX_CNTBLK;
+
+RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_CONFIG_MUX_CNTBLK);
+
+/*! Type used in the RGX API RGXConfigHWPerfCounters() */
+typedef struct
+{
+       /*! Reserved for future use */
+       IMG_UINT32 ui32Reserved;
+
+       /*! Counter block ID, see RGX_HWPERF_CNTBLK_ID */
+       IMG_UINT16 ui16BlockID;
+
+       /*! Number of configured counters within this block */
+       IMG_UINT16 ui16NumCounters;
+
+       /*! Counter register values */
+       IMG_UINT16 ui16Counters[RGX_CNTBLK_COUNTERS_MAX];
 } UNCACHED_ALIGN RGX_HWPERF_CONFIG_CNTBLK;
 
 RGX_FW_STRUCT_SIZE_ASSERT(RGX_HWPERF_CONFIG_CNTBLK);
 
-
 #if defined(__cplusplus)
 }
 #endif
index f650fda..abb6308 100644 (file)
@@ -223,8 +223,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* 0xEA_4000_0000 - 0xEA_FFFF_FFFF **/
        /* 937 GiB to 940 GiB, size of 3 GiB : FREE **/
 
-/* 0xEB_0000_0000 - 0xED_FFFF_FFFF **/
-       /* 940 GiB to 952 GiB, size of 12 GiB : RESERVED VOLCANIC  **/
+/* 0xEB_0000_0000 - 0xEB_FFFF_FFFF **/
+       /* 940 GiB to 944 GiB, size of 4 GiB : RESERVED VOLCANIC  **/
+
+/* 0xEC_0000_0000 - 0xEC_001F_FFFF **/
+       /* 944 GiB to 945 GiB, size 2 MiB : FBCDC_HEAP **/
+       #define RGX_FBCDC_HEAP_BASE                 IMG_UINT64_C(0xEC00000000)
+       #define RGX_FBCDC_HEAP_SIZE                 RGX_HEAP_SIZE_2MiB
+
+/* 0xEC_4000_0000 - 0xEC_401F_FFFF **/
+       /* 945 GiB to 946 GiB, size 2 MiB : FBCDC_LARGE_HEAP **/
+       #define RGX_FBCDC_LARGE_HEAP_BASE           IMG_UINT64_C(0xEC40000000)
+       #define RGX_FBCDC_LARGE_HEAP_SIZE           RGX_HEAP_SIZE_2MiB
+
+/* 0xEC_8000_0000 - 0xED_FFFF_FFFF **/
+       /* 946 GiB to 952 GiB, size of 6 GiB : RESERVED VOLCANIC  **/
 
 /* 0xEE_0000_0000 - 0xEE_3FFF_FFFF **/
        /* 952 GiB to 953 GiB, size of 1 GiB : CMP_MISSION_RMW_HEAP **/
@@ -243,7 +256,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        /* 957 GiB to 960 GiB, size of 3 GiB : RESERVED **/
 
 /* 0xF0_0000_0000 - 0xF0_FFFF_FFFF **/
-       /* 960 GiB to 964 GiB, size of 4 GiB : RESERVED VOLCANIC **/
+       /* 960 GiB to 964 GiB, size of 4 GiB : TEXTURE_STATE_HEAP (36-bit aligned) */
+       #define RGX_TEXTURE_STATE_HEAP_BASE         IMG_UINT64_C(0xF000000000)
+       #define RGX_TEXTURE_STATE_HEAP_SIZE         RGX_HEAP_SIZE_4GiB
 
 /* 0xF1_0000_0000 - 0xF1_FFFF_FFFF **/
        /* 964 GiB to 968 GiB, size of 4 GiB : FREE **/
index 9146a27..431273d 100644 (file)
@@ -86,6 +86,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
 #define RGX_TC_SYS_CLOCK_SPEED         (25000000) /*< At the moment just used for TCF5 */
+#define RGX_TC_CLOCK_MULTIPLEX    (1)
 
 #if defined(TC_APOLLO_TCF5_22_46_54_330)
  #undef RGX_TC_SYS_CLOCK_SPEED
index eb47e8c..91ee3b2 100644 (file)
@@ -87,9 +87,9 @@ typedef struct PVRSRV_DEV_CONNECTION_TAG PVRSRV_DEV_CONNECTION;
 #endif
 
 /*!
- * \anchor SRV_FLAGS
- * @name SRV_FLAGS: Flags for Services connection
- * Allows to define per-client policy for Services
+ * @Anchor SRV_FLAGS
+ * @Name SRV_FLAGS: Services connection flags
+ * Allows to define per-client policy for Services.
  * @{
  */
 
@@ -102,10 +102,10 @@ typedef struct PVRSRV_DEV_CONNECTION_TAG PVRSRV_DEV_CONNECTION;
  *    X---XXXXXXXX-------------XXX----
  */
 
-#define SRV_NO_HWPERF_CLIENT_STREAM     (1U << 4)  /*!< Don't create HWPerf for this connection */
-#define SRV_FLAGS_CLIENT_64BIT_COMPAT   (1U << 5)  /*!< This flags gets set if the client is 64 Bit compatible. */
-#define SRV_FLAGS_CLIENT_SLR_DISABLED   (1U << 6)  /*!< This flag is set if the client does not want Sync Lockup Recovery (SLR) enabled. */
-#define SRV_FLAGS_PDUMPCTRL             (1U << 31) /*!< PDump Ctrl client flag */
+#define SRV_NO_HWPERF_CLIENT_STREAM     (1UL << 4)  /*!< Don't create HWPerf for this connection */
+#define SRV_FLAGS_CLIENT_64BIT_COMPAT   (1UL << 5)  /*!< This flags gets set if the client is 64 Bit compatible. */
+#define SRV_FLAGS_CLIENT_SLR_DISABLED   (1UL << 6)  /*!< This flag is set if the client does not want Sync Lockup Recovery (SLR) enabled. */
+#define SRV_FLAGS_PDUMPCTRL             (1UL << 31) /*!< PDump Ctrl client flag */
 
 /*! @} SRV_FLAGS */
 
@@ -138,7 +138,7 @@ typedef struct PVRSRV_DEV_CONNECTION_TAG PVRSRV_DEV_CONNECTION;
 
 
 /* Size of pointer on a 64 bit machine */
-#define        POINTER_SIZE_64BIT      (8)
+#define        POINTER_SIZE_64BIT      (8U)
 
 
 /*
index d65bf12..5d685b2 100644 (file)
@@ -88,35 +88,19 @@ typedef enum _PVRSRV_SYS_POWER_STATE_
 /*!
   Device Power State Enum
  */
-typedef enum _PVRSRV_DEV_POWER_STATE_
-{
-       PVRSRV_DEV_POWER_STATE_DEFAULT  = -1,   /*!< Default state for the device */
-       PVRSRV_DEV_POWER_STATE_OFF              = 0,    /*!< Unpowered */
-       PVRSRV_DEV_POWER_STATE_ON               = 1,    /*!< Running */
-
-       PVRSRV_DEV_POWER_STATE_FORCE_I32 = 0x7fffffff   /*!< Force enum to be at least 32-bits wide */
-
-} PVRSRV_DEV_POWER_STATE, *PPVRSRV_DEV_POWER_STATE;    /*!< Typedef for ptr to PVRSRV_DEV_POWER_STATE */ /* PRQA S 3205 */
-
-
-/* Power transition handler prototypes */
+typedef IMG_INT32 PVRSRV_DEV_POWER_STATE;
+typedef IMG_INT32 *PPVRSRV_DEV_POWER_STATE;    /*!< Typedef for ptr to PVRSRV_DEV_POWER_STATE */ /* PRQA S 3205 */
+#define PVRSRV_DEV_POWER_STATE_DEFAULT -1      /*!< Default state for the device */
+#define PVRSRV_DEV_POWER_STATE_OFF              0      /*!< Unpowered */
+#define PVRSRV_DEV_POWER_STATE_ON               1      /*!< Running */
 
 /*!
-  Typedef for a pointer to a Function that will be called before a transition
-  from one power state to another. See also PFN_POST_POWER.
- */
-typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE                              hDevHandle,
-                                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState,
-                                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState,
-                                                                          IMG_BOOL                                     bForced);
-/*!
-  Typedef for a pointer to a Function that will be called after a transition
-  from one power state to another. See also PFN_PRE_POWER.
+  Power Flags Enum
  */
-typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE                             hDevHandle,
-                                                                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
-                                                                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
-                                                                               IMG_BOOL                                bForced);
+typedef IMG_UINT32 PVRSRV_POWER_FLAGS;
+#define PVRSRV_POWER_FLAGS_NONE                0U                      /*!< No flags */
+#define PVRSRV_POWER_FLAGS_FORCED      1U << 0         /*!< Power the transition should not fail */
+#define PVRSRV_POWER_FLAGS_SUSPEND     1U << 1         /*!< Power transition is due to OS suspend request */
 
 /* Clock speed handler prototypes */
 
index 399e380..19b5011 100644 (file)
@@ -49,9 +49,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifndef CHECKPOINT_TYPES
 #define CHECKPOINT_TYPES
-typedef struct _SYNC_CHECKPOINT_CONTEXT *PSYNC_CHECKPOINT_CONTEXT;
+typedef struct SYNC_CHECKPOINT_CONTEXT_TAG *PSYNC_CHECKPOINT_CONTEXT;
 
-typedef struct _SYNC_CHECKPOINT *PSYNC_CHECKPOINT;
+typedef struct SYNC_CHECKPOINT_TAG *PSYNC_CHECKPOINT;
 #endif
 
 /* PVRSRV_SYNC_CHECKPOINT states.
@@ -68,7 +68,7 @@ typedef IMG_UINT32 PVRSRV_SYNC_CHECKPOINT_STATE;
 #define PVRSRV_SYNC_CHECKPOINT_ERRORED       0xeffU   /*!< checkpoint has been errored */
 
 
-#define PVRSRV_UFO_IS_SYNC_CHECKPOINT_FWADDR(fwaddr)   ((fwaddr) & 0x1U)
+#define PVRSRV_UFO_IS_SYNC_CHECKPOINT_FWADDR(fwaddr)   (((fwaddr) & 0x1U) != 0U)
 #define PVRSRV_UFO_IS_SYNC_CHECKPOINT(ufoptr)                  (PVRSRV_UFO_IS_SYNC_CHECKPOINT_FWADDR((ufoptr)->puiAddrUFO.ui32Addr))
 
 /* Maximum number of sync checkpoints the firmware supports in one fence */
index 262f5b5..77164c2 100644 (file)
@@ -55,8 +55,8 @@ extern "C" {
  * internally.
  */
 
-typedef struct SYNC_PRIM_CONTEXT *PSYNC_PRIM_CONTEXT;
-typedef struct PVRSRV_CLIENT_SYNC_PRIM
+typedef struct SYNC_PRIM_CONTEXT_TAG *PSYNC_PRIM_CONTEXT;
+typedef struct PVRSRV_CLIENT_SYNC_PRIM_TAG
 {
        volatile uint32_t __iomem *pui32LinAddr;        /*!< User pointer to the primitive */
 } PVRSRV_CLIENT_SYNC_PRIM;
@@ -67,7 +67,7 @@ typedef struct PVRSRV_CLIENT_SYNC_PRIM
  *   Structure: #PVRSRV_CLIENT_SYNC_PRIM_OP
  *   Typedef: ::PVRSRV_CLIENT_SYNC_PRIM_OP
  */
-typedef struct PVRSRV_CLIENT_SYNC_PRIM_OP
+typedef struct PVRSRV_CLIENT_SYNC_PRIM_OP_TAG
 {
        #define PVRSRV_CLIENT_SYNC_PRIM_OP_CHECK        (1U << 0)
        #define PVRSRV_CLIENT_SYNC_PRIM_OP_UPDATE       (1U << 1)
index f2a4661..6234887 100644 (file)
@@ -284,9 +284,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_INTERRUPT_STATUS_CDMA           (1 << ODN_INTERRUPT_STATUS_CDMA_SHIFT)
 #define ODN_INTERRUPT_CLEAR_CDMA            (1 << ODN_INTERRUPT_CLR_CDMA_SHIFT)
 
-#define ODN_INTERRUPT_ENABLE_CDMA2          (1 << ODN_INTERRUPT_ENABLE_CDMA2_SHIFT)
-#define ODN_INTERRUPT_STATUS_CDMA2          (1 << ODN_INTERRUPT_STATUS_CDMA2_SHIFT)
-#define ODN_INTERRUPT_CLEAR_CDMA2           (1 << ODN_INTERRUPT_CLR_CDMA2_SHIFT)
+#define ODN_INTERRUPT_ENABLE_CDMA2          (1 << (ODN_INTERRUPT_ENABLE_CDMA_SHIFT + 1))
+#define ODN_INTERRUPT_STATUS_CDMA2          (1 << (ODN_INTERRUPT_STATUS_CDMA_SHIFT + 1))
+#define ODN_INTERRUPT_CLEAR_CDMA2           (1 << (ODN_INTERRUPT_CLR_CDMA_SHIFT + 1))
 
 /*
    Other defines
index 4d577e5..5d58216 100644 (file)
@@ -80,16 +80,16 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_ID_ID_SIGNED                        0
 
 /*
-       Register REVISION
+       Register REL
 */
-#define ODN_CORE_REVISION                       0x0004
-#define ODN_REVISION_MINOR_MASK                 0x0000FFFFU
-#define ODN_REVISION_MINOR_SHIFT                0
-#define ODN_REVISION_MINOR_SIGNED               0
+#define ODN_CORE_REL                            0x0004
+#define ODN_REL_MINOR_MASK                      0x0000FFFFU
+#define ODN_REL_MINOR_SHIFT                     0
+#define ODN_REL_MINOR_SIGNED                    0
 
-#define ODN_REVISION_MAJOR_MASK                 0xFFFF0000U
-#define ODN_REVISION_MAJOR_SHIFT                16
-#define ODN_REVISION_MAJOR_SIGNED               0
+#define ODN_REL_MAJOR_MASK                      0xFFFF0000U
+#define ODN_REL_MAJOR_SHIFT                     16
+#define ODN_REL_MAJOR_SIGNED                    0
 
 /*
        Register CHANGE_SET
@@ -103,7 +103,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        Register USER_ID
 */
 #define ODN_CORE_USER_ID                        0x000C
-#define ODN_USER_ID_ID_MASK                     0x0000000FU
+#define ODN_USER_ID_ID_MASK                     0x000000FFU
 #define ODN_USER_ID_ID_SHIFT                    0
 #define ODN_USER_ID_ID_SIGNED                   0
 
@@ -171,6 +171,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_EXTERNAL_RESETN_DUT_SPI_SHIFT       1
 #define ODN_EXTERNAL_RESETN_DUT_SPI_SIGNED      0
 
+#define ODN_EXTERNAL_RESETN_DUT_PEP_DDR_MASK    0x00000004U
+#define ODN_EXTERNAL_RESETN_DUT_PEP_DDR_SHIFT   2
+#define ODN_EXTERNAL_RESETN_DUT_PEP_DDR_SIGNED  0
+
+#define ODN_EXTERNAL_RESETN_DUT_IF_MASK         0x00000008U
+#define ODN_EXTERNAL_RESETN_DUT_IF_SHIFT        3
+#define ODN_EXTERNAL_RESETN_DUT_IF_SIGNED       0
+
+#define ODN_EXTERNAL_RESETN_DUT1_MASK           0x00000010U
+#define ODN_EXTERNAL_RESETN_DUT1_SHIFT          4
+#define ODN_EXTERNAL_RESETN_DUT1_SIGNED         0
+
+#define ODN_EXTERNAL_RESETN_DUT2_MASK           0x00000020U
+#define ODN_EXTERNAL_RESETN_DUT2_SHIFT          5
+#define ODN_EXTERNAL_RESETN_DUT2_SIGNED         0
+
 /*
        Register EXTERNAL_RESET
 */
@@ -251,13 +267,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_INTERRUPT_STATUS_GIST_OUT_MB_ERR_SHIFT 8
 #define ODN_INTERRUPT_STATUS_GIST_OUT_MB_ERR_SIGNED 0
 
-#define ODN_INTERRUPT_STATUS_CDMA_MASK          0x00000800U
+#define ODN_INTERRUPT_STATUS_DUT2_MASK          0x00000200U
+#define ODN_INTERRUPT_STATUS_DUT2_SHIFT         9
+#define ODN_INTERRUPT_STATUS_DUT2_SIGNED        0
+
+#define ODN_INTERRUPT_STATUS_AXI_LOCKUP_PROTECTION_MASK 0x00000400U
+#define ODN_INTERRUPT_STATUS_AXI_LOCKUP_PROTECTION_SHIFT 10
+#define ODN_INTERRUPT_STATUS_AXI_LOCKUP_PROTECTION_SIGNED 0
+
+#define ODN_INTERRUPT_STATUS_CDMA_MASK          0x00001800U
 #define ODN_INTERRUPT_STATUS_CDMA_SHIFT         11
 #define ODN_INTERRUPT_STATUS_CDMA_SIGNED        0
 
-#define ODN_INTERRUPT_STATUS_CDMA2_MASK          0x00001000U
-#define ODN_INTERRUPT_STATUS_CDMA2_SHIFT         12
-#define ODN_INTERRUPT_STATUS_CDMA2_SIGNED        0
+#define ODN_INTERRUPT_STATUS_OS_IRQ_MASK        0x001FE000U
+#define ODN_INTERRUPT_STATUS_OS_IRQ_SHIFT       13
+#define ODN_INTERRUPT_STATUS_OS_IRQ_SIGNED      0
 
 #define ODN_INTERRUPT_STATUS_IRQ_TEST_MASK      0x40000000U
 #define ODN_INTERRUPT_STATUS_IRQ_TEST_SHIFT     30
@@ -307,13 +331,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_INTERRUPT_ENABLE_GIST_OUT_MB_ERR_SHIFT 8
 #define ODN_INTERRUPT_ENABLE_GIST_OUT_MB_ERR_SIGNED 0
 
-#define ODN_INTERRUPT_ENABLE_CDMA_MASK          0x00000800U
+#define ODN_INTERRUPT_ENABLE_DUT2_MASK          0x00000200U
+#define ODN_INTERRUPT_ENABLE_DUT2_SHIFT         9
+#define ODN_INTERRUPT_ENABLE_DUT2_SIGNED        0
+
+#define ODN_INTERRUPT_ENABLE_AXI_LOCKUP_PROTECTION_MASK 0x00000400U
+#define ODN_INTERRUPT_ENABLE_AXI_LOCKUP_PROTECTION_SHIFT 10
+#define ODN_INTERRUPT_ENABLE_AXI_LOCKUP_PROTECTION_SIGNED 0
+
+#define ODN_INTERRUPT_ENABLE_CDMA_MASK          0x00001800U
 #define ODN_INTERRUPT_ENABLE_CDMA_SHIFT         11
 #define ODN_INTERRUPT_ENABLE_CDMA_SIGNED        0
 
-#define ODN_INTERRUPT_ENABLE_CDMA2_MASK          0x00001000U
-#define ODN_INTERRUPT_ENABLE_CDMA2_SHIFT         12
-#define ODN_INTERRUPT_ENABLE_CDMA2_SIGNED        0
+#define ODN_INTERRUPT_ENABLE_OS_IRQ_MASK        0x001FE000U
+#define ODN_INTERRUPT_ENABLE_OS_IRQ_SHIFT       13
+#define ODN_INTERRUPT_ENABLE_OS_IRQ_SIGNED      0
 
 #define ODN_INTERRUPT_ENABLE_IRQ_TEST_MASK      0x40000000U
 #define ODN_INTERRUPT_ENABLE_IRQ_TEST_SHIFT     30
@@ -363,13 +395,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_INTERRUPT_CLR_GIST_OUT_MB_ERR_SHIFT 8
 #define ODN_INTERRUPT_CLR_GIST_OUT_MB_ERR_SIGNED 0
 
-#define ODN_INTERRUPT_CLR_CDMA_MASK          0x00000800U
-#define ODN_INTERRUPT_CLR_CDMA_SHIFT         11
-#define ODN_INTERRUPT_CLR_CDMA_SIGNED        0
+#define ODN_INTERRUPT_CLR_DUT2_MASK             0x00000200U
+#define ODN_INTERRUPT_CLR_DUT2_SHIFT            9
+#define PVR5__INTERRUPT_CLR_DUT2_SIGNED           0
+
+#define ODN_INTERRUPT_CLR_AXI_LOCKUP_PROTECTION_MASK 0x00000400U
+#define ODN_INTERRUPT_CLR_AXI_LOCKUP_PROTECTION_SHIFT 10
+#define ODN_INTERRUPT_CLR_AXI_LOCKUP_PROTECTION_SIGNED 0
+
+#define ODN_INTERRUPT_CLR_CDMA_MASK             0x00001800U
+#define ODN_INTERRUPT_CLR_CDMA_SHIFT            11
+#define ODN_INTERRUPT_CLR_CDMA_SIGNED           0
 
-#define ODN_INTERRUPT_CLR_CDMA2_MASK          0x00001000U
-#define ODN_INTERRUPT_CLR_CDMA2_SHIFT         12
-#define ODN_INTERRUPT_CLR_CDMA2_SIGNED        0
+#define ODN_INTERRUPT_CLR_OS_IRQ_MASK           0x001FE000U
+#define ODN_INTERRUPT_CLR_OS_IRQ_SHIFT          13
+#define ODN_INTERRUPT_CLR_OS_IRQ_SIGNED         0
 
 #define ODN_INTERRUPT_CLR_IRQ_TEST_MASK         0x40000000U
 #define ODN_INTERRUPT_CLR_IRQ_TEST_SHIFT        30
@@ -388,6 +428,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_INTERRUPT_TEST_INTERRUPT_TEST_SIGNED 0
 
 /*
+       Register INTERRUPT_TIMEOUT_CLR
+*/
+#define ODN_CORE_INTERRUPT_TIMEOUT_CLR      0x0114
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_CLR_MASK 0x00000002U
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_CLR_SHIFT 1
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_CLR_SIGNED 0
+
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_MASK 0x00000001U
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_SHIFT 0
+#define ODN_INTERRUPT_TIMEOUT_CLR_INTERRUPT_MST_TIMEOUT_SIGNED 0
+
+/*
+       Register INTERRUPT_TIMEOUT
+*/
+#define ODN_CORE_INTERRUPT_TIMEOUT          0x0118
+#define ODN_INTERRUPT_TIMEOUT_INTERRUPT_TIMEOUT_THRESHOLD_COUNTER_MASK 0xFFFFFFFFU
+#define ODN_INTERRUPT_TIMEOUT_INTERRUPT_TIMEOUT_THRESHOLD_COUNTER_SHIFT 0
+#define ODN_INTERRUPT_TIMEOUT_INTERRUPT_TIMEOUT_THRESHOLD_COUNTER_SIGNED 0
+/*
        Register SYSTEM_ID
 */
 #define ODN_CORE_SYSTEM_ID                      0x011C
@@ -396,9 +455,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_SYSTEM_ID_ID_SIGNED                 0
 
 /*
-       Register SUPPORTED_FEATURE
+       Register SUPPORTED_FEATURES
 */
 #define ODN_CORE_SUPPORTED_FEATURES             0x0120
+#define ODN_SUPPORTED_FEATURES_UNIMPLEMENTED_FREATURES_MASK 0xFFFFFFFEU
+#define ODN_SUPPORTED_FEATURES_UNIMPLEMENTED_FREATURES_SHIFT 1
+#define ODN_SUPPORTED_FEATURES_UNIMPLEMENTED_FREATURES_SIGNED 0
+
 #define ODN_SUPPORTED_FEATURES_2X_CDMA_AND_IRQS_MASK 0x00000001U
 #define ODN_SUPPORTED_FEATURES_2X_CDMA_AND_IRQS_SHIFT 0
 #define ODN_SUPPORTED_FEATURES_2X_CDMA_AND_IRQS_SIGNED 0
@@ -647,6 +710,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ODN_DUT_MST_ADD_SLV_OUT_SHIFT           0
 #define ODN_DUT_MST_ADD_SLV_OUT_SIGNED          0
 
+/*
+       Register DUT_MULTIPLX_INFO
+*/
+#define ODN_CORE_DUT_MULTIPLX_INFO              0x0218
+#define ODN_DUT_MULTIPLX_INFO_MEM_MASK          0x000000FFU
+#define ODN_DUT_MULTIPLX_INFO_MEM_SHIFT         0
+#define ODN_DUT_MULTIPLX_INFO_MEM_SIGNED        0
 
 /****************************
   Generated from: ad_tx.def
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          System Description Header
+@Title          Definitions for virtualization
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header provides system-specific declarations and macros
+@Description    Services shared header for virtualization definitions
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,20 +41,23 @@ 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(__SYSINFO_H__)
-#define __SYSINFO_H__
+#ifndef SRV_VIRT_DEFS_H
+#define SRV_VIRT_DEFS_H
 
-/*!< System specific poll/timeout details */
-#if defined(VIRTUAL_PLATFORM) || defined(FPGA)
-#define MAX_HW_TIME_US                           (240000000)
-#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT  (120000)
-#else
-#define MAX_HW_TIME_US                           (500000)
-#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT  (1500)//(10000)
+#if !defined(GPUVIRT_VALIDATION_MAX_STRING_LENGTH)
+       #define GPUVIRT_VALIDATION_MAX_STRING_LENGTH 512
 #endif
-#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
-#define WAIT_TRY_COUNT                           (10000)
 
-#define SYS_RGX_DEV_NAME "tc_rogue"
+#define GPUVIRT_VALIDATION_MAX_OS 8
 
-#endif /* !defined(__SYSINFO_H__) */
+#define GPUVIRT_VALIDATION_NUM_REGIONS 2
+#define GPUVIRT_VAL_REGION_SECURE 0
+#define GPUVIRT_VAL_REGION_SHARED 1
+
+/* Shared region 1MB */
+#define GPUVIRT_SIZEOF_SHARED 0x100000
+
+/* Min region size 64MB */
+#define GPUVIRT_MIN_SIZE 0x4000000
+
+#endif /* SRV_VIRT_DEFS_H */
index af20049..987d37c 100644 (file)
@@ -54,7 +54,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* name,                            type,           class,       default,                                         helper,         */ \
 X(EnableTrustedDeviceAceConfig,     BOOL,           GPUVIRT_VAL, PVRSRV_APPHINT_ENABLETRUSTEDDEVICEACECONFIG,     NO_PARAM_TABLE   ) \
 X(CleanupThreadPriority,            UINT32,         NEVER,       PVRSRV_APPHINT_CLEANUPTHREADPRIORITY,            NO_PARAM_TABLE   ) \
-X(CacheOpThreadPriority,            UINT32,         NEVER,       PVRSRV_APPHINT_CACHEOPTHREADPRIORITY,            NO_PARAM_TABLE   ) \
 X(WatchdogThreadPriority,           UINT32,         NEVER,       PVRSRV_APPHINT_WATCHDOGTHREADPRIORITY,           NO_PARAM_TABLE   ) \
 X(HWPerfClientBufferSize,           UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFCLIENTBUFFERSIZE,           NO_PARAM_TABLE   ) \
 
@@ -116,7 +115,8 @@ X(EnablePollOnChecksumErrorStatus,  UINT32,         VALIDATION,  0,
 X(RiscvDmiTest,                     BOOL,           VALIDATION,  PVRSRV_APPHINT_RISCVDMITEST,                     NO_PARAM_TABLE   ) \
 X(DevMemFWHeapPolicy,               UINT32,         ALWAYS,      PVRSRV_APPHINT_FIRMWARE_HEAP_POLICY,             NO_PARAM_TABLE   ) \
 \
-X(EnableAPMAll,                     UINT32,         VALIDATION,  PVRSRV_APPHINT_ENABLEAPM,                        NO_PARAM_TABLE)
+X(EnableAPMAll,                     UINT32,         VALIDATION,  PVRSRV_APPHINT_ENABLEAPM,                        NO_PARAM_TABLE   ) \
+X(KernelCCBSizeLog2,                UINT32,         VALIDATION,  PVRSRV_APPHINT_KCCB_SIZE_LOG2,                   NO_PARAM_TABLE   )
 
 /*
 *******************************************************************************
@@ -127,8 +127,6 @@ X(EnableAPMAll,                     UINT32,         VALIDATION,  PVRSRV_APPHINT_
 X(EnableHTBLogGroup,                UINT32Bitfield, ALWAYS,      PVRSRV_APPHINT_ENABLEHTBLOGGROUP,                htb_loggroup_tbl ) \
 X(HTBOperationMode,                 UINT32List,     ALWAYS,      PVRSRV_APPHINT_HTBOPERATIONMODE,                 htb_opmode_tbl   ) \
 X(EnableFTraceGPU,                  BOOL,           ALWAYS,      PVRSRV_APPHINT_ENABLEFTRACEGPU,                  NO_PARAM_TABLE   ) \
-X(HWPerfFWFilter,                   UINT64,         ALWAYS,      PVRSRV_APPHINT_HWPERFFWFILTER,                   NO_PARAM_TABLE   ) \
-X(HWPerfHostFilter,                 UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFHOSTFILTER,                 NO_PARAM_TABLE   ) \
 X(HWPerfClientFilter_Services,      UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFCLIENTFILTER_SERVICES,      NO_PARAM_TABLE   ) \
 X(HWPerfClientFilter_EGL,           UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFCLIENTFILTER_EGL,           NO_PARAM_TABLE   ) \
 X(HWPerfClientFilter_OpenGLES,      UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFCLIENTFILTER_OPENGLES,      NO_PARAM_TABLE   ) \
@@ -137,7 +135,6 @@ X(HWPerfClientFilter_Vulkan,        UINT32,         ALWAYS,      PVRSRV_APPHINT_
 X(HWPerfClientFilter_OpenGL,        UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFCLIENTFILTER_OPENGL,        NO_PARAM_TABLE   ) \
 X(CacheOpConfig,                    UINT32,         ALWAYS,      PVRSRV_APPHINT_CACHEOPCONFIG,                    NO_PARAM_TABLE   ) \
 X(CacheOpUMKMThresholdSize,         UINT32,         ALWAYS,      PVRSRV_APPHINT_CACHEOPUMKMHRESHOLDSIZE,          NO_PARAM_TABLE   ) \
-X(TimeCorrClock,                    UINT32List,     ALWAYS,      PVRSRV_APPHINT_TIMECORRCLOCK,                    timecorr_clk_tbl )
 
 /*
 *******************************************************************************
@@ -152,14 +149,16 @@ X(CheckMList,                       BOOL,           ALWAYS,      PVRSRV_APPHINT_
 X(EnableLogGroup,                   UINT32Bitfield, ALWAYS,      PVRSRV_APPHINT_ENABLELOGGROUP,                   fwt_loggroup_tbl ) \
 X(FirmwareLogType,                  UINT32List,     ALWAYS,      PVRSRV_APPHINT_FIRMWARELOGTYPE,                  fwt_logtype_tbl  ) \
 X(HWRDebugDumpLimit,                UINT32,         ALWAYS,      PVRSRV_APPHINT_HWRDEBUGDUMPLIMIT,                NO_PARAM_TABLE   ) \
-X(KernelCCBSizeLog2,                UINT32,         VALIDATION,  PVRSRV_APPHINT_KCCB_SIZE_LOG2,                   NO_PARAM_TABLE   ) \
+X(TimeCorrClock,                    UINT32List,     ALWAYS,      PVRSRV_APPHINT_TIMECORRCLOCK,                    timecorr_clk_tbl ) \
+X(HWPerfFWFilter,                   UINT64,         ALWAYS,      PVRSRV_APPHINT_HWPERFFWFILTER,                   NO_PARAM_TABLE   ) \
 /* Device host config */ \
 X(EnableAPM,                        UINT32,         ALWAYS,      PVRSRV_APPHINT_ENABLEAPM,                        NO_PARAM_TABLE   ) \
 X(DisableFEDLogging,                BOOL,           ALWAYS,      PVRSRV_APPHINT_DISABLEFEDLOGGING,                NO_PARAM_TABLE   ) \
 X(ZeroFreelist,                     BOOL,           ALWAYS,      PVRSRV_APPHINT_ZEROFREELIST,                     NO_PARAM_TABLE   ) \
 X(DisablePDumpPanic,                BOOL,           PDUMP,       PVRSRV_APPHINT_DISABLEPDUMPPANIC,                NO_PARAM_TABLE   ) \
-X(EnableFWPoisonOnFree,             BOOL,           ALWAYS,      PVRSRV_APPHINT_ENABLEFWPOISONONFREE,             NO_PARAM_TABLE   ) \
+X(EnableFWPoisonOnFree,             BOOL,           DEBUG,       PVRSRV_APPHINT_ENABLEFWPOISONONFREE,             NO_PARAM_TABLE   ) \
 X(GPUUnitsPowerChange,              BOOL,           VALIDATION,  PVRSRV_APPHINT_GPUUNITSPOWERCHANGE,              NO_PARAM_TABLE   ) \
+X(HWPerfHostFilter,                 UINT32,         ALWAYS,      PVRSRV_APPHINT_HWPERFHOSTFILTER,                 NO_PARAM_TABLE   )
 
 /*
 *******************************************************************************
index db88a53..3ef7184 100644 (file)
@@ -126,6 +126,12 @@ typedef IMG_UINT32 PDUMP_FLAGS_T;
                                                           for the second and subsequent PDump client connections.
                                                           Never combine with the CONTINUOUS flag. */
 
+#define PDUMP_FLAGS_INTERVAL        0x04000000U    /*<! Output this entry even when the capture is on a
+                                                          "no capture interval frame" (see pdump -sr option).
+                                                          Useful for commands that have a resource that was written
+                                                          out in a frame that was captured. For example,
+                                                          used by RGXScheduleCleanupCommand. */
+
 #define PDUMP_FLAGS_DEBUG           0x00010000U    /*<! For internal debugging use */
 
 #define PDUMP_FLAGS_NOHW            0x00000001U    /* For internal use: Skip sending instructions to the hardware
index 838039c..060c5cd 100644 (file)
@@ -53,9 +53,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PHYSHEAP_H
 
 typedef struct _PHYS_HEAP_ PHYS_HEAP;
+#define INVALID_PHYS_HEAP 0xDEADDEAD
 
 struct _CONNECTION_DATA_;
 
+typedef struct _PG_HANDLE_
+{
+       union
+       {
+               void *pvHandle;
+               IMG_UINT64 ui64Handle;
+       }u;
+       /* The allocation order is log2 value of the number of pages to allocate.
+        * As such this is a correspondingly small value. E.g, for order 4 we
+        * are talking 2^4 * PAGE_SIZE contiguous allocation.
+        * DevPxAlloc API does not need to support orders higher than 4.
+        */
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       IMG_BYTE    uiOrder;    /* Order of the corresponding allocation */
+       IMG_BYTE    uiOSid;     /* OSid to use for allocation arena.
+                                * Connection-specific. */
+       IMG_BYTE    uiPad1,
+                   uiPad2;     /* Spare */
+#else
+       IMG_BYTE    uiOrder;    /* Order of the corresponding allocation */
+       IMG_BYTE    uiPad1,
+                   uiPad2,
+                   uiPad3;     /* Spare */
+#endif
+} PG_HANDLE;
+
 /*! Pointer to private implementation specific data */
 typedef void *PHEAP_IMPL_DATA;
 
@@ -89,6 +116,46 @@ typedef PVRSRV_ERROR (*PFN_GET_CPU_PADDR)(PHEAP_IMPL_DATA, IMG_CPU_PHYADDR*);
 @Return         PVRSRV_ERROR       PVRSRV_OK or error code
 */ /**************************************************************************/
 typedef PVRSRV_ERROR (*PFN_GET_SIZE)(PHEAP_IMPL_DATA, IMG_UINT64*);
+/*************************************************************************/ /*!
+@Function       Callback function PFN_GET_PAGE_SHIFT
+@Description    Get heap log2 page shift.
+@Return         IMG_UINT32         Log2 page shift
+*/ /**************************************************************************/
+typedef IMG_UINT32 (*PFN_GET_PAGE_SHIFT)(void);
+
+/*************************************************************************/ /*!
+@Function       Callback function PFN_GET_MEM_STATS
+@Description    Get total and free memory size of the physical heap managed by
+                the PMR Factory.
+@Input          PHEAP_IMPL_DATA    Pointer to implementation data.
+@Output         IMG_UINT64         total Size of heap.
+@Output         IMG_UINT64         free Size available in a heap.
+@Return         none
+*/ /**************************************************************************/
+typedef void (*PFN_GET_MEM_STATS)(PHEAP_IMPL_DATA, IMG_UINT64 *, IMG_UINT64 *);
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+typedef PVRSRV_ERROR (*PFN_PAGES_ALLOC_GPV)(PHYS_HEAP *psPhysHeap, size_t uiSize,
+                                            PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
+                                            IMG_UINT32 ui32OSid, IMG_PID uiPid);
+#endif
+typedef PVRSRV_ERROR (*PFN_PAGES_ALLOC)(PHYS_HEAP *psPhysHeap, size_t uiSize,
+                                        PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
+                                        IMG_PID uiPid);
+
+typedef void (*PFN_PAGES_FREE)(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle);
+
+typedef PVRSRV_ERROR (*PFN_PAGES_MAP)(PHYS_HEAP *psPhysHeap, PG_HANDLE *pshMemHandle,
+                                      size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+                                      void **pvPtr);
+
+typedef void (*PFN_PAGES_UNMAP)(PHYS_HEAP *psPhysHeap,
+                                PG_HANDLE *psMemHandle, void *pvPtr);
+
+typedef PVRSRV_ERROR (*PFN_PAGES_CLEAN)(PHYS_HEAP *psPhysHeap,
+                                        PG_HANDLE *pshMemHandle,
+                                        IMG_UINT32 uiOffset,
+                                        IMG_UINT32 uiLength);
 
 /*************************************************************************/ /*!
 @Function       Callback function PFN_CREATE_PMR
@@ -131,26 +198,31 @@ typedef struct PHEAP_IMPL_FUNCS_TAG
        PFN_GET_DEV_PADDR pfnGetDevPAddr;
        PFN_GET_CPU_PADDR pfnGetCPUPAddr;
        PFN_GET_SIZE pfnGetSize;
+       PFN_GET_PAGE_SHIFT pfnGetPageShift;
+       PFN_GET_MEM_STATS pfnGetPMRFactoryMemStats;
        PFN_CREATE_PMR pfnCreatePMR;
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       PFN_PAGES_ALLOC_GPV pfnPagesAllocGPV;
+#endif
+       PFN_PAGES_ALLOC pfnPagesAlloc;
+       PFN_PAGES_FREE pfnPagesFree;
+       PFN_PAGES_MAP pfnPagesMap;
+       PFN_PAGES_UNMAP pfnPagesUnMap;
+       PFN_PAGES_CLEAN pfnPagesClean;
 } PHEAP_IMPL_FUNCS;
 
 /*************************************************************************/ /*!
-@Function       PhysHeapCreateHeapsFromConfigs
-@Description    Create new heaps from configs.
+@Function       PhysHeapCreateDeviceHeapsFromConfigs
+@Description    Create new heaps for a device from configs.
 @Input          psDevNode      Pointer to device node struct
 @Input          pasConfigs     Pointer to array of Heap configurations.
 @Input          ui32NumConfigs Number of configurations in array.
-@Output         papsPhysHeaps  Pointer to array of phys heap pointers.
-@Output         pui32NumHeaps  Number of heaps created. Can be less than
-                               ui32NumConfigs if error.
 @Return         PVRSRV_ERROR PVRSRV_OK or error code
 */ /**************************************************************************/
 PVRSRV_ERROR
-PhysHeapCreateHeapsFromConfigs(PPVRSRV_DEVICE_NODE psDevNode,
-                                                         PHYS_HEAP_CONFIG *pasConfigs,
-                                                         IMG_UINT32 ui32NumConfigs,
-                                                         PHYS_HEAP **papsPhysHeaps,
-                                                         IMG_UINT32 *pui32NumHeaps);
+PhysHeapCreateDeviceHeapsFromConfigs(PPVRSRV_DEVICE_NODE psDevNode,
+                                     PHYS_HEAP_CONFIG *pasConfigs,
+                                     IMG_UINT32 ui32NumConfigs);
 
 /*************************************************************************/ /*!
 @Function       PhysHeapCreateHeapFromConfig
@@ -185,6 +257,14 @@ PVRSRV_ERROR PhysHeapCreate(PPVRSRV_DEVICE_NODE psDevNode,
                                                        PHEAP_IMPL_FUNCS *psImplFuncs,
                                                        PHYS_HEAP **ppsPhysHeap);
 
+/*************************************************************************/ /*!
+@Function       PhysHeapDestroyDeviceHeaps
+@Description    Destroys all heaps referenced by a device.
+@Input          psDevNode Pointer to a device node struct.
+@Return         void
+*/ /**************************************************************************/
+void PhysHeapDestroyDeviceHeaps(PPVRSRV_DEVICE_NODE psDevNode);
+
 void PhysHeapDestroy(PHYS_HEAP *psPhysHeap);
 
 PVRSRV_ERROR PhysHeapAcquire(PHYS_HEAP *psPhysHeap);
@@ -193,10 +273,12 @@ PVRSRV_ERROR PhysHeapAcquire(PHYS_HEAP *psPhysHeap);
 @Function       PhysHeapAcquireByUsage
 @Description    Acquire PhysHeap by usage flag.
 @Input          ui32UsageFlag PhysHeap usage flag
-@Output         ppsPhysHeap  PhysHeap if found.
+@Input          psDevNode     Pointer to device node struct
+@Output         ppsPhysHeap   PhysHeap if found.
 @Return         PVRSRV_ERROR PVRSRV_OK or error code
 */ /**************************************************************************/
 PVRSRV_ERROR PhysHeapAcquireByUsage(PHYS_HEAP_USAGE_FLAGS ui32UsageFlag,
+                                                                       PPVRSRV_DEVICE_NODE psDevNode,
                                                                        PHYS_HEAP **ppsPhysHeap);
 
 /*************************************************************************/ /*!
@@ -232,6 +314,8 @@ PHYS_HEAP_TYPE PhysHeapGetType(PHYS_HEAP *psPhysHeap);
 */ /**************************************************************************/
 PHYS_HEAP_USAGE_FLAGS PhysHeapGetFlags(PHYS_HEAP *psPhysHeap);
 
+IMG_BOOL PhysHeapValidateDefaultHeapExists(PPVRSRV_DEVICE_NODE psDevNode);
+
 PVRSRV_ERROR PhysHeapGetCpuPAddr(PHYS_HEAP *psPhysHeap,
                                                                           IMG_CPU_PHYADDR *psCpuPAddr);
 
@@ -239,11 +323,62 @@ PVRSRV_ERROR PhysHeapGetCpuPAddr(PHYS_HEAP *psPhysHeap,
 PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
                                                                   IMG_UINT64 *puiSize);
 
-PVRSRV_ERROR PhysHeapGetDevPAddr(PHYS_HEAP *psPhysHeap,
-                                                                          IMG_DEV_PHYADDR *psDevPAddr);
+/*************************************************************************/ /*!
+@Function       PVRSRVGetDevicePhysHeapCount
+@Description    Get the physical heap count supported by the device.
+@Input          psDevNode   Device node, the heap count is requested for.
+@Output         pui32PhysHeapCount  Buffer that holds the heap count
+@Return         None
+*/ /**************************************************************************/
+void PVRSRVGetDevicePhysHeapCount(PPVRSRV_DEVICE_NODE psDevNode,
+                                                                 IMG_UINT32 *pui32PhysHeapCount);
 
-PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
-                                                                  IMG_UINT64 *puiSize);
+/*************************************************************************/ /*!
+@Function       PhysHeapGetMemInfo
+@Description    Get phys heap memory statistics for a given physical heap ID.
+@Input          psDevNode          Pointer to device node struct
+@Input          ui32PhysHeapCount  Physical heap count
+@Input          paePhysHeapID      Physical heap ID
+@Output         paPhysHeapMemStats Buffer that holds the memory statistics
+@Return         PVRSRV_ERROR PVRSRV_OK or error code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PhysHeapGetMemInfo(PPVRSRV_DEVICE_NODE psDevNode,
+                                  IMG_UINT32 ui32PhysHeapCount,
+                                  PVRSRV_PHYS_HEAP *paePhysHeapID,
+                                  PHYS_HEAP_MEM_STATS_PTR paPhysHeapMemStats);
+
+/*************************************************************************/ /*!
+@Function       PhysHeapGetMemInfoPkd
+@Description    Get phys heap memory statistics for a given physical heap ID.
+@Input          psDevNode          Pointer to device node struct
+@Input          ui32PhysHeapCount  Physical heap count
+@Input          paePhysHeapID      Physical heap ID
+@Output         paPhysHeapMemStats Buffer that holds the memory statistics
+@Return         PVRSRV_ERROR PVRSRV_OK or error code
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PhysHeapGetMemInfoPkd(PPVRSRV_DEVICE_NODE psDevNode,
+                                         IMG_UINT32 ui32PhysHeapCount,
+                                         PVRSRV_PHYS_HEAP *paePhysHeapID,
+                                         PHYS_HEAP_MEM_STATS_PKD_PTR paPhysHeapMemStats);
+
+/*************************************************************************/ /*!
+@Function       PhysheapGetPhysMemUsage
+@Description    Get memory statistics for a given physical heap.
+@Input          psPhysHeap      Physical heap
+@Output         pui64TotalSize  Buffer that holds the total memory size of the
+                                given physical heap.
+@Output         pui64FreeSize   Buffer that holds the free memory available in
+                                a given physical heap.
+@Return         none
+*/ /**************************************************************************/
+void PhysheapGetPhysMemUsage(PHYS_HEAP *psPhysHeap,
+                                                        IMG_UINT64 *pui64TotalSize,
+                                                        IMG_UINT64 *pui64FreeSize);
+
+PVRSRV_ERROR PhysHeapGetDevPAddr(PHYS_HEAP *psPhysHeap,
+                                                                IMG_DEV_PHYADDR *psDevPAddr);
 
 void PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
                                                                IMG_UINT32 ui32NumOfAddr,
@@ -278,7 +413,7 @@ PVRSRV_ERROR PhysHeapCreatePMR(PHYS_HEAP *psPhysHeap,
                                                           IMG_UINT32 ui32PDumpFlags);
 
 PVRSRV_ERROR PhysHeapInit(void);
-PVRSRV_ERROR PhysHeapDeinit(void);
+void PhysHeapDeinit(void);
 
 /*************************************************************************/ /*!
 @Function       PhysHeapDeviceNode
@@ -304,4 +439,59 @@ IMG_BOOL PhysHeapPVRLayerAcquire(PVRSRV_PHYS_HEAP ePhysHeap);
 */ /**************************************************************************/
 IMG_BOOL PhysHeapUserModeAlloc(PVRSRV_PHYS_HEAP ePhysHeap);
 
+/*************************************************************************/ /*!
+@Function       PhysHeapMMUPxSetup
+@Description    Setup MMU Px allocation function pointers.
+@Input          psDeviceNode Pointer to device node struct
+@Return         PVRSRV_ERROR PVRSRV_OK on success.
+*/ /**************************************************************************/
+PVRSRV_ERROR PhysHeapMMUPxSetup(PPVRSRV_DEVICE_NODE psDeviceNode);
+
+/*************************************************************************/ /*!
+@Function       PhysHeapMMUPxDeInit
+@Description    Deinit after PhysHeapMMUPxSetup.
+@Input          psDeviceNode Pointer to device node struct
+*/ /**************************************************************************/
+void PhysHeapMMUPxDeInit(PPVRSRV_DEVICE_NODE psDeviceNode);
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+PVRSRV_ERROR PhysHeapPagesAllocGPV(PHYS_HEAP *psPhysHeap,
+                                   size_t uiSize,
+                                   PG_HANDLE *psMemHandle,
+                                   IMG_DEV_PHYADDR *psDevPAddr,
+                                   IMG_UINT32 ui32OSid, IMG_PID uiPid);
+#endif
+
+PVRSRV_ERROR PhysHeapPagesAlloc(PHYS_HEAP *psPhysHeap,
+                                size_t uiSize,
+                                PG_HANDLE *psMemHandle,
+                                IMG_DEV_PHYADDR *psDevPAddr,
+                                IMG_PID uiPid);
+
+void PhysHeapPagesFree(PHYS_HEAP *psPhysHeap,
+                       PG_HANDLE *psMemHandle);
+
+PVRSRV_ERROR PhysHeapPagesMap(PHYS_HEAP *psPhysHeap,
+                              PG_HANDLE *pshMemHandle,
+                              size_t uiSize,
+                              IMG_DEV_PHYADDR *psDevPAddr,
+                              void **pvPtr);
+
+void PhysHeapPagesUnMap(PHYS_HEAP *psPhysHeap,
+                        PG_HANDLE *psMemHandle,
+                        void *pvPtr);
+
+PVRSRV_ERROR PhysHeapPagesClean(PHYS_HEAP *psPhysHeap,
+                                PG_HANDLE *pshMemHandle,
+                                IMG_UINT32 uiOffset,
+                                IMG_UINT32 uiLength);
+
+/*************************************************************************/ /*!
+@Function       PhysHeapGetPageShift
+@Description    Get phys heap page shift.
+@Input          psPhysHeap   Pointer to physical heap.
+@Return         IMG_UINT32   Log2 page shift
+*/ /**************************************************************************/
+IMG_UINT32 PhysHeapGetPageShift(PHYS_HEAP *psPhysHeap);
+
 #endif /* PHYSHEAP_H */
index 22599e6..9d4d786 100644 (file)
@@ -88,29 +88,6 @@ typedef struct _PHYS_HEAP_FUNCTIONS_
        DevPAddrToCpuPAddr      pfnDevPAddrToCpuPAddr;
 } PHYS_HEAP_FUNCTIONS;
 
-/*! Type conveys the class of physical heap to instantiate within Services
- * for the physical pool of memory. */
-typedef enum _PHYS_HEAP_TYPE_
-{
-       PHYS_HEAP_TYPE_UNKNOWN = 0,     /*!< Not a valid value for any config */
-       PHYS_HEAP_TYPE_UMA,             /*!< Heap represents OS managed physical memory heap
-                                            i.e. system RAM. Unified Memory Architecture
-                                            physmem_osmem PMR factory */
-       PHYS_HEAP_TYPE_LMA,             /*!< Heap represents physical memory pool managed by
-                                            Services i.e. carve out from system RAM or local
-                                            card memory. Local Memory Architecture
-                                            physmem_lma PMR factory */
-       PHYS_HEAP_TYPE_DMA,             /*!< Heap represents a physical memory pool managed by
-                                            Services, alias of LMA and is only used on
-                                            VZ non-native system configurations for
-                                            a heap used for PHYS_HEAP_USAGE_FW_MAIN tagged
-                                            buffers */
-#if defined(SUPPORT_WRAP_EXTMEMOBJECT)
-       PHYS_HEAP_TYPE_WRAP,            /*!< Heap used to group UM buffers given
-                                            to Services. Integrity OS port only. */
-#endif
-} PHYS_HEAP_TYPE;
-
 /*! Structure used to describe a physical Heap supported by a system. A
  * system layer module can declare multiple physical heaps for different
  * purposes. At a minimum a system must provide one physical heap tagged for
index 26794af..fa4ca1f 100644 (file)
@@ -57,7 +57,9 @@ extern "C" {
 
 #include "common_rgxta3d_bridge.h"
 #include "common_rgxcmp_bridge.h"
+#if defined(SUPPORT_FASTRENDER_DM)
 #include "common_rgxtq2_bridge.h"
+#endif
 #if defined(SUPPORT_RGXTQ_BRIDGE)
 #include "common_rgxtq_bridge.h"
 #endif
@@ -73,7 +75,6 @@ extern "C" {
 #include "common_rgxregconfig_bridge.h"
 #endif
 #include "common_rgxkicksync_bridge.h"
-#include "common_rgxsignals_bridge.h"
 #include "common_rgxtimerquery_bridge.h"
 #if defined(SUPPORT_RGXRAY_BRIDGE)
 #include "common_rgxray_bridge.h"
@@ -170,20 +171,23 @@ extern "C" {
 #define PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST (PVRSRV_BRIDGE_RGXREGCONFIG_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST  (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXKICKSYNC_CMD_LAST)
 
-/* 137: RGX signals interface */
-#define PVRSRV_BRIDGE_RGXSIGNALS                 137UL
-#define PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST  (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST + 1)
-#define PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXSIGNALS_CMD_LAST)
-
-#define PVRSRV_BRIDGE_RGXTQ2                     138UL
-#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST      (PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST + 1)
+/* 137: RGX TQ2 interface */
+#define PVRSRV_BRIDGE_RGXTQ2                     137UL
+#if defined(SUPPORT_FASTRENDER_DM)
+#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST      (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST       (PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXTQ2_CMD_LAST)
+#else
+#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST      (0)
+#define PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST       (PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST)
+#endif
 
-#define PVRSRV_BRIDGE_RGXTIMERQUERY                 139UL
+/* 138: RGX timer query interface */
+#define PVRSRV_BRIDGE_RGXTIMERQUERY                 138UL
 #define PVRSRV_BRIDGE_RGXTIMERQUERY_DISPATCH_FIRST  (PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXTIMERQUERY_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXTIMERQUERY_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXTIMERQUERY_CMD_LAST)
 
-#define PVRSRV_BRIDGE_RGXRAY                 140UL
+/* 139: RGX Ray tracing interface */
+#define PVRSRV_BRIDGE_RGXRAY                 139UL
 #if defined(SUPPORT_RGXRAY_BRIDGE)
 #define PVRSRV_BRIDGE_RGXRAY_DISPATCH_FIRST  (PVRSRV_BRIDGE_RGXTIMERQUERY_DISPATCH_LAST + 1)
 #define PVRSRV_BRIDGE_RGXRAY_DISPATCH_LAST   (PVRSRV_BRIDGE_RGXRAY_DISPATCH_FIRST + PVRSRV_BRIDGE_RGXRAY_CMD_LAST)
@@ -215,9 +219,6 @@ static const IMG_UINT32 gui32RGXBridges =
        | (1U << (PVRSRV_BRIDGE_RGXREGCONFIG - PVRSRV_BRIDGE_RGX_FIRST))
 #endif
        | (1U << (PVRSRV_BRIDGE_RGXKICKSYNC - PVRSRV_BRIDGE_RGX_FIRST))
-#if defined(RGX_FEATURE_SIGNAL_SNOOPING) || defined(__KERNEL__)
-       | (1U << (PVRSRV_BRIDGE_RGXSIGNALS - PVRSRV_BRIDGE_RGX_FIRST))
-#endif
 #if defined(SUPPORT_FASTRENDER_DM) || defined(__KERNEL__)
        | (1U << (PVRSRV_BRIDGE_RGXTQ2 - PVRSRV_BRIDGE_RGX_FIRST))
 #endif
index 507cbda..16fc36b 100644 (file)
@@ -73,10 +73,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define APPHINT_LIST_MODPARAM \
 /* name,                            type,           class,       default,                                         helper,         */ \
 X(EnableCDMKillingRandMode,         BOOL,           VALIDATION,  PVRSRV_APPHINT_ENABLECDMKILLINGRANDMODE,         NO_PARAM_TABLE   ) \
-X(VDMContextSwitchMode,             UINT32,         VALIDATION,  PVRSRV_APPHINT_VDMCONTEXTSWITCHMODE,             NO_PARAM_TABLE   ) \
 \
 X(HWPerfDisableCustomCounterFilter, BOOL,           VALIDATION,  PVRSRV_APPHINT_HWPERFDISABLECUSTOMCOUNTERFILTER, NO_PARAM_TABLE   ) \
+X(ValidateSOCUSCTimer,              BOOL,           VALIDATION,  PVRSRV_APPHINT_VALIDATESOCUSCTIMERS,             NO_PARAM_TABLE   ) \
 X(ECCRAMErrInj,                     UINT32,         VALIDATION,  0,                                               NO_PARAM_TABLE   ) \
+\
+X(TFBCCompressionControlGroup,      UINT32,         VALIDATION,  PVRSRV_APPHINT_TFBCCOMPRESSIONCONTROLGROUP,      NO_PARAM_TABLE   ) \
+X(TFBCCompressionControlScheme,     UINT32,         VALIDATION,  PVRSRV_APPHINT_TFBCCOMPRESSIONCONTROLSCHEME,     NO_PARAM_TABLE   ) \
+X(TFBCCompressionControlYUVFormat,  BOOL,           VALIDATION,  0,                                               NO_PARAM_TABLE   ) \
 
 /*
 *******************************************************************************
index 72f4dd5..65ba85d 100644 (file)
@@ -191,7 +191,7 @@ PVRSRV_ERROR RGXHWPerfGetFilter(
 
 
 /*************************************************************************/ /*!
-@Function       RGXHWPerfConfigureAndEnableCounters
+@Function       RGXHWPerfConfigMuxCounters
 @Description    Enable and configure the performance counter block for one or
                  more device layout modules.
                  See RGXHWPerfConfigureAndEnableCustomCounters().
@@ -201,10 +201,10 @@ PVRSRV_ERROR RGXHWPerfGetFilter(
 @Input          asBlockConfigs     Address of the array of configuration blocks
 @Return         PVRSRV_ERROR       System error code
 */ /**************************************************************************/
-PVRSRV_ERROR RGXHWPerfConfigureAndEnableCounters(
-               RGX_HWPERF_CONNECTION *psHWPerfConnection,
-               IMG_UINT32                 ui32NumBlocks,
-               RGX_HWPERF_CONFIG_CNTBLK*  asBlockConfigs);
+PVRSRV_ERROR RGXHWPerfConfigMuxCounters(
+               RGX_HWPERF_CONNECTION         *psHWPerfConnection,
+               IMG_UINT32                     ui32NumBlocks,
+               RGX_HWPERF_CONFIG_MUX_CNTBLK  *asBlockConfigs);
 
 /*************************************************************************/ /*!
 @Function       RGXHWPerfConfigureAndEnableCustomCounters
index e7c96c3..ce17847 100644 (file)
@@ -64,7 +64,7 @@ struct SYNC_CHECKPOINT_RECORD;
 
 typedef struct _SYNC_CHECKPOINT_CONTEXT_CTL_ _SYNC_CHECKPOINT_CONTEXT_CTL, *_PSYNC_CHECKPOINT_CONTEXT_CTL;
 
-typedef struct _SYNC_CHECKPOINT_CONTEXT_
+typedef struct SYNC_CHECKPOINT_CONTEXT_TAG
 {
        PPVRSRV_DEVICE_NODE                             psDevNode;
        IMG_CHAR                                                azName[PVRSRV_SYNC_NAME_LENGTH];       /*!< Name of the RA */
@@ -100,7 +100,7 @@ typedef struct _SYNC_CHECKPOINT_BLOCK_
 
 typedef struct SYNC_CHECKPOINT_RECORD* PSYNC_CHECKPOINT_RECORD_HANDLE;
 
-typedef struct _SYNC_CHECKPOINT_
+typedef struct SYNC_CHECKPOINT_TAG
 {
        //_SYNC_CHECKPOINT_CONTEXT      *psContext;             /*!< pointer to the parent context of this checkpoint */
        /* A sync checkpoint is assigned a unique ID, to avoid any confusion should
@@ -122,12 +122,12 @@ typedef struct _SYNC_CHECKPOINT_
        DLLIST_NODE                     sDeferredFreeListNode;  /*!< List node for the deferred free sync chkpt list */
        IMG_UINT32                      ui32FWAddr;             /*!< FWAddr stored at sync checkpoint alloc time */
        PDUMP_FLAGS_T                   ui32PDumpFlags;         /*!< Pdump Capture mode to be used for POL*/
-} _SYNC_CHECKPOINT;
+} SYNC_CHECKPOINT;
 
 
 typedef struct _SYNC_CHECKPOINT_SIGNAL_
 {
-       _SYNC_CHECKPOINT                asSyncCheckpoint;       /*!< Store sync checkpt for deferred signal */
+       SYNC_CHECKPOINT                asSyncCheckpoint;       /*!< Store sync checkpt for deferred signal */
        IMG_UINT32                      ui32Status;             /*!< sync checkpt status signal/errored */
 } _SYNC_CHECKPOINT_DEFERRED_SIGNAL;
 
@@ -267,4 +267,22 @@ SyncCheckpointGetTimeline(PSYNC_CHECKPOINT psSyncCheckpoint);
 PRGXFWIF_UFO_ADDR*
 SyncCheckpointGetRGXFWIFUFOAddr(PSYNC_CHECKPOINT psSyncCheckpoint);
 
+#if !defined(SUPPORT_NATIVE_FENCE_SYNC)
+/*************************************************************************/ /*!
+@Function       SyncCheckpointGetAssociatedDevice
+
+@Description    .
+
+@Input          psSyncCheckpointContext Synchronisation Checkpoint context
+                                        to get the device node of
+
+@Return         The PVRSRV_DEVICE_NODE of the device on which the sync
+                checkpoint context was created.
+
+*/
+/*****************************************************************************/
+PPVRSRV_DEVICE_NODE
+SyncCheckpointGetAssociatedDevice(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext);
+#endif /* !defined(SUPPORT_NATIVE_FENCE_SYNC) */
+
 #endif /* SYNC_CHECKPOINT_INTERNAL_H */
index c9122b8..368c1ee 100644 (file)
@@ -86,32 +86,22 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DECR_WRAP(x)                                           ((x-1) < 0 ? (CACHEOP_STATS_ITEMS_MAX-1) : (x-1))
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
 /* Refer to CacheOpStatsExecLogHeader() for header item names */
-#define CACHEOP_RI_PRINTF_HEADER                       "%-8s %-10s %-10s %-5s %-16s %-16s %-10s %-10s %-18s %-18s %-12s"
-#define CACHEOP_RI_PRINTF                                      "%-8d %-10s %-10s %-5s 0x%-14llx 0x%-14llx 0x%-8llx 0x%-8llx %-18llu %-18llu 0x%-10x\n"
+#define CACHEOP_RI_PRINTF_HEADER                       "%-8s %-8s %-10s %-10s %-5s %-16s %-16s %-10s %-10s %-18s"
+#define CACHEOP_RI_PRINTF                                      "%-8d %-8d %-10s %-10s %-5s 0x%-14llx 0x%-14llx 0x%-8llx 0x%-8llx %-18llu\n"
 #else
-#define CACHEOP_PRINTF_HEADER                          "%-8s %-10s %-10s %-5s %-10s %-10s %-18s %-18s %-12s"
-#define CACHEOP_PRINTF                                         "%-8d %-10s %-10s %-5s 0x%-8llx 0x%-8llx %-18llu %-18llu 0x%-10x\n"
+#define CACHEOP_PRINTF_HEADER                          "%-8s %-8s %-10s %-10s %-5s %-10s %-10s %-18s"
+#define CACHEOP_PRINTF                                         "%-8d %-8d %-10s %-10s %-5s 0x%-8llx 0x%-8llx %-18llu\n"
 #endif
 #endif
 
 //#define CACHEOP_NO_CACHE_LINE_ALIGNED_ROUNDING               /* Force OS page (not cache line) flush granularity */
 #define CACHEOP_PVR_ASSERT(x)                                                  /* Define as PVR_ASSERT(x), enable for swdev & testing */
-#if defined(PVRSRV_SERVER_THREADS_INDEFINITE_SLEEP)
-#define CACHEOP_THREAD_WAIT_TIMEOUT                    0ULL            /* Wait indefinitely */
-#else
-#define CACHEOP_THREAD_WAIT_TIMEOUT                    500000ULL       /* Wait 500ms between wait unless woken-up on demand */
-#endif
-#define CACHEOP_FENCE_WAIT_TIMEOUT                     1000ULL         /* Wait 1ms between wait events unless woken-up */
-#define CACHEOP_FENCE_RETRY_ABORT                      1000ULL         /* Fence retries that aborts fence operation */
-#define CACHEOP_SEQ_MIDPOINT (IMG_UINT32)      0x7FFFFFFF      /* Where seqNum(s) are rebase, compared at */
-#define CACHEOP_ABORT_FENCE_ERROR_STRING       "detected stalled client, retrying cacheop fence"
 #define CACHEOP_DEVMEM_OOR_ERROR_STRING                "cacheop device memory request is out of range"
 #define CACHEOP_MAX_DEBUG_MESSAGE_LEN          160
 
 typedef struct _CACHEOP_WORK_ITEM_
 {
        PMR *psPMR;
-       IMG_UINT32 ui32OpSeqNum;
        IMG_DEVMEM_SIZE_T uiSize;
        PVRSRV_CACHE_OP uiCacheOp;
        IMG_DEVMEM_OFFSET_T uiOffset;
@@ -119,37 +109,26 @@ typedef struct _CACHEOP_WORK_ITEM_
        SYNC_TIMELINE_OBJ sSWTimelineObj;
        PVRSRV_DEVICE_NODE *psDevNode;
 #if defined(CACHEOP_DEBUG)
-       IMG_UINT64 ui64EnqueuedTime;
-       IMG_UINT64 ui64DequeuedTime;
-       IMG_UINT64 ui64ExecuteTime;
-       IMG_BOOL bDeferred;
+       IMG_UINT64 ui64StartTime;
+       IMG_UINT64 ui64EndTime;
        IMG_BOOL bKMReq;
-       IMG_BOOL bUMF;
        IMG_PID pid;
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-       RGXFWIF_DM eFenceOpType;
-#endif
 #endif
 } CACHEOP_WORK_ITEM;
 
 typedef struct _CACHEOP_STATS_EXEC_ITEM_
 {
+       IMG_UINT32 ui32DeviceID;
        IMG_PID pid;
-       IMG_UINT32 ui32OpSeqNum;
        PVRSRV_CACHE_OP uiCacheOp;
        IMG_DEVMEM_SIZE_T uiOffset;
        IMG_DEVMEM_SIZE_T uiSize;
-       IMG_UINT64 ui64EnqueuedTime;
-       IMG_UINT64 ui64DequeuedTime;
-       IMG_UINT64 ui64ExecuteTime;
-       IMG_BOOL bIsFence;
+       IMG_UINT64 ui64StartTime;
+       IMG_UINT64 ui64EndTime;
        IMG_BOOL bKMReq;
-       IMG_BOOL bUMF;
-       IMG_BOOL bDeferred;
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
        IMG_DEV_VIRTADDR sDevVAddr;
        IMG_DEV_PHYADDR sDevPAddr;
-       RGXFWIF_DM eFenceOpType;
 #endif
 } CACHEOP_STATS_EXEC_ITEM;
 
@@ -181,112 +160,31 @@ typedef struct _CACHEOP_WORK_QUEUE_
        IMG_UINT32 uiLineShift;
        IMG_UINT32 uiPageShift;
        OS_CACHE_OP_ADDR_TYPE uiCacheOpAddrType;
-/*
-  CacheOp deferred queueing protocol
-  + Implementation geared for performance, atomic counter based
-       - Value Space is 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> n.
-       - Index Space is 0 -> 1 -> 2 -> 3 -> 0 -> 1 -> 2 -> 3 -> 0 -> m.
-               - Index = Value modulo CACHEOP_INDICES_LOG2_SIZE.
-  + Write counter never collides with read counter in index space
-       - Unless at start of day when both are initialised to zero.
-       - This means we sacrifice one entry when the queue is full.
-       - Incremented by producer
-               - Value space tracks total number of CacheOps queued.
-               - Index space identifies CacheOp CCB queue index.
-  + Read counter increments towards write counter in value space
-       - Empty queue occurs when read equals write counter.
-       - Wrap-round logic handled by consumer as/when needed.
-       - Incremented by consumer
-               - Value space tracks total # of CacheOps executed.
-               - Index space identifies CacheOp CCB queue index.
-  + Total queued size adjusted up/down during write/read activity
-       - Counter might overflow but does not compromise framework.
- */
-       ATOMIC_T hReadCounter;
-       ATOMIC_T hWriteCounter;
-/*
-  CacheOp sequence numbers
-  + hCommonSeqNum:
-       - Common sequence, numbers every CacheOp operation in both UM/KM.
-       - In KM
-               - Every deferred CacheOp (on behalf of UM) gets a unique seqNum.
-               - Last executed deferred CacheOp updates gsCwq.hCompletedSeqNum.
-               - Under debug, all CacheOp gets a unique seqNum for tracking.
-               - This includes all UM/KM synchronous non-deferred CacheOp(s)
-       - In UM
-               - CacheOp(s) discarding happens in both UM and KM space.
-  + hCompletedSeqNum:
-       - Tracks last executed KM/deferred RBF/Global<timeline> CacheOp(s)
- */
-       ATOMIC_T hCommonSeqNum;
-       ATOMIC_T hCompletedSeqNum;
-/*
-  CacheOp information page
-  + psInfoPagePMR:
-       - Single system-wide OS page that is multi-mapped in UM/KM.
-       - Mapped into clients using read-only memory protection.
-       - Mapped into server using read/write memory protection.
-       - Contains information pertaining to cache framework.
-  + pui32InfoPage:
-       - Server linear address pointer to said information page.
-       - Each info-page entry currently of sizeof(IMG_UINT32).
- */
        PMR *psInfoPagePMR;
        IMG_UINT32 *pui32InfoPage;
-/*
-  CacheOp deferred work-item queue
-  + CACHEOP_INDICES_LOG2_SIZE
- */
-#define CACHEOP_INDICES_LOG2_SIZE      (4)
-#define CACHEOP_INDICES_MAX                    (1 << CACHEOP_INDICES_LOG2_SIZE)
-#define CACHEOP_INDICES_MASK           (CACHEOP_INDICES_MAX-1)
-       CACHEOP_WORK_ITEM asWorkItems[CACHEOP_INDICES_MAX];
+
 #if defined(CACHEOP_DEBUG)
 /*
   CacheOp statistics
  */
        DI_ENTRY *psDIEntry;
        IMG_HANDLE hStatsExecLock;
-       IMG_UINT32 ui32ServerASync;
-       IMG_UINT32 ui32ServerSyncVA;
-       IMG_UINT32 ui32ServerSync;
-       IMG_UINT32 ui32ServerRBF;
-       IMG_UINT32 ui32ServerDTL;
-       IMG_UINT32 ui32ClientSync;
-       IMG_UINT32 ui32ClientRBF;
-       IMG_UINT32 ui32TotalFenceOps;
-       IMG_UINT32 ui32TotalExecOps;
+
+       IMG_UINT32 ui32ServerOps;
+       IMG_UINT32 ui32ClientOps;
+       IMG_UINT32 ui32TotalOps;
+       IMG_UINT32 ui32ServerOpUsedUMVA;
        IMG_UINT32 ui32AvgExecTime;
        IMG_UINT32 ui32AvgExecTimeRemainder;
-       IMG_UINT32 ui32AvgFenceTime;
-       IMG_UINT32 ui32AvgFenceTimeRemainder;
+
        IMG_INT32 i32StatsExecWriteIdx;
        CACHEOP_STATS_EXEC_ITEM asStatsExecuted[CACHEOP_STATS_ITEMS_MAX];
 #endif
-/*
-  CacheOp (re)configuration
- */
+
        DI_ENTRY *psConfigTune;
        IMG_HANDLE hConfigLock;
-/*
-  CacheOp deferred worker thread
-  + eConfig
-       - Runtime configuration
-  + hWorkerThread
-       - CacheOp thread handler
-  + hThreadWakeUpEvtObj
-       - Event object to drive CacheOp worker thread sleep/wake-ups.
-  + hClientWakeUpEvtObj
-       - Event object to unblock stalled clients waiting on queue.
- */
        CACHEOP_CONFIG  eConfig;
        IMG_UINT32              ui32Config;
-       IMG_HANDLE              hWorkerThread;
-       IMG_HANDLE              hDeferredLock;
-       IMG_HANDLE              hThreadWakeUpEvtObj;
-       IMG_HANDLE              hClientWakeUpEvtObj;
-       IMG_UINT32              ui32FenceWaitTimeUs;
-       IMG_UINT32              ui32FenceRetryAbort;
        IMG_BOOL                bSupportsUMFlush;
 } CACHEOP_WORK_QUEUE;
 
@@ -294,54 +192,8 @@ typedef struct _CACHEOP_WORK_QUEUE_
 static CACHEOP_WORK_QUEUE gsCwq;
 
 #define CacheOpConfigSupports(e) ((gsCwq.eConfig & (e)) ? IMG_TRUE : IMG_FALSE)
-
 extern void do_invalid_range(unsigned long start, unsigned long len);
 
-
-
-
-static INLINE IMG_UINT32 CacheOpIdxRead(ATOMIC_T *phCounter)
-{
-       IMG_UINT32 ui32Idx = OSAtomicRead(phCounter);
-       return ui32Idx & CACHEOP_INDICES_MASK;
-}
-
-static INLINE IMG_UINT32 CacheOpIdxIncrement(ATOMIC_T *phCounter)
-{
-       IMG_UINT32 ui32Idx = OSAtomicIncrement(phCounter);
-       return ui32Idx & CACHEOP_INDICES_MASK;
-}
-
-static INLINE IMG_UINT32 CacheOpIdxNext(ATOMIC_T *phCounter)
-{
-       IMG_UINT32 ui32Idx = OSAtomicRead(phCounter);
-       return ++ui32Idx & CACHEOP_INDICES_MASK;
-}
-
-static INLINE IMG_UINT32 CacheOpIdxSpan(ATOMIC_T *phLhs, ATOMIC_T *phRhs)
-{
-       return OSAtomicRead(phLhs) - OSAtomicRead(phRhs);
-}
-
-/* Callback to dump info of cacheop thread in debug_dump */
-static void CacheOpThreadDumpInfo(DUMPDEBUG_PRINTF_FUNC* pfnDumpDebugPrintf,
-                                                               void *pvDumpDebugFile)
-{
-       PVR_DUMPDEBUG_LOG("    Configuration: QSZ: %d, UKT: %d, KDFT: %d, "
-                         "LINESIZE: %d, PGSIZE: %d, KDF: %s, "
-                         "URBF: %s",
-                         CACHEOP_INDICES_MAX,
-                         gsCwq.pui32InfoPage[CACHEOP_INFO_UMKMTHRESHLD],
-                         gsCwq.pui32InfoPage[CACHEOP_INFO_KMDFTHRESHLD],
-                         gsCwq.pui32InfoPage[CACHEOP_INFO_LINESIZE],
-                         gsCwq.pui32InfoPage[CACHEOP_INFO_PGSIZE],
-                         gsCwq.eConfig & CACHEOP_CONFIG_KDF  ? "Yes" : "No",
-                         gsCwq.eConfig & CACHEOP_CONFIG_URBF ? "Yes" : "No"
-                         );
-       PVR_DUMPDEBUG_LOG("    Pending deferred CacheOp entries : %u",
-                         CacheOpIdxSpan(&gsCwq.hWriteCounter, &gsCwq.hReadCounter));
-}
-
 #if defined(CACHEOP_DEBUG)
 static INLINE void CacheOpStatsExecLogHeader(IMG_CHAR szBuffer[CACHEOP_MAX_DEBUG_MESSAGE_LEN])
 {
@@ -351,31 +203,27 @@ static INLINE void CacheOpStatsExecLogHeader(IMG_CHAR szBuffer[CACHEOP_MAX_DEBUG
 #else
                                CACHEOP_PRINTF_HEADER,
 #endif
+                               "DevID",
                                "Pid",
                                "CacheOp",
-                               "  Type",
-                               "Mode",
+                               "Type",
+                               "Origin",
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                                "DevVAddr",
                                "DevPAddr",
 #endif
                                "Offset",
                                "Size",
-                               "xTime (us)",
-                               "qTime (us)",
-                               "SeqNum");
+                               "xTime (us)");
 }
 
 static void CacheOpStatsExecLogWrite(CACHEOP_WORK_ITEM *psCacheOpWorkItem)
 {
-       IMG_UINT64 ui64ExecuteTime;
-       IMG_UINT64 ui64EnqueuedTime;
        IMG_INT32 i32WriteOffset;
-
-       if (!psCacheOpWorkItem->ui32OpSeqNum && !psCacheOpWorkItem->uiCacheOp)
+       IMG_UINT32 ui32ExecTime;
+       printk("log write\n");
+       if (!psCacheOpWorkItem->uiCacheOp)
        {
-               /* This breaks the logic of read-out, so we do not queue items
-                  with zero sequence number and no CacheOp */
                return;
        }
        else if (psCacheOpWorkItem->bKMReq && !CacheOpConfigSupports(CACHEOP_CONFIG_KLOG))
@@ -387,20 +235,16 @@ static void CacheOpStatsExecLogWrite(CACHEOP_WORK_ITEM *psCacheOpWorkItem)
        OSLockAcquire(gsCwq.hStatsExecLock);
 
        i32WriteOffset = gsCwq.i32StatsExecWriteIdx;
-       gsCwq.asStatsExecuted[i32WriteOffset].pid = psCacheOpWorkItem->pid;
        gsCwq.i32StatsExecWriteIdx = INCR_WRAP(gsCwq.i32StatsExecWriteIdx);
-       gsCwq.asStatsExecuted[i32WriteOffset].bUMF = psCacheOpWorkItem->bUMF;
+       gsCwq.asStatsExecuted[i32WriteOffset].ui32DeviceID = psCacheOpWorkItem->psDevNode ? psCacheOpWorkItem->psDevNode->sDevId.ui32InternalID : -1;
+       gsCwq.asStatsExecuted[i32WriteOffset].pid = psCacheOpWorkItem->pid;
        gsCwq.asStatsExecuted[i32WriteOffset].uiSize = psCacheOpWorkItem->uiSize;
        gsCwq.asStatsExecuted[i32WriteOffset].bKMReq = psCacheOpWorkItem->bKMReq;
        gsCwq.asStatsExecuted[i32WriteOffset].uiOffset  = psCacheOpWorkItem->uiOffset;
        gsCwq.asStatsExecuted[i32WriteOffset].uiCacheOp = psCacheOpWorkItem->uiCacheOp;
-       gsCwq.asStatsExecuted[i32WriteOffset].bDeferred = psCacheOpWorkItem->bDeferred;
-       gsCwq.asStatsExecuted[i32WriteOffset].ui32OpSeqNum      = psCacheOpWorkItem->ui32OpSeqNum;
-       gsCwq.asStatsExecuted[i32WriteOffset].ui64ExecuteTime = psCacheOpWorkItem->ui64ExecuteTime;
-       gsCwq.asStatsExecuted[i32WriteOffset].ui64EnqueuedTime = psCacheOpWorkItem->ui64EnqueuedTime;
-       gsCwq.asStatsExecuted[i32WriteOffset].ui64DequeuedTime = psCacheOpWorkItem->ui64DequeuedTime;
-       /* During early system initialisation, only non-fence & non-PMR CacheOps are processed */
-       gsCwq.asStatsExecuted[i32WriteOffset].bIsFence = gsCwq.bInit && !psCacheOpWorkItem->psPMR;
+       gsCwq.asStatsExecuted[i32WriteOffset].ui64StartTime = psCacheOpWorkItem->ui64StartTime;
+       gsCwq.asStatsExecuted[i32WriteOffset].ui64EndTime = psCacheOpWorkItem->ui64EndTime;
+
        CACHEOP_PVR_ASSERT(gsCwq.asStatsExecuted[i32WriteOffset].pid);
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
        if (gsCwq.bInit && psCacheOpWorkItem->psPMR)
@@ -437,74 +281,60 @@ static void CacheOpStatsExecLogWrite(CACHEOP_WORK_ITEM *psCacheOpWorkItem)
 
                gsCwq.asStatsExecuted[i32WriteOffset].sDevPAddr.uiAddr = sDevPAddr.uiAddr;
        }
-
-       if (gsCwq.asStatsExecuted[i32WriteOffset].bIsFence)
-       {
-               gsCwq.asStatsExecuted[i32WriteOffset].eFenceOpType = psCacheOpWorkItem->eFenceOpType;
-       }
 #endif
 
-       {
-               /* Convert timing from nanoseconds to microseconds */
-               IMG_UINT64 ui64ExecuteTimeNs = gsCwq.asStatsExecuted[i32WriteOffset].ui64ExecuteTime;
-               IMG_UINT64 ui64EnqueuedTimeNs = gsCwq.asStatsExecuted[i32WriteOffset].ui64EnqueuedTime;
-
-               do_div(ui64ExecuteTimeNs, 1000);
-               do_div(ui64EnqueuedTimeNs, 1000);
+       /* Calculate the approximate cumulative moving average execution time.
+        * This calculation is based on standard equation:
+        *
+        * CMAnext = (new + count * CMAprev) / (count + 1)
+        *
+        * but in simplified form:
+        *
+        * CMAnext = CMAprev + (new - CMAprev) / (count + 1)
+        *
+        * this gets rid of multiplication and prevents overflow.
+        *
+        * Also to increase accuracy that we lose with integer division,
+        * we hold the moving remainder of the division and add it.
+        *
+        * CMAnext = CMAprev + (new - CMAprev + CMRprev) / (count + 1)
+        *
+        * Multiple tests proved it to be the best solution for approximating
+        * CMA using integers.
+        *
+        */
 
-               ui64ExecuteTime = ui64ExecuteTimeNs;
-               ui64EnqueuedTime = ui64EnqueuedTimeNs;
-       }
+       ui32ExecTime =
+               gsCwq.asStatsExecuted[i32WriteOffset].ui64EndTime -
+               gsCwq.asStatsExecuted[i32WriteOffset].ui64StartTime;
 
-       /* Coalesced deferred CacheOps do not contribute to statistics,
-          as both enqueue/execute time is identical for these CacheOps */
-       if (!gsCwq.asStatsExecuted[i32WriteOffset].bIsFence)
        {
-               /* Calculate the approximate cumulative moving average execution time.
-                * This calculation is based on standard equation:
-                *
-                * CMAnext = (new + count * CMAprev) / (count + 1)
-                *
-                * but in simplified form:
-                *
-                * CMAnext = CMAprev + (new - CMAprev) / (count + 1)
-                *
-                * this gets rid of multiplication and prevents overflow.
-                *
-                * Also to increase accuracy that we lose with integer division,
-                * we hold the moving remainder of the division and add it.
-                *
-                * CMAnext = CMAprev + (new - CMAprev + CMRprev) / (count + 1)
-                *
-                * Multiple tests proved it to be the best solution for approximating
-                * CMA using integers.
-                *
-                */
 
-               IMG_UINT32 ui32Time = ui64ExecuteTime - ui64EnqueuedTime;
-               IMG_INT32 i32Div = (IMG_INT32)ui32Time - (IMG_INT32)gsCwq.ui32AvgExecTime + (IMG_INT32)gsCwq.ui32AvgExecTimeRemainder;
+       IMG_INT32 i32Div =
+               (IMG_INT32) ui32ExecTime -
+               (IMG_INT32) gsCwq.ui32AvgExecTime +
+               (IMG_INT32) gsCwq.ui32AvgExecTimeRemainder;
 
-               gsCwq.ui32AvgExecTime += i32Div / (IMG_INT32)(gsCwq.ui32TotalExecOps + 1);
-               gsCwq.ui32AvgExecTimeRemainder = i32Div % (IMG_INT32)(gsCwq.ui32TotalExecOps + 1);
+       gsCwq.ui32AvgExecTime += i32Div / (IMG_INT32)(gsCwq.ui32TotalOps + 1);
+       gsCwq.ui32AvgExecTimeRemainder = i32Div % (IMG_INT32)(gsCwq.ui32TotalOps + 1);
+
+       gsCwq.ui32TotalOps++;
 
-               gsCwq.ui32TotalExecOps++;
        }
 
        if (!gsCwq.asStatsExecuted[i32WriteOffset].bKMReq)
        {
                /* This operation queues only UM CacheOp in per-PID process statistics database */
-               PVRSRVStatsUpdateCacheOpStats(gsCwq.asStatsExecuted[i32WriteOffset].uiCacheOp,
-                                               gsCwq.asStatsExecuted[i32WriteOffset].ui32OpSeqNum,
+               PVRSRVStatsUpdateCacheOpStats(
+                                               gsCwq.asStatsExecuted[i32WriteOffset].uiCacheOp,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                                                gsCwq.asStatsExecuted[i32WriteOffset].sDevVAddr,
                                                gsCwq.asStatsExecuted[i32WriteOffset].sDevPAddr,
-                                               gsCwq.asStatsExecuted[i32WriteOffset].eFenceOpType,
 #endif
                                                gsCwq.asStatsExecuted[i32WriteOffset].uiOffset,
                                                gsCwq.asStatsExecuted[i32WriteOffset].uiSize,
-                                               ui64ExecuteTime-ui64EnqueuedTime,
-                                               gsCwq.asStatsExecuted[i32WriteOffset].bUMF,
-                                               gsCwq.asStatsExecuted[i32WriteOffset].bIsFence,
+                                               ui32ExecTime,
+                                               !gsCwq.asStatsExecuted[i32WriteOffset].bKMReq,
                                                psCacheOpWorkItem->pid);
        }
 
@@ -516,40 +346,31 @@ e0:
 
 static int CacheOpStatsExecLogRead(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       IMG_CHAR *pszFlushype;
+       IMG_CHAR *pszFlushType;
        IMG_CHAR *pszCacheOpType;
        IMG_CHAR *pszFlushSource;
        IMG_INT32 i32ReadOffset;
        IMG_INT32 i32WriteOffset;
-       IMG_UINT64 ui64EnqueuedTime;
-       IMG_UINT64 ui64DequeuedTime;
-       IMG_UINT64 ui64ExecuteTime;
+
        IMG_CHAR szBuffer[CACHEOP_MAX_DEBUG_MESSAGE_LEN] = {0};
        PVR_UNREFERENCED_PARAMETER(pvData);
 
        OSLockAcquire(gsCwq.hStatsExecLock);
 
        DIPrintf(psEntry,
-                       "Primary CPU d-cache architecture: LSZ: 0x%d, URBF: %s\n",
+                       "Primary CPU d-cache architecture: LSZ: 0x%x, URBF: %s\n",
                        gsCwq.uiLineSize,
-                       gsCwq.bSupportsUMFlush ? "Yes" : "No"
-               );
+                       gsCwq.bSupportsUMFlush ? "Yes" : "No");
 
        DIPrintf(psEntry,
-                       "Configuration: QSZ: %d, UKT: %d, KDFT: %d, KDF: %s, URBF: %s\n",
-                       CACHEOP_INDICES_MAX,
+                       "Configuration: UKT: %d, URBF: %s\n",
                        gsCwq.pui32InfoPage[CACHEOP_INFO_UMKMTHRESHLD],
-                       gsCwq.pui32InfoPage[CACHEOP_INFO_KMDFTHRESHLD],
-                       gsCwq.eConfig & CACHEOP_CONFIG_KDF  ? "Yes" : "No",
-                       gsCwq.eConfig & CACHEOP_CONFIG_URBF ? "Yes" : "No"
-               );
+                       gsCwq.eConfig & CACHEOP_CONFIG_URBF ? "Yes" : "No");
 
        DIPrintf(psEntry,
-                       "Summary: OP[F][TL] (tot.avg): %d.%d/%d.%d/%d, [KM][UM][A]SYNC: %d.%d/%d/%d, RBF (um/km): %d/%d\n",
-                       gsCwq.ui32TotalExecOps, gsCwq.ui32AvgExecTime, gsCwq.ui32TotalFenceOps, gsCwq.ui32AvgFenceTime, gsCwq.ui32ServerDTL,
-                       gsCwq.ui32ServerSync, gsCwq.ui32ServerSyncVA, gsCwq.ui32ClientSync,     gsCwq.ui32ServerASync,
-                       gsCwq.ui32ClientRBF,   gsCwq.ui32ServerRBF
-               );
+                       "Summary: Total Ops [%d] - Server(using UMVA)/Client [%d(%d)/%d]. Avg execution time [%d]\n",
+                       gsCwq.ui32TotalOps, gsCwq.ui32ServerOps, gsCwq.ui32ServerOpUsedUMVA, gsCwq.ui32ClientOps, gsCwq.ui32AvgExecTime);
+
 
        CacheOpStatsExecLogHeader(szBuffer);
        DIPrintf(psEntry, "%s\n", szBuffer);
@@ -559,158 +380,71 @@ static int CacheOpStatsExecLogRead(OSDI_IMPL_ENTRY *psEntry, void *pvData)
                 i32ReadOffset != i32WriteOffset;
                 i32ReadOffset = DECR_WRAP(i32ReadOffset))
        {
-               if (!gsCwq.asStatsExecuted[i32ReadOffset].ui32OpSeqNum &&
-                       !gsCwq.asStatsExecuted[i32ReadOffset].uiCacheOp)
+               IMG_UINT64 ui64ExecTime =
+                       gsCwq.asStatsExecuted[i32ReadOffset].ui64EndTime -
+                       gsCwq.asStatsExecuted[i32ReadOffset].ui64StartTime;
+
+               IMG_DEVMEM_SIZE_T ui64NumOfPages =
+                       gsCwq.asStatsExecuted[i32ReadOffset].uiSize >> gsCwq.uiPageShift;
+
+
+               if (!gsCwq.asStatsExecuted[i32ReadOffset].uiCacheOp)
                {
                        break;
                }
-
+               if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
                {
-                       /* Convert from nano-seconds to micro-seconds */
-                       IMG_UINT64 ui64ExecuteTimeNs = gsCwq.asStatsExecuted[i32ReadOffset].ui64ExecuteTime;
-                       IMG_UINT64 ui64EnqueuedTimeNs = gsCwq.asStatsExecuted[i32ReadOffset].ui64EnqueuedTime;
-                       IMG_UINT64 ui64DequeuedTimeNs = gsCwq.asStatsExecuted[i32ReadOffset].ui64DequeuedTime;
-
-                       do_div(ui64ExecuteTimeNs, 1000);
-                       do_div(ui64EnqueuedTimeNs, 1000);
-                       do_div(ui64DequeuedTimeNs, 1000);
-
-                       ui64ExecuteTime  = ui64ExecuteTimeNs;
-                       ui64EnqueuedTime = ui64EnqueuedTimeNs;
-                       ui64DequeuedTime = ui64DequeuedTimeNs;
-               }
-
-               if (gsCwq.asStatsExecuted[i32ReadOffset].bIsFence)
-               {
-                       IMG_CHAR *pszMode = "";
-                       IMG_CHAR *pszFenceType = "";
-                       pszCacheOpType = "Fence";
-
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                       switch (gsCwq.asStatsExecuted[i32ReadOffset].eFenceOpType)
-                       {
-                               case RGXFWIF_DM_GP:
-                                       pszFenceType = "  GP ";
-                                       break;
-
-                               case RGXFWIF_DM_TDM:
-                                       pszFenceType = "  TDM ";
-                                       break;
-
-                               case RGXFWIF_DM_GEOM:
-                                       pszFenceType = " GEOM";
-                                       break;
-
-                               case RGXFWIF_DM_3D:
-                                       pszFenceType = "  3D ";
-                                       break;
-
-                               case RGXFWIF_DM_CDM:
-                                       pszFenceType = "  CDM ";
-                                       break;
-
-                               default:
-                                       pszFenceType = "  DM? ";
-                                       CACHEOP_PVR_ASSERT(0);
-                                       break;
-                       }
-#endif
-
-                       DIPrintf(psEntry,
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       CACHEOP_RI_PRINTF,
-#else
-                                                       CACHEOP_PRINTF,
-#endif
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].pid,
-                                                       pszCacheOpType,
-                                                       pszFenceType,
-                                                       pszMode,
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       0ull,
-                                                       0ull,
-#endif
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].uiOffset,
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].uiSize,
-                                                       ui64ExecuteTime - ui64EnqueuedTime,
-                                                       ui64DequeuedTime ? ui64DequeuedTime - ui64EnqueuedTime : 0, /* CacheOp might not have a valid DequeuedTime */
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].ui32OpSeqNum);
+                       pszFlushType = "RBF.Fast";
                }
                else
                {
-                       IMG_DEVMEM_SIZE_T ui64NumOfPages;
+                       pszFlushType = "RBF.Slow";
+               }
 
-                       ui64NumOfPages = gsCwq.asStatsExecuted[i32ReadOffset].uiSize >> gsCwq.uiPageShift;
-                       if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
-                       {
-                               pszFlushype = "RBF.Fast";
-                       }
-                       else
-                       {
-                               pszFlushype = "RBF.Slow";
-                       }
+               pszFlushSource = gsCwq.asStatsExecuted[i32ReadOffset].bKMReq ? " KM" : " UM";
 
-                       if (gsCwq.asStatsExecuted[i32ReadOffset].bUMF)
-                       {
-                               pszFlushSource = " UM";
-                       }
-                       else
-                       {
-                               /*
-                                  - Request originates directly from a KM thread or in KM (KM<), or
-                                  - Request originates from a UM thread and is KM deferred (KM+), or
-                               */
-                               pszFlushSource =
-                                       gsCwq.asStatsExecuted[i32ReadOffset].bKMReq ? " KM<" :
-                                       gsCwq.asStatsExecuted[i32ReadOffset].bDeferred && gsCwq.asStatsExecuted[i32ReadOffset].ui64ExecuteTime ? " KM+" :
-                                       !gsCwq.asStatsExecuted[i32ReadOffset].ui64ExecuteTime ? " KM-" : " KM";
-                       }
-
-                       switch (gsCwq.asStatsExecuted[i32ReadOffset].uiCacheOp)
-                       {
-                               case PVRSRV_CACHE_OP_NONE:
-                                       pszCacheOpType = "None";
-                                       break;
-                               case PVRSRV_CACHE_OP_CLEAN:
-                                       pszCacheOpType = "Clean";
-                                       break;
-                               case PVRSRV_CACHE_OP_INVALIDATE:
-                                       pszCacheOpType = "Invalidate";
-                                       break;
-                               case PVRSRV_CACHE_OP_FLUSH:
-                                       pszCacheOpType = "Flush";
-                                       break;
-                               case PVRSRV_CACHE_OP_TIMELINE:
-                                       pszCacheOpType = "Timeline";
-                                       pszFlushype = "      ";
-                                       break;
-                               default:
-                                       pszCacheOpType = "Unknown";
-                                       gsCwq.asStatsExecuted[i32ReadOffset].ui32OpSeqNum =
-                                                       (IMG_UINT32) gsCwq.asStatsExecuted[i32ReadOffset].uiCacheOp;
-                                       break;
-                       }
+               switch (gsCwq.asStatsExecuted[i32ReadOffset].uiCacheOp)
+               {
+                       case PVRSRV_CACHE_OP_NONE:
+                               pszCacheOpType = "None";
+                               break;
+                       case PVRSRV_CACHE_OP_CLEAN:
+                               pszCacheOpType = "Clean";
+                               break;
+                       case PVRSRV_CACHE_OP_INVALIDATE:
+                               pszCacheOpType = "Invalidate";
+                               break;
+                       case PVRSRV_CACHE_OP_FLUSH:
+                               pszCacheOpType = "Flush";
+                               break;
+                       case PVRSRV_CACHE_OP_TIMELINE:
+                               pszCacheOpType = "Timeline";
+                               pszFlushType = "      ";
+                               break;
+                       default:
+                               pszCacheOpType = "Unknown";
+                               break;
+               }
 
-                       DIPrintf(psEntry,
+               DIPrintf(psEntry,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       CACHEOP_RI_PRINTF,
+                                               CACHEOP_RI_PRINTF,
 #else
-                                                       CACHEOP_PRINTF,
+                                               CACHEOP_PRINTF,
 #endif
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].pid,
-                                                       pszCacheOpType,
-                                                       pszFlushype,
-                                                       pszFlushSource,
+                                               gsCwq.asStatsExecuted[i32ReadOffset].ui32DeviceID,
+                                               gsCwq.asStatsExecuted[i32ReadOffset].pid,
+                                               pszCacheOpType,
+                                               pszFlushType,
+                                               pszFlushSource,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].sDevVAddr.uiAddr,
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].sDevPAddr.uiAddr,
+                                               gsCwq.asStatsExecuted[i32ReadOffset].sDevVAddr.uiAddr,
+                                               gsCwq.asStatsExecuted[i32ReadOffset].sDevPAddr.uiAddr,
 #endif
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].uiOffset,
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].uiSize,
-                                                       ui64ExecuteTime - ui64EnqueuedTime,
-                                                       ui64DequeuedTime ? ui64DequeuedTime - ui64EnqueuedTime : 0, /* CacheOp might not have a valid DequeuedTime */
-                                                       gsCwq.asStatsExecuted[i32ReadOffset].ui32OpSeqNum);
-               }
+                                               gsCwq.asStatsExecuted[i32ReadOffset].uiOffset,
+                                               gsCwq.asStatsExecuted[i32ReadOffset].uiSize,
+                                               ui64ExecTime);
+
        }
 
        OSLockRelease(gsCwq.hStatsExecLock);
@@ -722,20 +456,15 @@ static int CacheOpStatsExecLogRead(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 static INLINE void CacheOpStatsReset(void)
 {
 #if defined(CACHEOP_DEBUG)
-       gsCwq.ui32TotalExecOps                  = 0;
-       gsCwq.ui32TotalFenceOps                 = 0;
-       gsCwq.ui32AvgExecTime                   = 0;
-       gsCwq.ui32AvgExecTimeRemainder  = 0;
-       gsCwq.ui32AvgFenceTime                  = 0;
-       gsCwq.ui32AvgFenceTimeRemainder = 0;
-       gsCwq.ui32ClientRBF                             = 0;
-       gsCwq.ui32ClientSync                    = 0;
-       gsCwq.ui32ServerRBF                             = 0;
-       gsCwq.ui32ServerASync                   = 0;
-       gsCwq.ui32ServerSyncVA                  = 0;
-       gsCwq.ui32ServerSync                    = 0;
-       gsCwq.ui32ServerDTL                             = 0;
-       gsCwq.i32StatsExecWriteIdx              = 0;
+       gsCwq.ui32ServerOps = 0;
+       gsCwq.ui32ClientOps = 0;
+       gsCwq.ui32TotalOps = 0;
+       gsCwq.ui32ServerOpUsedUMVA = 0;
+       gsCwq.ui32AvgExecTime = 0;
+       gsCwq.ui32AvgExecTimeRemainder = 0;
+
+       gsCwq.i32StatsExecWriteIdx = 0;
+
        OSCachedMemSet(gsCwq.asStatsExecuted, 0, sizeof(gsCwq.asStatsExecuted));
 #endif
 }
@@ -830,11 +559,10 @@ static void CacheOpConfigUpdate(IMG_UINT32 ui32Config)
 static int CacheOpConfigRead(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
        PVR_UNREFERENCED_PARAMETER(pvData);
-       DIPrintf(psEntry,
-                       "KDF: %s, URBF: %s\n",
-                       gsCwq.eConfig & CACHEOP_CONFIG_KDF  ? "Yes" : "No",
-                       gsCwq.eConfig & CACHEOP_CONFIG_URBF ? "Yes" : "No"
-               );
+
+       DIPrintf(psEntry, "URBF: %s\n",
+               gsCwq.eConfig & CACHEOP_CONFIG_URBF ? "Yes" : "No");
+
        return 0;
 }
 
@@ -906,68 +634,6 @@ static INLINE PVRSRV_ERROR CacheOpConfigSet(const PVRSRV_DEVICE_NODE *psDevNode,
        return PVRSRV_OK;
 }
 
-static INLINE IMG_UINT32 CacheOpGetNextCommonSeqNum(void)
-{
-       IMG_UINT32 ui32SeqNum = OSAtomicIncrement(&gsCwq.hCommonSeqNum);
-       if (! ui32SeqNum)
-       {
-               ui32SeqNum = OSAtomicIncrement(&gsCwq.hCommonSeqNum);
-       }
-       return ui32SeqNum;
-}
-
-static INLINE IMG_BOOL CacheOpFenceCheck(IMG_UINT32 ui32CompletedSeqNum,
-                                                                                IMG_UINT32 ui32FenceSeqNum)
-{
-       IMG_UINT32 ui32RebasedCompletedNum;
-       IMG_UINT32 ui32RebasedFenceNum;
-       IMG_UINT32 ui32Rebase;
-
-       if (ui32FenceSeqNum == 0)
-       {
-               return IMG_TRUE;
-       }
-
-       /*
-          The problem statement is how to compare two values on
-          a numerical sequentially incrementing timeline in the
-          presence of wrap around arithmetic semantics using a
-          single ui32 counter & atomic (increment) operations.
-
-          The rationale for the solution here is to rebase the
-          incoming values to the sequence midpoint and perform
-          comparisons there; this allows us to handle overflow
-          or underflow wrap-round using only a single integer.
-
-          NOTE: Here we assume that the absolute value of the
-          difference between the two incoming values in _not_
-          greater than CACHEOP_SEQ_MIDPOINT. This assumption
-          holds as it implies that it is very _unlikely_ that 2
-          billion CacheOp requests could have been made between
-          a single client's CacheOp request & the corresponding
-          fence check. This code sequence is hopefully a _more_
-          hand optimised (branchless) version of this:
-
-                  x = ui32CompletedOpSeqNum
-                  y = ui32FenceOpSeqNum
-
-                  if (|x - y| < CACHEOP_SEQ_MIDPOINT)
-                          return (x - y) >= 0 ? true : false
-                  else
-                          return (y - x) >= 0 ? true : false
-        */
-       ui32Rebase = CACHEOP_SEQ_MIDPOINT - ui32CompletedSeqNum;
-
-       /* ui32Rebase could be either positive/negative, in
-          any case we still perform operation using unsigned
-          semantics as 2's complement notation always means
-          we end up with the correct result */
-       ui32RebasedCompletedNum = ui32Rebase + ui32CompletedSeqNum;
-       ui32RebasedFenceNum = ui32Rebase + ui32FenceSeqNum;
-
-       return (ui32RebasedCompletedNum >= ui32RebasedFenceNum);
-}
-
 static INLINE PVRSRV_ERROR CacheOpTimelineBind(PVRSRV_DEVICE_NODE *psDevNode,
                                                                                           CACHEOP_WORK_ITEM *psCacheOpWorkItem,
                                                                                           PVRSRV_TIMELINE iTimeline)
@@ -1099,10 +765,6 @@ static INLINE void CacheOpExecRangeBased(PVRSRV_DEVICE_NODE *psDevNode,
                        break;
        }
 
-#if defined(CACHEOP_DEBUG)
-       /* Tracks the number of kernel-mode cacheline maintenance instructions */
-       gsCwq.ui32ServerRBF += (uiRelFlushSize & ((IMG_DEVMEM_SIZE_T)~(gsCwq.uiLineSize - 1))) >> gsCwq.uiLineShift;
-#endif
 }
 
 static INLINE void CacheOpExecRangeBasedVA(PVRSRV_DEVICE_NODE *psDevNode,
@@ -1138,10 +800,6 @@ static INLINE void CacheOpExecRangeBasedVA(PVRSRV_DEVICE_NODE *psDevNode,
                        break;
        }
 
-#if defined(CACHEOP_DEBUG)
-       /* Tracks the number of kernel-mode cacheline maintenance instructions */
-       gsCwq.ui32ServerRBF += (uiSize & ((IMG_DEVMEM_SIZE_T)~(gsCwq.uiLineSize - 1))) >> gsCwq.uiLineShift;
-#endif
 }
 
 static INLINE PVRSRV_ERROR CacheOpValidateUMVA(PMR *psPMR,
@@ -1274,7 +932,7 @@ static PVRSRV_ERROR CacheOpPMRExec (PMR *psPMR,
                                PVR_LOG_IF_ERROR(eError, "PMRUnlockSysPhysAddresses");
                        }
 #if defined(CACHEOP_DEBUG)
-                       gsCwq.ui32ServerSyncVA += 1;
+                       gsCwq.ui32ServerOpUsedUMVA += 1;
 #endif
                        return PVRSRV_OK;
                }
@@ -1283,7 +941,7 @@ static PVRSRV_ERROR CacheOpPMRExec (PMR *psPMR,
                        /* Round down the incoming VA (if any) down to the nearest page aligned VA */
                        pvAddress = (void*)((uintptr_t)pvAddress & ~((uintptr_t)gsCwq.uiPageSize-1));
 #if defined(CACHEOP_DEBUG)
-                       gsCwq.ui32ServerSyncVA += 1;
+                       gsCwq.ui32ServerOpUsedUMVA += 1;
 #endif
                }
        }
@@ -1583,213 +1241,18 @@ e0:
        return eError;
 }
 
-static PVRSRV_ERROR CacheOpQListExecRangeBased(void)
-{
-       IMG_UINT32 ui32NumOfEntries;
-       PVRSRV_ERROR eError = PVRSRV_OK;
-       CACHEOP_WORK_ITEM *psCacheOpWorkItem = NULL;
-
-       /* Take a snapshot of the current count of deferred entries at this junction */
-       ui32NumOfEntries = CacheOpIdxSpan(&gsCwq.hWriteCounter, &gsCwq.hReadCounter);
-       if (! ui32NumOfEntries)
-       {
-               return PVRSRV_OK;
-       }
-#if defined(CACHEOP_DEBUG)
-       CACHEOP_PVR_ASSERT(ui32NumOfEntries < CACHEOP_INDICES_MAX);
-#endif
-
-       while (ui32NumOfEntries)
-       {
-               if (! OSAtomicRead(&gsCwq.hReadCounter))
-               {
-                       /* Normally, the read-counter will trail the write counter until the write
-                          counter wraps-round to zero. Under this condition we (re)calculate as the
-                          read-counter too is wrapping around at this point */
-                       ui32NumOfEntries = CacheOpIdxSpan(&gsCwq.hWriteCounter, &gsCwq.hReadCounter);
-               }
-#if defined(CACHEOP_DEBUG)
-               /* Something's gone horribly wrong if these 2 counters are identical at this point */
-               CACHEOP_PVR_ASSERT(OSAtomicRead(&gsCwq.hWriteCounter) != OSAtomicRead(&gsCwq.hReadCounter));
-#endif
-
-               /* Select the next pending deferred work-item for RBF cache maintenance */
-               psCacheOpWorkItem = &gsCwq.asWorkItems[CacheOpIdxNext(&gsCwq.hReadCounter)];
-
-#if defined(CACHEOP_DEBUG)
-               /* The time waiting in the queue to be serviced */
-               psCacheOpWorkItem->ui64DequeuedTime = OSClockns64();
-#endif
-
-               eError = CacheOpPMRExec(psCacheOpWorkItem->psPMR,
-                                                               NULL, /* No UM virtual address */
-                                                               psCacheOpWorkItem->uiOffset,
-                                                               psCacheOpWorkItem->uiSize,
-                                                               psCacheOpWorkItem->uiCacheOp,
-                                                               IMG_TRUE /* PMR is pre-validated */
-                                                               );
-               if (eError != PVRSRV_OK)
-               {
-#if defined(CACHEOP_DEBUG)
-#define PID_FMTSPEC " PID:%u"
-#define CACHE_OP_WORK_PID psCacheOpWorkItem->pid
-#else
-#define PID_FMTSPEC "%s"
-#define CACHE_OP_WORK_PID ""
-#endif
-
-                       PVR_LOG(("Deferred CacheOpPMRExec failed:"
-                                        PID_FMTSPEC
-                                        " PMR:%p"
-                                        " Offset:%" IMG_UINT64_FMTSPECX
-                                        " Size:%" IMG_UINT64_FMTSPECX
-                                        " CacheOp:%d,"
-                                        " error: %d",
-                                       CACHE_OP_WORK_PID,
-                                       psCacheOpWorkItem->psPMR,
-                                       psCacheOpWorkItem->uiOffset,
-                                       psCacheOpWorkItem->uiSize,
-                                       psCacheOpWorkItem->uiCacheOp,
-                                       eError));
-
-#undef PID_FMTSPEC
-#undef CACHE_OP_WORK_PID
-               }
-
-#if defined(CACHEOP_DEBUG)
-               psCacheOpWorkItem->ui64ExecuteTime = OSClockns64();
-               CacheOpStatsExecLogWrite(psCacheOpWorkItem);
-#endif
-
-               /* The currently executed CacheOp item updates gsCwq.hCompletedSeqNum.
-                  NOTE: This CacheOp item might be a discard item, if so its seqNum
-                  still updates the gsCwq.hCompletedSeqNum */
-               OSAtomicWrite(&gsCwq.hCompletedSeqNum, psCacheOpWorkItem->ui32OpSeqNum);
-
-               /* If CacheOp is timeline(d), notify timeline waiters */
-               eError = CacheOpTimelineExec(psCacheOpWorkItem);
-               PVR_LOG_IF_ERROR(eError, "CacheOpTimelineExec");
-
-               eError = PMRUnlockSysPhysAddresses(psCacheOpWorkItem->psPMR);
-               PVR_LOG_IF_ERROR(eError, "PMRUnlockSysPhysAddresses");
-
-               (void) CacheOpIdxIncrement(&gsCwq.hReadCounter);
-               ui32NumOfEntries = ui32NumOfEntries - 1;
-       }
-
-       return eError;
-}
-
-static INLINE PVRSRV_ERROR CacheOpQListExec(void)
-{
-       PVRSRV_ERROR eError;
-
-       eError = CacheOpQListExecRangeBased();
-       PVR_LOG_IF_ERROR(eError, "CacheOpQListExecRangeBased");
-
-       /* Signal any waiting threads blocked on CacheOp fence checks update
-          completed sequence number to last queue work item */
-       eError = OSEventObjectSignal(gsCwq.hClientWakeUpEvtObj);
-       PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
-
-       return eError;
-}
-
-static void CacheOpThread(void *pvData)
-{
-       PVRSRV_DATA *psPVRSRVData = pvData;
-       IMG_HANDLE hOSEvent;
-       PVRSRV_ERROR eError;
-
-       /* Open CacheOp thread event object, abort driver if event object open fails */
-       eError = OSEventObjectOpen(gsCwq.hThreadWakeUpEvtObj, &hOSEvent);
-       PVR_LOG_IF_ERROR(eError, "OSEventObjectOpen");
-
-       /* While driver is in good state & loaded, perform pending cache maintenance */
-       while ((psPVRSRVData->eServicesState == PVRSRV_SERVICES_STATE_OK) && gsCwq.bInit)
-       {
-               /* Sleep-wait here until when signalled for new queued CacheOp work items;
-                  when woken-up, drain deferred queue completely before next event-wait */
-               (void) OSEventObjectWaitKernel(hOSEvent, CACHEOP_THREAD_WAIT_TIMEOUT);
-               while (CacheOpIdxSpan(&gsCwq.hWriteCounter, &gsCwq.hReadCounter))
-               {
-                       eError = CacheOpQListExec();
-                       PVR_LOG_IF_ERROR(eError, "CacheOpQListExec");
-               }
-       }
-
-       eError = CacheOpQListExec();
-       PVR_LOG_IF_ERROR(eError, "CacheOpQListExec");
-
-       eError = OSEventObjectClose(hOSEvent);
-       PVR_LOG_IF_ERROR(eError, "OSEventObjectClose");
-}
-
 static PVRSRV_ERROR CacheOpBatchExecTimeline(PVRSRV_DEVICE_NODE *psDevNode,
-                                                                                        PVRSRV_TIMELINE iTimeline,
-                                                                                        IMG_UINT32 ui32CurrentFenceSeqNum,
-                                                                                        IMG_UINT32 *pui32NextFenceSeqNum)
+                                                                                        PVRSRV_TIMELINE iTimeline)
 {
        PVRSRV_ERROR eError;
-       IMG_UINT32 ui32NextIdx;
        CACHEOP_WORK_ITEM sCacheOpWorkItem = {NULL};
-       CACHEOP_WORK_ITEM *psCacheOpWorkItem = NULL;
 
        eError = CacheOpTimelineBind(psDevNode, &sCacheOpWorkItem, iTimeline);
        PVR_LOG_RETURN_IF_ERROR(eError, "CacheOpTimelineBind");
 
-       OSLockAcquire(gsCwq.hDeferredLock);
-
-       /*
-          Check if there is any deferred queueing space available and that nothing is
-          currently queued. This second check is required as Android where timelines
-          are used sets a timeline signalling deadline of 1000ms to signal timelines
-          else complains. So seeing we cannot be sure how long the CacheOp presently
-          in the queue would take we should not send this timeline down the queue as
-          well.
-        */
-       ui32NextIdx = CacheOpIdxNext(&gsCwq.hWriteCounter);
-       if (!CacheOpIdxSpan(&gsCwq.hWriteCounter, &gsCwq.hReadCounter) &&
-               CacheOpIdxRead(&gsCwq.hReadCounter) != ui32NextIdx)
-       {
-               psCacheOpWorkItem = &gsCwq.asWorkItems[ui32NextIdx];
-
-               psCacheOpWorkItem->sSWTimelineObj = sCacheOpWorkItem.sSWTimelineObj;
-               psCacheOpWorkItem->iTimeline = sCacheOpWorkItem.iTimeline;
-               psCacheOpWorkItem->psDevNode = sCacheOpWorkItem.psDevNode;
-               psCacheOpWorkItem->ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
-               psCacheOpWorkItem->uiCacheOp = PVRSRV_CACHE_OP_TIMELINE;
-               psCacheOpWorkItem->uiOffset = (IMG_DEVMEM_OFFSET_T)0;
-               psCacheOpWorkItem->uiSize = (IMG_DEVMEM_SIZE_T)0;
-               /* Defer timeline using information page PMR */
-               psCacheOpWorkItem->psPMR = gsCwq.psInfoPagePMR;
-
-               eError = PMRLockSysPhysAddresses(psCacheOpWorkItem->psPMR);
-               PVR_LOG_GOTO_IF_ERROR(eError, "PMRLockSysPhysAddresses", e0);
+       eError = CacheOpTimelineExec(&sCacheOpWorkItem);
+       PVR_LOG_IF_ERROR(eError, "CacheOpTimelineExec");
 
-#if defined(CACHEOP_DEBUG)
-               psCacheOpWorkItem->pid = OSGetCurrentClientProcessIDKM();
-               psCacheOpWorkItem->ui64EnqueuedTime = OSClockns64();
-               gsCwq.ui32ServerASync += 1;
-               gsCwq.ui32ServerDTL += 1;
-#endif
-
-               /* Mark index ready for cache maintenance */
-               (void) CacheOpIdxIncrement(&gsCwq.hWriteCounter);
-
-               eError = OSEventObjectSignal(gsCwq.hThreadWakeUpEvtObj);
-               PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
-       }
-       else
-       {
-               /* signal timeline.
-                * All ops with timelines and partial batches were executed synchronously. */
-               eError = CacheOpTimelineExec(&sCacheOpWorkItem);
-               PVR_LOG_IF_ERROR(eError, "CacheOpTimelineExec");
-       }
-
-e0:
-       OSLockRelease(gsCwq.hDeferredLock);
        return eError;
 }
 
@@ -1800,21 +1263,14 @@ static PVRSRV_ERROR CacheOpBatchExecRangeBased(PVRSRV_DEVICE_NODE *psDevNode,
                                                                                        IMG_DEVMEM_SIZE_T *puiSize,
                                                                                        PVRSRV_CACHE_OP *puiCacheOp,
                                                                                        IMG_UINT32 ui32NumCacheOps,
-                                                                                       PVRSRV_TIMELINE uiTimeline,
-                                                                                       IMG_UINT32 uiCurrentFenceSeqNum,
-                                                                                       IMG_UINT32 *pui32NextFenceSeqNum)
+                                                                                       PVRSRV_TIMELINE uiTimeline)
 {
        IMG_UINT32 ui32Idx;
-       IMG_UINT32 ui32NextIdx;
        IMG_BOOL bBatchHasTimeline;
-       IMG_BOOL bCacheOpConfigKDF;
-       IMG_DEVMEM_SIZE_T uiLogicalSize;
-       IMG_BOOL bBatchForceSynchronous = IMG_FALSE;
        PVRSRV_ERROR eError = PVRSRV_OK;
-       CACHEOP_WORK_ITEM *psCacheOpWorkItem = NULL;
+
 #if defined(CACHEOP_DEBUG)
        CACHEOP_WORK_ITEM sCacheOpWorkItem = {0};
-       IMG_UINT32 ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
        sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
 #endif
 
@@ -1822,169 +1278,41 @@ static PVRSRV_ERROR CacheOpBatchExecRangeBased(PVRSRV_DEVICE_NODE *psDevNode,
        bBatchHasTimeline = puiCacheOp[ui32NumCacheOps-1] & PVRSRV_CACHE_OP_TIMELINE;
        puiCacheOp[ui32NumCacheOps-1] &= ~(PVRSRV_CACHE_OP_TIMELINE);
 
-       /* Check if batch is forcing synchronous execution */
-       bBatchForceSynchronous = puiCacheOp[ui32NumCacheOps-1] & PVRSRV_CACHE_OP_FORCE_SYNCHRONOUS;
-       puiCacheOp[ui32NumCacheOps-1] &= ~(PVRSRV_CACHE_OP_FORCE_SYNCHRONOUS);
-
-       /* Check if config. supports kernel deferring of cacheops */
-       bCacheOpConfigKDF = CacheOpConfigSupports(CACHEOP_CONFIG_KDF);
-
-       /*
-          Client expects the next fence seqNum to be zero unless the server has deferred
-          at least one CacheOp in the submitted queue in which case the server informs
-          the client of the last CacheOp seqNum deferred in this batch.
-       */
-       for (*pui32NextFenceSeqNum = 0, ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
+       for (ui32Idx = 0; ui32Idx < ui32NumCacheOps; ui32Idx++)
        {
                /* Fail UM request, don't silently ignore */
                PVR_GOTO_IF_INVALID_PARAM(puiSize[ui32Idx], eError, e0);
 
-               if (bCacheOpConfigKDF)
-               {
-                       /* Check if there is deferred queueing space available */
-                       ui32NextIdx = CacheOpIdxNext(&gsCwq.hWriteCounter);
-                       if (ui32NextIdx != CacheOpIdxRead(&gsCwq.hReadCounter))
-                       {
-                               psCacheOpWorkItem = &gsCwq.asWorkItems[ui32NextIdx];
-                       }
-               }
-
-               /*
-                  Normally, we would like to defer client CacheOp(s) but we may not always be in a
-                  position or is necessary to do so based on the following reasons:
-                  0 - There is currently no queueing space left to enqueue this CacheOp, this might
-                      imply the system is queueing more requests than can be consumed by the CacheOp
-                      thread in time.
-                  1 - Batch has timeline, action this now due to Android timeline signaling deadlines.
-                  2 - Batch is forced synchronous. Necessary on Android for batches scheduled in the
-                      middle of add operation. Those cannot have timelines that client plans to add
-                          during actual batch execution and thus make synchronization on Android tricky.
-                  3 - Configuration does not support deferring of cache maintenance operations so we
-                      execute the batch synchronously/immediately.
-                  4 - CacheOp has an INVALIDATE, as this is used to transfer device memory buffer
-                      ownership back to the processor, we cannot defer it so action it immediately.
-                  5 - CacheOp size too small (single OS page size) to warrant overhead of deferment,
-                  6 - CacheOp size OK for deferment, but a client virtual address is supplied so we
-                      might has well just take advantage of said VA & flush immediately in UM context.
-                  7 - Prevent DoS attack if a malicious client queues something very large, say 1GiB.
-                      Here we upper bound this threshold to PVR_DIRTY_BYTES_FLUSH_THRESHOLD.
-               */
-               if (!psCacheOpWorkItem  ||
-                       bBatchHasTimeline   ||
-                       bBatchForceSynchronous ||
-                       !bCacheOpConfigKDF  ||
-                       puiCacheOp[ui32Idx] & PVRSRV_CACHE_OP_INVALIDATE ||
-                       (puiSize[ui32Idx] <= (IMG_DEVMEM_SIZE_T)gsCwq.uiPageSize) ||
-                       (pvAddress[ui32Idx] && puiSize[ui32Idx] < (IMG_DEVMEM_SIZE_T)gsCwq.pui32InfoPage[CACHEOP_INFO_KMDFTHRESHLD]) ||
-                       (puiSize[ui32Idx] >= (IMG_DEVMEM_SIZE_T)(gsCwq.pui32InfoPage[CACHEOP_INFO_KMDFTHRESHLD] << 2)))
-               {
-                       /* When the CacheOp thread not keeping up, trash d-cache */
 #if defined(CACHEOP_DEBUG)
-                       sCacheOpWorkItem.ui64EnqueuedTime = OSClockns64();
-                       gsCwq.ui32ServerSync += 1;
+               sCacheOpWorkItem.ui64StartTime = OSClockus64();
 #endif
-                       psCacheOpWorkItem = NULL;
 
-                       eError = CacheOpPMRExec(ppsPMR[ui32Idx],
-                                                                       pvAddress[ui32Idx],
-                                                                       puiOffset[ui32Idx],
-                                                                       puiSize[ui32Idx],
-                                                                       puiCacheOp[ui32Idx],
-                                                                       IMG_FALSE);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "CacheOpExecPMR", e0);
+               eError = CacheOpPMRExec(ppsPMR[ui32Idx],
+                                                               pvAddress[ui32Idx],
+                                                               puiOffset[ui32Idx],
+                                                               puiSize[ui32Idx],
+                                                               puiCacheOp[ui32Idx],
+                                                               IMG_FALSE);
+               PVR_LOG_GOTO_IF_ERROR(eError, "CacheOpExecPMR", e0);
 
 #if defined(CACHEOP_DEBUG)
-                       sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
-                       sCacheOpWorkItem.ui32OpSeqNum = ui32OpSeqNum;
-                       sCacheOpWorkItem.psPMR = ppsPMR[ui32Idx];
-                       sCacheOpWorkItem.uiSize = puiSize[ui32Idx];
-                       sCacheOpWorkItem.uiOffset = puiOffset[ui32Idx];
-                       sCacheOpWorkItem.uiCacheOp = puiCacheOp[ui32Idx];
-                       CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
-#endif
-
-                       continue;
-               }
-
-               /* Need to validate request parameters here before enqueing */
-               eError = PMR_LogicalSize(ppsPMR[ui32Idx], &uiLogicalSize);
-               PVR_LOG_GOTO_IF_ERROR(eError, "PMR_LogicalSize", e0);
-               eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-               PVR_LOG_GOTO_IF_FALSE(((puiOffset[ui32Idx]+puiSize[ui32Idx]) <= uiLogicalSize), CACHEOP_DEVMEM_OOR_ERROR_STRING, e0);
-               eError = PVRSRV_OK;
-
-               /* For safety, take reference here in user context */
-               eError = PMRLockSysPhysAddresses(ppsPMR[ui32Idx]);
-               PVR_LOG_GOTO_IF_ERROR(eError, "PMRLockSysPhysAddresses", e0);
-
-               OSLockAcquire(gsCwq.hDeferredLock);
-               /* Select next item off the queue to defer with */
-               ui32NextIdx = CacheOpIdxNext(&gsCwq.hWriteCounter);
-               if (ui32NextIdx != CacheOpIdxRead(&gsCwq.hReadCounter))
-               {
-                       psCacheOpWorkItem = &gsCwq.asWorkItems[ui32NextIdx];
-               }
-               else
-               {
-                       /* Retry, disable KDF for this batch */
-                       OSLockRelease(gsCwq.hDeferredLock);
-                       bCacheOpConfigKDF = IMG_FALSE;
-                       psCacheOpWorkItem = NULL;
-                       eError = PMRUnlockSysPhysAddresses(ppsPMR[ui32Idx]);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "PMRUnlockSysPhysAddresses", e0);
-                       ui32Idx = ui32Idx - 1;
-                       continue;
-               }
+               sCacheOpWorkItem.ui64EndTime = OSClockus64();
 
-               psCacheOpWorkItem->psPMR = ppsPMR[ui32Idx];
-               psCacheOpWorkItem->uiCacheOp = puiCacheOp[ui32Idx];
-               psCacheOpWorkItem->uiOffset = puiOffset[ui32Idx];
-               psCacheOpWorkItem->uiSize = puiSize[ui32Idx];
-               
-               /* Timeline need to be looked-up (i.e. bind) in the user context
-                  before deferring into the CacheOp thread kernel context */
-               eError = CacheOpTimelineBind(psDevNode, psCacheOpWorkItem, PVRSRV_NO_TIMELINE);
-               PVR_LOG_GOTO_IF_ERROR(eError, "CacheOpTimelineBind", e1);
-
-               /* Prepare & enqueue next deferred work item for CacheOp thread */
-               psCacheOpWorkItem->ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
-               *pui32NextFenceSeqNum = psCacheOpWorkItem->ui32OpSeqNum;
+               sCacheOpWorkItem.psDevNode = psDevNode;
+               sCacheOpWorkItem.psPMR = ppsPMR[ui32Idx];
+               sCacheOpWorkItem.uiSize = puiSize[ui32Idx];
+               sCacheOpWorkItem.uiOffset = puiOffset[ui32Idx];
+               sCacheOpWorkItem.uiCacheOp = puiCacheOp[ui32Idx];
+               CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
 
-#if defined(CACHEOP_DEBUG)
-               psCacheOpWorkItem->ui64EnqueuedTime = OSClockns64();
-               psCacheOpWorkItem->pid = sCacheOpWorkItem.pid;
-               psCacheOpWorkItem->bDeferred = IMG_TRUE;
-               psCacheOpWorkItem->bKMReq = IMG_FALSE;
-               psCacheOpWorkItem->bUMF = IMG_FALSE;
-               gsCwq.ui32ServerASync += 1;
+               gsCwq.ui32ServerOps += 1;
 #endif
-
-               /* Increment deferred size & mark index ready for cache maintenance */
-               (void) CacheOpIdxIncrement(&gsCwq.hWriteCounter);
-
-               OSLockRelease(gsCwq.hDeferredLock);
-               psCacheOpWorkItem = NULL;
-       }
-
-       /* Signal the CacheOp thread to ensure these items get processed */
-       eError = OSEventObjectSignal(gsCwq.hThreadWakeUpEvtObj);
-       PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
-
-e1:
-       if (psCacheOpWorkItem)
-       {
-               eError = PMRUnlockSysPhysAddresses(psCacheOpWorkItem->psPMR);
-               PVR_LOG_IF_ERROR(eError, "PMRUnlockSysPhysAddresses");
        }
-       OSLockRelease(gsCwq.hDeferredLock);
 
 e0:
        if (bBatchHasTimeline)
        {
-               PVRSRV_ERROR eError2;
-               eError2 = CacheOpBatchExecTimeline(psDevNode, uiTimeline,
-                                                                                  uiCurrentFenceSeqNum, pui32NextFenceSeqNum);
-               eError = (eError2 == PVRSRV_ERROR_RETRY) ? eError2 : eError;
+               eError = CacheOpBatchExecTimeline(psDevNode, uiTimeline);
        }
 
        return eError;
@@ -1999,7 +1327,7 @@ PVRSRV_ERROR CacheOpExec (PPVRSRV_DEVICE_NODE psDevNode,
                                                  PVRSRV_CACHE_OP uiCacheOp)
 {
 #if defined(CACHEOP_DEBUG)
-       IMG_UINT64 ui64EnqueueTime = OSClockns64();
+       IMG_UINT64 ui64StartTime = OSClockus64();
 #endif
 
        switch (uiCacheOp)
@@ -2024,19 +1352,17 @@ PVRSRV_ERROR CacheOpExec (PPVRSRV_DEVICE_NODE psDevNode,
        {
                CACHEOP_WORK_ITEM sCacheOpWorkItem = {0};
 
-               gsCwq.ui32ServerSync += 1;
-               gsCwq.ui32ServerRBF +=
-                               ((sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr) & ((IMG_DEVMEM_SIZE_T)~(gsCwq.uiLineSize - 1))) >> gsCwq.uiLineShift;
+               gsCwq.ui32ServerOps += 1;
 
                sCacheOpWorkItem.uiOffset = 0;
                sCacheOpWorkItem.bKMReq = IMG_TRUE;
                sCacheOpWorkItem.uiCacheOp = uiCacheOp;
                /* Use information page PMR for logging KM request */
                sCacheOpWorkItem.psPMR = gsCwq.psInfoPagePMR;
-               sCacheOpWorkItem.ui64EnqueuedTime = ui64EnqueueTime;
-               sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
+               sCacheOpWorkItem.psDevNode = psDevNode;
+               sCacheOpWorkItem.ui64StartTime = ui64StartTime;
+               sCacheOpWorkItem.ui64EndTime = OSClockus64();
                sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
-               sCacheOpWorkItem.ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
                sCacheOpWorkItem.uiSize = (sCPUPhysEnd.uiAddr - sCPUPhysStart.uiAddr);
 
                CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
@@ -2056,14 +1382,8 @@ PVRSRV_ERROR CacheOpValExec(PMR *psPMR,
        IMG_CPU_VIRTADDR pvAddress = (IMG_CPU_VIRTADDR)(uintptr_t)uiAddress;
 #if defined(CACHEOP_DEBUG)
        CACHEOP_WORK_ITEM sCacheOpWorkItem = {0};
-       gsCwq.ui32ServerSync += 1;
-       sCacheOpWorkItem.psPMR = psPMR;
-       sCacheOpWorkItem.uiSize = uiSize;
-       sCacheOpWorkItem.uiOffset = uiOffset;
-       sCacheOpWorkItem.uiCacheOp = uiCacheOp;
-       sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
-       sCacheOpWorkItem.ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
-       sCacheOpWorkItem.ui64EnqueuedTime = OSClockns64();
+
+       sCacheOpWorkItem.ui64StartTime = OSClockus64();
 #endif
 
        eError = CacheOpPMRExec(psPMR,
@@ -2075,8 +1395,17 @@ PVRSRV_ERROR CacheOpValExec(PMR *psPMR,
        PVR_LOG_GOTO_IF_ERROR(eError, "CacheOpPMRExec", e0);
 
 #if defined(CACHEOP_DEBUG)
-       sCacheOpWorkItem.ui64ExecuteTime = OSClockns64();
+       sCacheOpWorkItem.ui64EndTime = OSClockus64();
+
+       sCacheOpWorkItem.psDevNode = PMR_DeviceNode(psPMR);
+       sCacheOpWorkItem.psPMR = psPMR;
+       sCacheOpWorkItem.uiSize = uiSize;
+       sCacheOpWorkItem.uiOffset = uiOffset;
+       sCacheOpWorkItem.uiCacheOp = uiCacheOp;
+       sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
        CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
+
+       gsCwq.ui32ServerOps += 1;
 #endif
 
 e0:
@@ -2091,9 +1420,7 @@ PVRSRV_ERROR CacheOpQueue (CONNECTION_DATA *psConnection,
                                                   IMG_DEVMEM_OFFSET_T *puiOffset,
                                                   IMG_DEVMEM_SIZE_T *puiSize,
                                                   PVRSRV_CACHE_OP *puiCacheOp,
-                                                  IMG_UINT32 ui32OpTimeline,
-                                                  IMG_UINT32 uiCurrentFenceSeqNum,
-                                                  IMG_UINT32 *pui32NextFenceSeqNum)
+                                                  IMG_UINT32 ui32OpTimeline)
 {
        PVRSRV_ERROR eError;
        PVRSRV_TIMELINE uiTimeline = (PVRSRV_TIMELINE)ui32OpTimeline;
@@ -2113,7 +1440,7 @@ PVRSRV_ERROR CacheOpQueue (CONNECTION_DATA *psConnection,
        /* Ensure any single timeline CacheOp request is processed immediately */
        else if (ui32NumCacheOps == 1 && puiCacheOp[0] == PVRSRV_CACHE_OP_TIMELINE)
        {
-               eError = CacheOpBatchExecTimeline(psDevNode, uiTimeline, uiCurrentFenceSeqNum, pui32NextFenceSeqNum);
+               eError = CacheOpBatchExecTimeline(psDevNode, uiTimeline);
        }
        /* This is the default entry for all client requests */
        else
@@ -2132,162 +1459,35 @@ PVRSRV_ERROR CacheOpQueue (CONNECTION_DATA *psConnection,
                                                                           puiSize,
                                                                           puiCacheOp,
                                                                           ui32NumCacheOps,
-                                                                          uiTimeline,
-                                                                          uiCurrentFenceSeqNum,
-                                                                          pui32NextFenceSeqNum);
+                                                                          uiTimeline);
        }
 
        return eError;
 }
 
-PVRSRV_ERROR CacheOpFence (RGXFWIF_DM eFenceOpType, IMG_UINT32 ui32FenceOpSeqNum)
-{
-       IMG_HANDLE hOSEvent;
-       PVRSRV_ERROR eError2;
-       IMG_UINT32 ui32RetryAbort;
-       IMG_UINT32 ui32CompletedOpSeqNum;
-       PVRSRV_ERROR eError = PVRSRV_OK;
-#if defined(CACHEOP_DEBUG)
-       IMG_UINT64 uiTimeNow;
-       CACHEOP_WORK_ITEM sCacheOpWorkItem = {0};
-       sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
-       sCacheOpWorkItem.ui32OpSeqNum = ui32FenceOpSeqNum;
-       sCacheOpWorkItem.ui64EnqueuedTime = OSClockns64();
-       uiTimeNow = sCacheOpWorkItem.ui64EnqueuedTime;
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-       sCacheOpWorkItem.eFenceOpType = eFenceOpType;
-#endif
-       sCacheOpWorkItem.uiSize = (uintptr_t) OSAtomicRead(&gsCwq.hCompletedSeqNum);
-       sCacheOpWorkItem.uiOffset = 0;
-#endif
-       PVR_UNREFERENCED_PARAMETER(eFenceOpType);
-
-       /* If initial fence check fails, then wait-and-retry in loop */
-       ui32CompletedOpSeqNum = OSAtomicRead(&gsCwq.hCompletedSeqNum);
-       if (CacheOpFenceCheck(ui32CompletedOpSeqNum, ui32FenceOpSeqNum))
-       {
-#if defined(CACHEOP_DEBUG)
-               sCacheOpWorkItem.uiSize = (uintptr_t) ui32CompletedOpSeqNum;
-#endif
-               goto e0;
-       }
-
-       /* Open CacheOp update event object, if event open fails return error */
-       eError2 = OSEventObjectOpen(gsCwq.hClientWakeUpEvtObj, &hOSEvent);
-       PVR_LOG_GOTO_IF_ERROR(eError2, "OSEventObjectOpen", e0);
-
-       /* Linear (i.e. use exponential?) back-off, upper bounds user wait */
-       for (ui32RetryAbort = gsCwq.ui32FenceRetryAbort; ;--ui32RetryAbort)
-       {
-               /* (Re)read completed CacheOp sequence number before waiting */
-               ui32CompletedOpSeqNum = OSAtomicRead(&gsCwq.hCompletedSeqNum);
-               if (CacheOpFenceCheck(ui32CompletedOpSeqNum, ui32FenceOpSeqNum))
-               {
-#if defined(CACHEOP_DEBUG)
-                       sCacheOpWorkItem.uiSize = (uintptr_t) ui32CompletedOpSeqNum;
-#endif
-                       break;
-               }
-
-               (void) OSEventObjectWaitTimeout(hOSEvent, gsCwq.ui32FenceWaitTimeUs);
-
-               if (! ui32RetryAbort)
-               {
-#if defined(CACHEOP_DEBUG)
-                       sCacheOpWorkItem.uiSize = (uintptr_t) OSAtomicRead(&gsCwq.hCompletedSeqNum);
-                       sCacheOpWorkItem.uiOffset = 0;
-                       uiTimeNow = OSClockns64();
-#endif
-                       PVR_LOG(("CacheOpFence() event: "CACHEOP_ABORT_FENCE_ERROR_STRING));
-                       eError = PVRSRV_ERROR_RETRY;
-                       break;
-               }
-               else
-               {
-#if defined(CACHEOP_DEBUG)
-                       uiTimeNow = OSClockns64();
-#endif
-               }
-       }
-
-       eError2 = OSEventObjectClose(hOSEvent);
-       PVR_LOG_IF_ERROR(eError2, "OSEventObjectOpen");
-
-e0:
-#if defined(CACHEOP_DEBUG)
-       sCacheOpWorkItem.ui64ExecuteTime = uiTimeNow;
-       if (ui32FenceOpSeqNum)
-       {
-               IMG_UINT64 ui64TimeTakenNs = sCacheOpWorkItem.ui64EnqueuedTime - sCacheOpWorkItem.ui64ExecuteTime;
-               IMG_UINT32 ui32Time;
-               IMG_INT32 i32Div;
-
-               do_div(ui64TimeTakenNs, 1000);
-               ui32Time = ui64TimeTakenNs;
-
-               /* Only fences pending on CacheOps contribute towards statistics,
-                * Calculate the approximate cumulative moving average fence time.
-                * This calculation is based on standard equation:
-                *
-                * CMAnext = (new + count * CMAprev) / (count + 1)
-                *
-                * but in simplified form:
-                *
-                * CMAnext = CMAprev + (new - CMAprev) / (count + 1)
-                *
-                * this gets rid of multiplication and prevents overflow.
-                *
-                * Also to increase accuracy that we lose with integer division,
-                * we hold the moving remainder of the division and add it.
-                *
-                * CMAnext = CMAprev + (new - CMAprev + CMRprev) / (count + 1)
-                *
-                * Multiple tests proved it to be the best solution for approximating
-                * CMA using integers.
-                *
-                */
-
-               i32Div = (IMG_INT32)ui32Time - (IMG_INT32)gsCwq.ui32AvgFenceTime + (IMG_INT32)gsCwq.ui32AvgFenceTimeRemainder;
-
-
-               gsCwq.ui32AvgFenceTime += i32Div / (IMG_INT32)(gsCwq.ui32TotalFenceOps + 1);
-               gsCwq.ui32AvgFenceTimeRemainder = i32Div % (IMG_INT32)(gsCwq.ui32TotalFenceOps + 1);
-
-
-               gsCwq.ui32TotalFenceOps++;
-
-       }
-       CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
-#endif
-
-       return eError;
-}
-
 PVRSRV_ERROR CacheOpLog (PMR *psPMR,
                                                 IMG_UINT64 puiAddress,
                                                 IMG_DEVMEM_OFFSET_T uiOffset,
                                                 IMG_DEVMEM_SIZE_T uiSize,
-                                                IMG_UINT64 ui64EnqueuedTimeUs,
-                                                IMG_UINT64 ui64ExecuteTimeUs,
-                                                IMG_UINT32 ui32NumRBF,
+                                                IMG_UINT64 ui64StartTime,
+                                                IMG_UINT64 ui64EndTime,
                                                 PVRSRV_CACHE_OP uiCacheOp)
 {
 #if defined(CACHEOP_DEBUG)
        CACHEOP_WORK_ITEM sCacheOpWorkItem = {0};
        PVR_UNREFERENCED_PARAMETER(puiAddress);
 
+       sCacheOpWorkItem.psDevNode = PMR_DeviceNode(psPMR);
        sCacheOpWorkItem.psPMR = psPMR;
        sCacheOpWorkItem.uiSize = uiSize;
        sCacheOpWorkItem.uiOffset = uiOffset;
        sCacheOpWorkItem.uiCacheOp = uiCacheOp;
        sCacheOpWorkItem.pid = OSGetCurrentClientProcessIDKM();
-       sCacheOpWorkItem.ui32OpSeqNum = CacheOpGetNextCommonSeqNum();
 
-       sCacheOpWorkItem.ui64EnqueuedTime = ui64EnqueuedTimeUs;
-       sCacheOpWorkItem.ui64ExecuteTime = ui64ExecuteTimeUs;
-       sCacheOpWorkItem.bUMF = IMG_TRUE;
-       gsCwq.ui32ClientRBF += ui32NumRBF;
-       gsCwq.ui32ClientSync += 1;
+       sCacheOpWorkItem.ui64StartTime = ui64StartTime;
+       sCacheOpWorkItem.ui64EndTime = ui64EndTime;
+
+       gsCwq.ui32ClientOps += 1;
 
        CacheOpStatsExecLogWrite(&sCacheOpWorkItem);
 #else
@@ -2295,41 +1495,22 @@ PVRSRV_ERROR CacheOpLog (PMR *psPMR,
        PVR_UNREFERENCED_PARAMETER(uiSize);
        PVR_UNREFERENCED_PARAMETER(uiOffset);
        PVR_UNREFERENCED_PARAMETER(uiCacheOp);
-       PVR_UNREFERENCED_PARAMETER(ui32NumRBF);
        PVR_UNREFERENCED_PARAMETER(puiAddress);
-       PVR_UNREFERENCED_PARAMETER(ui64ExecuteTimeUs);
-       PVR_UNREFERENCED_PARAMETER(ui64EnqueuedTimeUs);
+       PVR_UNREFERENCED_PARAMETER(ui64StartTime);
+       PVR_UNREFERENCED_PARAMETER(ui64EndTime);
 #endif
        return PVRSRV_OK;
 }
 
 PVRSRV_ERROR CacheOpInit2 (void)
 {
-       void *pvAppHintState = NULL;
-       IMG_UINT32 ui32AppHintDefault = PVRSRV_APPHINT_CACHEOPTHREADPRIORITY;
-       IMG_UINT32 ui32AppHintCacheOpThreadPriority;
-
        PVRSRV_ERROR eError;
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
 
-       /* Create an event object for pending CacheOp work items */
-       eError = OSEventObjectCreate("PVRSRV_CACHEOP_EVENTOBJECT", &gsCwq.hThreadWakeUpEvtObj);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSEventObjectCreate", e0);
-
-       /* Create an event object for updating pending fence checks on CacheOp */
-       eError = OSEventObjectCreate("PVRSRV_CACHEOP_EVENTOBJECT", &gsCwq.hClientWakeUpEvtObj);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSEventObjectCreate", e0);
-
-       /* Appending work-items is not concurrent, lock protects against this */
-       eError = OSLockCreate((POS_LOCK*)&gsCwq.hDeferredLock);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate", e0);
-
        /* Apphint read/write is not concurrent, so lock protects against this */
        eError = OSLockCreate((POS_LOCK*)&gsCwq.hConfigLock);
        PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate", e0);
 
-       gsCwq.ui32FenceWaitTimeUs = CACHEOP_FENCE_WAIT_TIMEOUT;
-       gsCwq.ui32FenceRetryAbort = CACHEOP_FENCE_RETRY_ABORT;
 
 #if defined(CACHEFLUSH_ISA_SUPPORTS_UM_FLUSH)
        gsCwq.bSupportsUMFlush = IMG_TRUE;
@@ -2358,24 +1539,6 @@ PVRSRV_ERROR CacheOpInit2 (void)
        /* Set before spawning thread */
        gsCwq.bInit = IMG_TRUE;
 
-       OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintUINT32(pvAppHintState, CacheOpThreadPriority,
-                                    &ui32AppHintDefault, &ui32AppHintCacheOpThreadPriority);
-       OSFreeKMAppHintState(pvAppHintState);
-
-       /* Create a thread which is used to execute the deferred CacheOp(s),
-          these are CacheOp(s) executed by the server on behalf of clients
-          asynchronously. All clients synchronise with the server before
-          submitting any HW operation (i.e. device kicks) to ensure that
-          client device work-load memory is coherent */
-       eError = OSThreadCreatePriority(&gsCwq.hWorkerThread,
-                                                                       "pvr_cacheop",
-                                                                       CacheOpThread,
-                                                                       CacheOpThreadDumpInfo,
-                                                                       IMG_TRUE,
-                                                                       psPVRSRVData,
-                                                                       ui32AppHintCacheOpThreadPriority);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSThreadCreatePriority", e0);
        {
                DI_ITERATOR_CB sIterator = {.pfnShow = CacheOpConfigRead};
                /* Writing the unsigned integer binary encoding of CACHEOP_CONFIG
@@ -2406,66 +1569,14 @@ e0:
 
 void CacheOpDeInit2 (void)
 {
-       PVRSRV_ERROR eError = PVRSRV_OK;
-
        gsCwq.bInit = IMG_FALSE;
 
-       if (gsCwq.hThreadWakeUpEvtObj)
-       {
-               eError = OSEventObjectSignal(gsCwq.hThreadWakeUpEvtObj);
-               PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
-       }
-
-       if (gsCwq.hClientWakeUpEvtObj)
-       {
-               eError = OSEventObjectSignal(gsCwq.hClientWakeUpEvtObj);
-               PVR_LOG_IF_ERROR(eError, "OSEventObjectSignal");
-       }
-
-       if (gsCwq.hWorkerThread)
-       {
-               LOOP_UNTIL_TIMEOUT(OS_THREAD_DESTROY_TIMEOUT_US)
-               {
-                       eError = OSThreadDestroy(gsCwq.hWorkerThread);
-                       if (PVRSRV_OK == eError)
-                       {
-                               gsCwq.hWorkerThread = NULL;
-                               break;
-                       }
-                       OSWaitus(OS_THREAD_DESTROY_TIMEOUT_US/OS_THREAD_DESTROY_RETRY_COUNT);
-               } END_LOOP_UNTIL_TIMEOUT();
-               PVR_LOG_IF_ERROR(eError, "OSThreadDestroy");
-               gsCwq.hWorkerThread = NULL;
-       }
-
-       if (gsCwq.hClientWakeUpEvtObj)
-       {
-               eError = OSEventObjectDestroy(gsCwq.hClientWakeUpEvtObj);
-               PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
-               gsCwq.hClientWakeUpEvtObj = NULL;
-       }
-
-       if (gsCwq.hThreadWakeUpEvtObj)
-       {
-               eError = OSEventObjectDestroy(gsCwq.hThreadWakeUpEvtObj);
-               PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
-               gsCwq.hThreadWakeUpEvtObj = NULL;
-       }
-
        if (gsCwq.hConfigLock)
        {
-               eError = OSLockDestroy(gsCwq.hConfigLock);
-               PVR_LOG_IF_ERROR(eError, "OSLockDestroy");
+               OSLockDestroy(gsCwq.hConfigLock);
                gsCwq.hConfigLock = NULL;
        }
 
-       if (gsCwq.hDeferredLock)
-       {
-               eError = OSLockDestroy(gsCwq.hDeferredLock);
-               PVR_LOG_IF_ERROR(eError, "OSLockDestroy");
-               gsCwq.hDeferredLock = NULL;
-       }
-
        if (gsCwq.psConfigTune)
        {
                DIDestroyEntry(gsCwq.psConfigTune);
@@ -2478,14 +1589,8 @@ void CacheOpDeInit2 (void)
 
 PVRSRV_ERROR CacheOpInit (void)
 {
-       IMG_UINT32 idx;
        PVRSRV_ERROR eError = PVRSRV_OK;
 
-       /* DDK initialisation is anticipated to be performed on the boot
-          processor (little core in big/little systems) though this may
-          not always be the case. If so, the value cached here is the
-          system wide safe (i.e. smallest) L1 d-cache line size value
-          on any/such platforms with mismatched d-cache line sizes */
        gsCwq.uiPageSize = OSGetPageSize();
        gsCwq.uiPageShift = OSGetPageShift();
        gsCwq.uiLineSize = OSCPUCacheAttributeSize(OS_CPU_CACHE_ATTRIBUTE_LINE_SIZE);
@@ -2493,21 +1598,6 @@ PVRSRV_ERROR CacheOpInit (void)
        PVR_LOG_RETURN_IF_FALSE((gsCwq.uiLineSize && gsCwq.uiPageSize && gsCwq.uiPageShift), "", PVRSRV_ERROR_INIT_FAILURE);
        gsCwq.uiCacheOpAddrType = OSCPUCacheOpAddressType();
 
-       /* More information regarding these atomic counters can be found
-          in the CACHEOP_WORK_QUEUE type definition at top of file */
-       OSAtomicWrite(&gsCwq.hCompletedSeqNum, 0);
-       OSAtomicWrite(&gsCwq.hCommonSeqNum, 0);
-       OSAtomicWrite(&gsCwq.hWriteCounter, 0);
-       OSAtomicWrite(&gsCwq.hReadCounter, 0);
-
-       for (idx = 0; idx < CACHEOP_INDICES_MAX; idx++)
-       {
-               gsCwq.asWorkItems[idx].iTimeline = PVRSRV_NO_TIMELINE;
-               gsCwq.asWorkItems[idx].psPMR = (void *)(uintptr_t)~0;
-               gsCwq.asWorkItems[idx].ui32OpSeqNum = (IMG_UINT32)~0;
-       }
-
-
 #if defined(CACHEOP_DEBUG)
        /* debugfs file read-out is not concurrent, so lock protects against this */
        eError = OSLockCreate((POS_LOCK*)&gsCwq.hStatsExecLock);
@@ -2533,7 +1623,7 @@ void CacheOpDeInit (void)
 #if defined(CACHEOP_DEBUG)
        if (gsCwq.hStatsExecLock)
        {
-               (void) OSLockDestroy(gsCwq.hStatsExecLock);
+               OSLockDestroy(gsCwq.hStatsExecLock);
                gsCwq.hStatsExecLock = NULL;
        }
 
index 2b7f877..92e0551 100644 (file)
@@ -53,6 +53,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pdump_km.h"
 #include "osfunc.h"
 #include "tlstream.h"
+#include "rgxhwperf_common.h"
 
 /* PID associated with Connection currently being purged by Cleanup thread */
 static IMG_PID gCurrentPurgeConnectionPid;
@@ -91,41 +92,9 @@ static PVRSRV_ERROR ConnectionDataDestroy(CONNECTION_DATA *psConnection)
 
        if (psProcessHandleBase != NULL)
        {
-               /* acquire the lock now to ensure unref and removal from the
-                * hash table is atomic.
-                * if the refcount becomes zero then the lock needs to be held
-                * until the entry is removed from the hash table.
-                */
-               OSLockAcquire(psPVRSRVData->hProcessHandleBase_Lock);
-
-               /* In case the refcount becomes 0 we can remove the process handle base */
-               if (OSAtomicDecrement(&psProcessHandleBase->iRefCount) == 0)
-               {
-                       uintptr_t uiHashValue;
-
-                       uiHashValue = HASH_Remove(psPVRSRVData->psProcessHandleBase_Table, psConnection->pid);
-                       OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
-
-                       if (!uiHashValue)
-                       {
-                               PVR_DPF((PVR_DBG_ERROR,
-                                               "%s: Failed to remove handle base from hash table.",
-                                               __func__));
-                               return PVRSRV_ERROR_UNABLE_TO_REMOVE_HASH_VALUE;
-                       }
-
-                       eError = PVRSRVFreeKernelHandles(psProcessHandleBase->psHandleBase);
-                       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVFreeKernelHandles");
-
-                       eError = PVRSRVFreeHandleBase(psProcessHandleBase->psHandleBase, ui64MaxBridgeTime);
-                       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVFreeHandleBase:1");
-
-                       OSFreeMem(psProcessHandleBase);
-               }
-               else
-               {
-                       OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
-               }
+               eError = PVRSRVReleaseProcessHandleBase(psProcessHandleBase, psConnection->pid,
+                                                       ui64MaxBridgeTime);
+               PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVReleaseProcessHandleBase");
 
                psConnection->psProcessHandleBase = NULL;
        }
@@ -195,7 +164,6 @@ PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData)
        CONNECTION_DATA *psConnection;
        PVRSRV_ERROR eError;
        PROCESS_HANDLE_BASE *psProcessHandleBase;
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
 
        /* Allocate connection data area, no stats since process not registered yet */
        psConnection = OSAllocZMemNoStats(sizeof(*psConnection));
@@ -227,10 +195,6 @@ PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData)
        psConnection->bAcceptDmaRequests = IMG_TRUE;
 #endif
 
-#if defined(DEBUG) || defined(PDUMP)
-       PVR_LOG(("%s connected", psConnection->pszProcName));
-#endif
-
        /* Register this connection with the sync core */
        eError = SyncRegisterConnection(&psConnection->psSyncConnectionData);
        PVR_LOG_GOTO_IF_ERROR(eError, "SyncRegisterConnection", failure);
@@ -249,51 +213,41 @@ PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData)
                                       PVRSRV_HANDLE_BASE_TYPE_CONNECTION);
        PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandleBase", failure);
 
-       /* Try to get process handle base if it already exists */
-       OSLockAcquire(psPVRSRVData->hProcessHandleBase_Lock);
-       psProcessHandleBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(PVRSRVGetPVRSRVData()->psProcessHandleBase_Table,
-                                                                  psConnection->pid);
-
-       /* In case there is none we are going to allocate one */
-       if (psProcessHandleBase == NULL)
-       {
-               psProcessHandleBase = OSAllocZMem(sizeof(PROCESS_HANDLE_BASE));
-               PVR_LOG_GOTO_IF_NOMEM(psProcessHandleBase, eError, failureLock);
-
-               OSAtomicWrite(&psProcessHandleBase->iRefCount, 0);
-
-               /* Allocate handle base for this process */
-               eError = PVRSRVAllocHandleBase(&psProcessHandleBase->psHandleBase,
-                                              PVRSRV_HANDLE_BASE_TYPE_PROCESS);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_LOG_ERROR(eError, "PVRSRVAllocHandleBase");
-                       OSFreeMem(psProcessHandleBase);
-                       goto failureLock;
-               }
-
-               /* Insert the handle base into the global hash table */
-               if (!HASH_Insert(PVRSRVGetPVRSRVData()->psProcessHandleBase_Table,
-                                psConnection->pid,
-                                (uintptr_t) psProcessHandleBase))
-               {
-                       PVRSRVFreeHandleBase(psProcessHandleBase->psHandleBase, 0);
-
-                       OSFreeMem(psProcessHandleBase);
-                       PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_UNABLE_TO_INSERT_HASH_VALUE, failureLock);
-               }
-       }
-       OSAtomicIncrement(&psProcessHandleBase->iRefCount);
-
-       OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
+       /* get process handle base (if it doesn't exist it will be allocated) */
+       eError = PVRSRVAcquireProcessHandleBase(psConnection->pid, &psProcessHandleBase);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAcquireProcessHandleBase", failure);
 
        /* hConnectionsLock now resides in PVRSRV_DEVICE_NODE */
        {
+               IMG_BOOL bHostStreamIsNull;
+               PVRSRV_RGXDEV_INFO  *psRgxDevInfo;
                PVRSRV_DEVICE_NODE      *psDevNode = OSGetDevNode(psConnection);
 
                OSLockAcquire(psDevNode->hConnectionsLock);
                dllist_add_to_tail(&psDevNode->sConnections, &psConnection->sConnectionListNode);
+#if defined(DEBUG) || defined(PDUMP)
+               PVR_LOG(("%s connected - (devID = %u)", psConnection->pszProcName,
+                       psDevNode->sDevId.ui32InternalID));
+#endif
                OSLockRelease(psDevNode->hConnectionsLock);
+
+               if (!PVRSRV_VZ_MODE_IS(GUEST))
+               {
+                       psRgxDevInfo = _RGX_DEVICE_INFO_FROM_NODE(psDevNode);
+
+                       OSLockAcquire(psRgxDevInfo->hLockHWPerfHostStream);
+                       bHostStreamIsNull = (IMG_BOOL)(psRgxDevInfo->hHWPerfHostStream == NULL);
+                       OSLockRelease(psRgxDevInfo->hLockHWPerfHostStream);
+
+                       if (!bHostStreamIsNull)
+                       {
+                               if (TLStreamIsOpenForReading(psRgxDevInfo->hHWPerfHostStream))
+                               {
+                                       /* Announce this client connection in the host stream, if event mask is set */
+                                       RGXSRV_HWPERF_HOST_CLIENT_INFO_PROCESS_NAME(psDevNode, psConnection->pid, psConnection->pszProcName);
+                               }
+                       }
+               }
        }
 
        psConnection->psProcessHandleBase = psProcessHandleBase;
@@ -302,8 +256,6 @@ PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData)
 
        return PVRSRV_OK;
 
-failureLock:
-       OSLockRelease(psPVRSRVData->hProcessHandleBase_Lock);
 failure:
        ConnectionDataDestroy(psConnection);
 
@@ -402,7 +354,7 @@ void PVRSRVCommonConnectionDisconnect(void *pvDataPtr)
        /* Notify the PDump core if the pdump control client is disconnecting */
        if (psConnectionData->ui32ClientFlags & SRV_FLAGS_PDUMPCTRL)
        {
-               PDumpDisconnectionNotify();
+               PDumpDisconnectionNotify(psDevNode);
        }
 #if defined(SUPPORT_DMA_TRANSFER)
        OSLockAcquire(psConnectionData->hDmaReqLock);
@@ -418,7 +370,8 @@ void PVRSRVCommonConnectionDisconnect(void *pvDataPtr)
 #endif
 
 #if defined(DEBUG) || defined(PDUMP)
-       PVR_LOG(("%s disconnected", psConnectionData->pszProcName));
+       PVR_LOG(("%s disconnected - (devID = %u)", psConnectionData->pszProcName,
+               psDevNode->sDevId.ui32InternalID));
 #endif
 
 #if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
@@ -447,111 +400,92 @@ IMG_PID PVRSRVGetPurgeConnectionPid(void)
 #define MAX_DEBUG_DUMP_CONNECTION_STR_LEN (1+10+10+10+7+PVRSRV_CONNECTION_PROCESS_NAME_LEN)
 #define MAX_DEBUG_DUMP_STRING_LEN         (1+MAX_CONNECTIONS_PREFIX+(3*MAX_DEBUG_DUMP_CONNECTION_STR_LEN))
 
-void PVRSRVConnectionDebugNotify(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+void PVRSRVConnectionDebugNotify(PVRSRV_DEVICE_NODE *psDevNode,
+                                                                DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                  void *pvDumpDebugFile)
 {
        PDLLIST_NODE pNext, pNode;
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-       PVRSRV_DEVICE_NODE *psDevNode;
-       IMG_BOOL bFoundConnections = IMG_FALSE;
 
-       /*
-        * Connections are linked to each device-node within
-        * PVRSRV_DATA->psDeviceNodeList. Traverse this and display each connection
-        * within device node.
+       /* We must check for an initialised device before accessing its mutex.
+        * The mutex is initialised as part of DeviceInitialize() which occurs
+        * on first access to the device node.
         */
-       for (psDevNode = psPVRSRVData->psDeviceNodeList;
-            psDevNode != NULL;
-            psDevNode = psDevNode->psNext)
+       if (psDevNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
        {
-               /* We must check for an initialised device before accessing its mutex.
-                * The mutex is initialised as part of DeviceInitialize() which occurs
-                * on first access to the device node.
-                */
-               if (psDevNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
+               PVR_DUMPDEBUG_LOG("Connections: No Devices: No active connections");
+               return;
+       }
+
+       OSLockAcquire(psDevNode->hConnectionsLock);
+       if (dllist_is_empty(&psDevNode->sConnections))
+       {
+               PVR_DUMPDEBUG_LOG(CONNECTIONS_PREFIX " No active connections",
+                                                 (unsigned char)psDevNode->sDevId.ui32InternalID,
+                                                 (unsigned char)psDevNode->sDevId.i32OsDeviceID);
+       }
+       else
+       {
+               IMG_CHAR sActiveConnections[MAX_DEBUG_DUMP_STRING_LEN];
+               IMG_UINT16 i, uiPos = 0;
+               IMG_BOOL bPrinted = IMG_FALSE;
+               size_t uiSize = sizeof(sActiveConnections);
+
+               IMG_CHAR szTmpConBuff[MAX_CONNECTIONS_PREFIX + 1];
+               i = OSSNPrintf(szTmpConBuff,
+                                          MAX_CONNECTIONS_PREFIX,
+                                          CONNECTIONS_PREFIX,
+                                          (unsigned char)psDevNode->sDevId.ui32InternalID,
+                                          (unsigned char)psDevNode->sDevId.i32OsDeviceID);
+               OSStringLCopy(sActiveConnections+uiPos, szTmpConBuff, uiSize);
+
+               /* Move the write offset to the end of the current string */
+               uiPos += i;
+               /* Update the amount of remaining space available to copy into */
+               uiSize -= i;
+
+               dllist_foreach_node(&psDevNode->sConnections, pNode, pNext)
                {
-                       continue;
-               }
+                       CONNECTION_DATA *sData = IMG_CONTAINER_OF(pNode, CONNECTION_DATA, sConnectionListNode);
 
-               bFoundConnections = IMG_TRUE;
+                       IMG_CHAR sTmpBuff[MAX_DEBUG_DUMP_CONNECTION_STR_LEN];
+                       i = OSSNPrintf(sTmpBuff, MAX_DEBUG_DUMP_CONNECTION_STR_LEN,
+                               DEBUG_DUMP_CONNECTION_FORMAT_STR, sData->pid, sData->vpid, sData->tid, sData->pszProcName);
+                       i = MIN(MAX_DEBUG_DUMP_CONNECTION_STR_LEN, i);
+                       bPrinted = IMG_FALSE;
 
-               OSLockAcquire(psDevNode->hConnectionsLock);
-               if (dllist_is_empty(&psDevNode->sConnections))
-               {
-                       PVR_DUMPDEBUG_LOG(CONNECTIONS_PREFIX " No active connections",
-                                             (unsigned char)psDevNode->sDevId.ui32InternalID,
-                                             (unsigned char)psDevNode->sDevId.i32OsDeviceID);
-               }
-               else
-               {
-                       IMG_CHAR sActiveConnections[MAX_DEBUG_DUMP_STRING_LEN];
-                       IMG_UINT16 i, uiPos = 0;
-                       IMG_BOOL bPrinted = IMG_FALSE;
-                       size_t uiSize = sizeof(sActiveConnections);
-
-                       IMG_CHAR szTmpConBuff[MAX_CONNECTIONS_PREFIX + 1];
-                       i = OSSNPrintf(szTmpConBuff,
-                                          MAX_CONNECTIONS_PREFIX,
-                                          CONNECTIONS_PREFIX,
-                                          (unsigned char)psDevNode->sDevId.ui32InternalID,
-                                          (unsigned char)psDevNode->sDevId.i32OsDeviceID);
-                       OSStringLCopy(sActiveConnections+uiPos, szTmpConBuff, uiSize);
+                       OSStringLCopy(sActiveConnections+uiPos, sTmpBuff, uiSize);
 
                        /* Move the write offset to the end of the current string */
                        uiPos += i;
                        /* Update the amount of remaining space available to copy into */
                        uiSize -= i;
 
-                       dllist_foreach_node(&psDevNode->sConnections, pNode, pNext)
+                       /* If there is not enough space to add another connection to this line, output the line */
+                       if (uiSize <= MAX_DEBUG_DUMP_CONNECTION_STR_LEN)
                        {
-                               CONNECTION_DATA *sData = IMG_CONTAINER_OF(pNode, CONNECTION_DATA, sConnectionListNode);
-
-                               IMG_CHAR sTmpBuff[MAX_DEBUG_DUMP_CONNECTION_STR_LEN];
-                               i = OSSNPrintf(sTmpBuff, MAX_DEBUG_DUMP_CONNECTION_STR_LEN,
-                                       DEBUG_DUMP_CONNECTION_FORMAT_STR, sData->pid, sData->vpid, sData->tid, sData->pszProcName);
-                               i = MIN(MAX_DEBUG_DUMP_CONNECTION_STR_LEN, i);
-                               bPrinted = IMG_FALSE;
-
-                               OSStringLCopy(sActiveConnections+uiPos, sTmpBuff, uiSize);
-
-                               /* Move the write offset to the end of the current string */
-                               uiPos += i;
-                               /* Update the amount of remaining space available to copy into */
-                               uiSize -= i;
+                               PVR_DUMPDEBUG_LOG("%s", sActiveConnections);
 
-                               /* If there is not enough space to add another connection to this line, output the line */
-                               if (uiSize <= MAX_DEBUG_DUMP_CONNECTION_STR_LEN)
-                               {
-                                       PVR_DUMPDEBUG_LOG("%s", sActiveConnections);
-
-                                       /*
-                                        * Remove the "Connections:" prefix from the buffer.
-                                        * Leave the subsequent buffer contents indented by the same
-                                        * amount to aid in interpreting the debug output.
-                                        */
-                                       uiPos = sizeof(CONNECTIONS_PREFIX) - 1;
-                                       /* Reset the amount of space available to copy into */
-                                       uiSize = MAX_DEBUG_DUMP_STRING_LEN - uiPos;
-                                       bPrinted = IMG_TRUE;
-                               }
+                               /*
+                                * Remove the "Connections:" prefix from the buffer.
+                                * Leave the subsequent buffer contents indented by the same
+                                * amount to aid in interpreting the debug output.
+                                */
+                               uiPos = sizeof(CONNECTIONS_PREFIX) - 1;
+                               /* Reset the amount of space available to copy into */
+                               uiSize = MAX_DEBUG_DUMP_STRING_LEN - uiPos;
+                               bPrinted = IMG_TRUE;
                        }
+               }
 
-                       /* Only print the current line if it hasn't already been printed */
-                       if (!bPrinted)
-                       {
-                               // Strip of the final comma
-                               sActiveConnections[OSStringNLength(sActiveConnections, MAX_DEBUG_DUMP_STRING_LEN) - 1] = '\0';
-                               PVR_DUMPDEBUG_LOG("%s", sActiveConnections);
-                       }
+               /* Only print the current line if it hasn't already been printed */
+               if (!bPrinted)
+               {
+                       /* Strip off the final comma */
+                       sActiveConnections[OSStringNLength(sActiveConnections, MAX_DEBUG_DUMP_STRING_LEN) - 1] = '\0';
+                       PVR_DUMPDEBUG_LOG("%s", sActiveConnections);
+               }
 #undef MAX_DEBUG_DUMP_STRING_LEN
 #undef MAX_DEBUG_DUMP_CONNECTIONS_PER_LINE
-               }
-               OSLockRelease(psDevNode->hConnectionsLock);
-       }
-
-       /* Check to see if we have displayed anything from the loop above */
-       if (bFoundConnections == IMG_FALSE)
-       {
-               PVR_DUMPDEBUG_LOG("Connections: No Devices: No active connections");
        }
+       OSLockRelease(psDevNode->hConnectionsLock);
 }
index a49fe11..ee17281 100644 (file)
@@ -58,28 +58,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxdevice.h"
 #include "rgxdebug.h"
 #include "rgxinit.h"
+#include "rgxmmudefs_km.h"
 static IMG_HANDLE ghGpuUtilUserDebugFS;
 #endif
 
 static DI_ENTRY *gpsVersionDIEntry;
 static DI_ENTRY *gpsStatusDIEntry;
-static DI_ENTRY *gpsDumpDebugDIEntry;
 
-#ifdef SUPPORT_RGX
-static DI_ENTRY *gpsFWTraceDIEntry;
-#ifdef SUPPORT_POWER_VALIDATION_VIA_DEBUGFS
-static DI_ENTRY *gpsPowMonDIEntry;
-#endif /* SUPPORT_POWER_VALIDATION_VIA_DEBUGFS */
-#ifdef SUPPORT_FIRMWARE_GCOV
-static DI_ENTRY *gpsFirmwareGcovDIEntry;
-#endif /* SUPPORT_FIRMWARE_GCOV */
-#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
-static DI_ENTRY *gpsPowerDataDIEntry;
-#endif /* SUPPORT_POWER_SAMPLING_VIA_DEBUGFS */
-#ifdef SUPPORT_VALIDATION
-static DI_ENTRY *gpsRGXRegsDIEntry;
-#endif /* SUPPORT_VALIDATION */
-#endif /* SUPPORT_RGX */
 #ifdef SUPPORT_VALIDATION
 static DI_ENTRY *gpsTestMemLeakDIEntry;
 #endif /* SUPPORT_VALIDATION */
@@ -87,6 +72,18 @@ static DI_ENTRY *gpsTestMemLeakDIEntry;
 static DI_ENTRY *gpsDebugLevelDIEntry;
 #endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
 
+static void _DumpDebugDIPrintfWrapper(void *pvDumpDebugFile, const IMG_CHAR *pszFormat, ...)
+{
+       IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
+       va_list ArgList;
+
+       OSSNPrintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, "%s\n", pszFormat);
+
+       va_start(ArgList, pszFormat);
+       DIVPrintf(pvDumpDebugFile, szBuffer, ArgList);
+       va_end(ArgList);
+}
+
 /*************************************************************************/ /*!
  Version DebugFS entry
 */ /**************************************************************************/
@@ -107,6 +104,7 @@ static void *_VersionDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
 {
        PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
        IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        PVR_UNREFERENCED_PARAMETER(psEntry);
 
@@ -120,10 +118,14 @@ static void *_VersionDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
                return DI_START_TOKEN;
        }
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
                                              _DebugVersionCompare_AnyVaCb,
                                              &uiCurrentPosition,
                                              *pui64Pos);
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
+       return psDeviceNode;
 }
 
 static void _VersionDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvPriv)
@@ -137,13 +139,18 @@ static void *_VersionDINext(OSDI_IMPL_ENTRY *psEntry,void *pvPriv,
 {
        PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
        IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        (*pui64Pos)++;
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
                                              _DebugVersionCompare_AnyVaCb,
                                              &uiCurrentPosition,
                                              *pui64Pos);
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
+       return psDeviceNode;
 }
 
 #define DI_PRINT_VERSION_FMTSPEC \
@@ -151,6 +158,7 @@ static void *_VersionDINext(OSDI_IMPL_ENTRY *psEntry,void *pvPriv,
 #define STR_DEBUG   "debug"
 #define STR_RELEASE "release"
 
+#if defined(DEBUG) || defined(SUPPORT_VALIDATION)
 #define BUILD_OPT_LEN 80
 
 static inline void _AppendOptionStr(IMG_CHAR pszBuildOptions[], const IMG_CHAR* str, OSDI_IMPL_ENTRY *psEntry, IMG_UINT32* pui32BuildOptionLen)
@@ -172,6 +180,7 @@ static inline void _AppendOptionStr(IMG_CHAR pszBuildOptions[], const IMG_CHAR*
        }
        *pui32BuildOptionLen = ui32BuildOptionLen;
 }
+#endif /* DEBUG || SUPPORT_VALIDATION */
 
 static int _VersionDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvPriv)
 {
@@ -236,6 +245,8 @@ static int _VersionDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvPriv)
                IMG_BOOL bFwVersionInfoPrinted = IMG_FALSE;
 
                DIPrintf(psEntry, "\nDevice Name: %s\n", psDevConfig->pszName);
+               DIPrintf(psEntry, "Device ID: %u:%d\n", psDevNode->sDevId.ui32InternalID,
+                                                       psDevNode->sDevId.i32OsDeviceID);
 
                if (psDevConfig->pszVersion)
                {
@@ -328,53 +339,6 @@ static int _VersionDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvPriv)
  Power data DebugFS entry
 */ /**************************************************************************/
 
-static void *_DebugPowerDataCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode,
-                                         va_list va)
-{
-       IMG_UINT64 *pui64CurrentPosition = va_arg(va, IMG_UINT64 *);
-       IMG_UINT64 ui64Position = va_arg(va, IMG_UINT64;
-       IMG_UINT64 ui64CurrentPosition = *pui64CurrentPosition;
-
-       (*puiCurrentPosition)++;
-
-       return (ui64CurrentPosition == ui64Position) ? psDevNode : NULL;
-}
-
-static void *_DebugPowerDataDIStart(OSDI_IMPL_ENTRY *psEntry,
-                                                                        IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 0;
-
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                             _DebugPowerDataCompare_AnyVaCb,
-                                             &uiCurrentPosition,
-                                             *pui64Pos);
-}
-
-static void _DebugPowerDataDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       PVR_UNREFERENCED_PARAMETER(psEntry);
-       PVR_UNREFERENCED_PARAMETER(pvData);
-}
-
-static void *_DebugPowerDataDINext(OSDI_IMPL_ENTRY *psEntry,
-                                                                       void *pvData,
-                                                                       IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 0;
-
-       PVR_UNREFERENCED_PARAMETER(pvData);
-
-       (*pui64Pos)++;
-
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                             _DebugPowerDataCompare_AnyVaCb,
-                                             &uiCurrentPosition,
-                                             *pui64Pos);
-}
-
 static PVRSRV_ERROR SendPowerCounterCommand(PVRSRV_DEVICE_NODE* psDeviceNode,
                                             RGXFWIF_COUNTER_DUMP_REQUEST eRequestType,
                                             IMG_UINT32 *pui32kCCBCommandSlot)
@@ -383,6 +347,8 @@ static PVRSRV_ERROR SendPowerCounterCommand(PVRSRV_DEVICE_NODE* psDeviceNode,
 
        RGXFWIF_KCCB_CMD sCounterDumpCmd;
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        sCounterDumpCmd.eCmdType = RGXFWIF_KCCB_CMD_COUNTER_DUMP;
        sCounterDumpCmd.uCmdData.sCounterDumpConfigData.eCounterDumpRequest = eRequestType;
 
@@ -397,132 +363,96 @@ static PVRSRV_ERROR SendPowerCounterCommand(PVRSRV_DEVICE_NODE* psDeviceNode,
        return eError;
 }
 
-static void *_IsDevNodeNotInitialised(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-       return psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_ACTIVE ?
-               NULL : psDeviceNode;
-}
-
-static void _SendPowerCounterCommand(PVRSRV_DEVICE_NODE* psDeviceNode,
-                                                                        va_list va)
+static int _DebugPowerDataDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       IMG_UINT32         ui32kCCBCommandSlot;
+       IMG_UINT32 ui32kCCBCommandSlot;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
-       OSLockAcquire(psDevInfo->hCounterDumpingLock);
+       PVR_UNREFERENCED_PARAMETER(pvData);
 
-       SendPowerCounterCommand(psDeviceNode,
-                               va_arg(va, RGXFWIF_COUNTER_DUMP_REQUEST),
-                               &ui32kCCBCommandSlot);
+       if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Device not initialised when "
+                                "power counter data was requested!"));
+               return -EIO;
+       }
 
-       OSLockRelease(psDevInfo->hCounterDumpingLock);
-}
+       OSLockAcquire(psDevInfo->hCounterDumpingLock);
 
-static int _DebugPowerDataDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-       IMG_UINT32 ui32kCCBCommandSlot;
-       PVRSRV_ERROR eError = PVRSRV_OK;
+       eError = SendPowerCounterCommand(psDeviceNode,
+                                                                        RGXFWIF_PWR_COUNTER_DUMP_SAMPLE,
+                                                                        &ui32kCCBCommandSlot);
 
-       if (pvData != NULL)
+       if (eError != PVRSRV_OK)
        {
-               PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
-               PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-
-               if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "Not all device nodes were initialised "
-                               "when power counter data was requested!"));
-                       return -EIO;
-               }
+               OSLockRelease(psDevInfo->hCounterDumpingLock);
+               return -EIO;
+       }
 
-               OSLockAcquire(psDevInfo->hCounterDumpingLock);
+       /* Wait for FW complete completion */
+       eError = RGXWaitForKCCBSlotUpdate(psDevInfo,
+                                                                         ui32kCCBCommandSlot,
+                                                                         PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_LOG_ERROR(eError, "RGXWaitForKCCBSlotUpdate");
+               OSLockRelease(psDevInfo->hCounterDumpingLock);
+               return -EIO;
+       }
 
-               eError = SendPowerCounterCommand(psDeviceNode,
-                                                RGXFWIF_PWR_COUNTER_DUMP_SAMPLE,
-                                                &ui32kCCBCommandSlot);
+       /* Read back the buffer */
+       {
+               IMG_UINT32* pui32PowerBuffer;
+               IMG_UINT32 ui32NumOfRegs, ui32SamplePeriod;
+               IMG_UINT32 i, j;
 
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psCounterBufferMemDesc,
+                                                                                 (void**)&pui32PowerBuffer);
                if (eError != PVRSRV_OK)
                {
+                       PVR_LOG_ERROR(eError, "DevmemAcquireCpuVirtAddr");
                        OSLockRelease(psDevInfo->hCounterDumpingLock);
                        return -EIO;
                }
 
-               /* Wait for FW complete completion */
-               eError = RGXWaitForKCCBSlotUpdate(psDevInfo,
-                                                 ui32kCCBCommandSlot,
-                                                 PDUMP_FLAGS_CONTINUOUS);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_LOG_ERROR(eError, "RGXWaitForKCCBSlotUpdate");
-                       OSLockRelease(psDevInfo->hCounterDumpingLock);
-                       return -EIO;
-               }
+               ui32NumOfRegs = *pui32PowerBuffer++;
+               ui32SamplePeriod = *pui32PowerBuffer++;
 
-               /* Read back the buffer */
+               if (ui32NumOfRegs)
                {
-                       IMG_UINT32* pui32PowerBuffer;
-                       IMG_UINT32 ui32NumOfRegs, ui32SamplePeriod;
-                       IMG_UINT32 i, j;
+                       DIPrintf(psEntry, "Power counter data for device\n");
+                       DIPrintf(psEntry, "Sample period: 0x%08x\n", ui32SamplePeriod);
 
-                       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psCounterBufferMemDesc,
-                                                         (void**)&pui32PowerBuffer);
-                       if (eError != PVRSRV_OK)
+                       for (i = 0; i < ui32NumOfRegs; i++)
                        {
-                               PVR_LOG_ERROR(eError, "DevmemAcquireCpuVirtAddr");
-                               OSLockRelease(psDevInfo->hCounterDumpingLock);
-                               return -EIO;
-                       }
-#ifdef CACHE_TEST
-                       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psCounterBufferMemDesc;
-                       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-                       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-                       {
-                           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pui32PowerBuffer - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-                       }
-#endif
+                               IMG_UINT32 ui32High, ui32Low;
+                               IMG_UINT32 ui32RegOffset = *pui32PowerBuffer++;
+                               IMG_UINT32 ui32NumOfInstances = *pui32PowerBuffer++;
 
-                       ui32NumOfRegs = *pui32PowerBuffer++;
-                       ui32SamplePeriod = *pui32PowerBuffer++;
+                               PVR_ASSERT(ui32NumOfInstances);
 
-                       if (ui32NumOfRegs)
-                       {
-                               DIPrintf(psEntry, "Power counter data for device id: %d\n",
-                                        psDeviceNode->sDevId.i32OsDeviceID);
-                               DIPrintf(psEntry, "Sample period: 0x%08x\n", ui32SamplePeriod);
+                               DIPrintf(psEntry, "0x%08x:", ui32RegOffset);
 
-                               for (i = 0; i < ui32NumOfRegs; i++)
+                               for (j = 0; j < ui32NumOfInstances; j++)
                                {
-                                       IMG_UINT32 ui32High, ui32Low;
-                                       IMG_UINT32 ui32RegOffset = *pui32PowerBuffer++;
-                                       IMG_UINT32 ui32NumOfInstances = *pui32PowerBuffer++;
-
-                                       PVR_ASSERT(ui32NumOfInstances);
-
-                                       DIPrintf(psEntry, "0x%08x:", ui32RegOffset);
+                                       ui32Low = *pui32PowerBuffer++;
+                                       ui32High = *pui32PowerBuffer++;
 
-                                       for (j = 0; j < ui32NumOfInstances; j++)
-                                       {
-                                               ui32Low = *pui32PowerBuffer++;
-                                               ui32High = *pui32PowerBuffer++;
-
-                                               DIPrintf(psEntry, " 0x%016llx",
-                                                       (IMG_UINT64) ui32Low | (IMG_UINT64) ui32High << 32);
-                                       }
-
-                                       DIPrintf(psEntry, "\n");
+                                       DIPrintf(psEntry, " 0x%016llx",
+                                                        (IMG_UINT64) ui32Low | (IMG_UINT64) ui32High << 32);
                                }
-                       }
 
-                       DevmemReleaseCpuVirtAddr(psDevInfo->psCounterBufferMemDesc);
+                               DIPrintf(psEntry, "\n");
+                       }
                }
 
-               OSLockRelease(psDevInfo->hCounterDumpingLock);
+               DevmemReleaseCpuVirtAddr(psDevInfo->psCounterBufferMemDesc);
        }
 
+       OSLockRelease(psDevInfo->hCounterDumpingLock);
+
        return eError;
 }
 
@@ -530,19 +460,20 @@ static IMG_INT64 PowerDataSet(const IMG_CHAR __user *pcBuffer,
                               IMG_UINT64 ui64Count, IMG_UINT64 *pui64Pos,
                               void *pvData)
 {
-       PVRSRV_DATA* psPVRSRVData = (PVRSRV_DATA*) pvData;
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvData;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        RGXFWIF_COUNTER_DUMP_REQUEST eRequest;
+       IMG_UINT32 ui32kCCBCommandSlot;
 
        PVR_RETURN_IF_FALSE(pcBuffer != NULL, -EIO);
        PVR_RETURN_IF_FALSE(pui64Pos != NULL && *pui64Pos == 0, -EIO);
        PVR_RETURN_IF_FALSE(ui64Count >= 1, -EINVAL);
        PVR_RETURN_IF_FALSE(pcBuffer[ui64Count - 1] == '\0', -EINVAL);
 
-       if (List_PVRSRV_DEVICE_NODE_Any(psPVRSRVData->psDeviceNodeList,
-                                       _IsDevNodeNotInitialised))
+       if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
        {
-               PVR_DPF((PVR_DBG_ERROR, "Not all device nodes were initialised when "
-                       "power counter data was requested!"));
+               PVR_DPF((PVR_DBG_ERROR, "Device not initialised when "
+                                "power counter data was requested!"));
                return -EIO;
        }
 
@@ -559,8 +490,13 @@ static IMG_INT64 PowerDataSet(const IMG_CHAR __user *pcBuffer,
                return -EINVAL;
        }
 
-       List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
-                                                                          _SendPowerCounterCommand, eRequest);
+       OSLockAcquire(psDevInfo->hCounterDumpingLock);
+
+       SendPowerCounterCommand(psDeviceNode,
+                               eRequest,
+                               &ui32kCCBCommandSlot);
+
+       OSLockRelease(psDevInfo->hCounterDumpingLock);
 
        *pui64Pos += ui64Count;
        return ui64Count;
@@ -588,16 +524,21 @@ static void *_DebugStatusDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
 {
        PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
        IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        if (*pui64Pos == 0)
        {
                return DI_START_TOKEN;
        }
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode =  List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
                                                                                  _DebugStatusCompare_AnyVaCb,
                                                                                  &uiCurrentPosition,
                                                                                  *pui64Pos);
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
+       return psDeviceNode;
 }
 
 static void _DebugStatusDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
@@ -612,15 +553,20 @@ static void *_DebugStatusDINext(OSDI_IMPL_ENTRY *psEntry,
 {
        PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
        IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        PVR_UNREFERENCED_PARAMETER(pvData);
 
        (*pui64Pos)++;
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode =  List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
                                                                                  _DebugStatusCompare_AnyVaCb,
                                                                                  &uiCurrentPosition,
                                                                                  *pui64Pos);
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
+       return psDeviceNode;
 }
 
 static int _DebugStatusDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
@@ -657,6 +603,9 @@ static int _DebugStatusDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
                PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus;
                PVRSRV_DEVICE_HEALTH_REASON eHealthReason;
 
+               DIPrintf(psEntry, "\nDevice ID: %u:%d\n", psDeviceNode->sDevId.ui32InternalID,
+                                                         psDeviceNode->sDevId.i32OsDeviceID);
+
                /* Update the health status now if possible... */
                if (psDeviceNode->pfnUpdateHealthStatus)
                {
@@ -705,8 +654,8 @@ static int _DebugStatusDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
                {
 #ifdef SUPPORT_RGX
                        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-                       RGXFWIF_HWRINFOBUF *psHWRInfoBuf = psDevInfo->psRGXFWIfHWRInfoBufCtl;
-                       RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+                       const RGXFWIF_HWRINFOBUF *psHWRInfoBuf = psDevInfo->psRGXFWIfHWRInfoBufCtl;
+                       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
 
 #ifdef PVRSRV_DEBUG_LISR_EXECUTION
                        /* Show the detected #LISR, #MISR scheduled calls */
@@ -812,166 +761,177 @@ static IMG_INT64 DebugStatusSet(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
  Dump Debug DebugFS entry
 */ /**************************************************************************/
 
-static void *_DebugDumpDebugCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
+static int _DebugDumpDebugDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       IMG_UINT64 *pui64CurrentPosition = va_arg(va, IMG_UINT64 *);
-       IMG_UINT64 ui64Position = va_arg(va, IMG_UINT64);
-       IMG_UINT64 ui64CurrentPosition = *pui64CurrentPosition;
-
-       (*pui64CurrentPosition)++;
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
 
-       return (ui64CurrentPosition == ui64Position) ? psDevNode : NULL;
-}
-
-static void *_DebugDumpDebugDIStart(OSDI_IMPL_ENTRY *psEntry,
-                                    IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
+       PVR_UNREFERENCED_PARAMETER(pvData);
 
-       if (*pui64Pos == 0)
+       if (psDeviceNode->pvDevice != NULL)
        {
-               return DI_START_TOKEN;
+               PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX,
+                                  _DumpDebugDIPrintfWrapper, psEntry);
        }
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _DebugDumpDebugCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
-
-static void _DebugDumpDebugDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       PVR_UNREFERENCED_PARAMETER(psEntry);
-       PVR_UNREFERENCED_PARAMETER(pvData);
+       return 0;
 }
 
-static void *_DebugDumpDebugDINext(OSDI_IMPL_ENTRY *psEntry,
-                                                                       void *pvData,
-                                                                       IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
-
-       PVR_UNREFERENCED_PARAMETER(pvData);
-
-       (*pui64Pos)++;
+#ifdef SUPPORT_RGX
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _DebugDumpDebugCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
+/*************************************************************************/ /*!
+ Firmware Trace DebugFS entry
+*/ /**************************************************************************/
 
-static void _DumpDebugDIPrintf(void *pvDumpDebugFile,
-                               const IMG_CHAR *pszFormat, ...)
+static int _DebugFWTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       OSDI_IMPL_ENTRY *psEntry = pvDumpDebugFile;
-       IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
-       va_list ArgList;
-
-       va_start(ArgList, pszFormat);
-       vsnprintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, pszFormat, ArgList);
-       va_end(ArgList);
-       DIPrintf(psEntry, "%s\n", szBuffer);
-}
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
-static int _DebugDumpDebugDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       if (pvData != NULL  &&  pvData != DI_START_TOKEN)
+       if (psDevInfo != NULL)
        {
-               PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
-
-               if (psDeviceNode->pvDevice != NULL)
-               {
-                       PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX,
-                                          _DumpDebugDIPrintf, psEntry);
-               }
+               RGXDumpFirmwareTrace(_DumpDebugDIPrintfWrapper, psEntry, psDevInfo);
        }
 
        return 0;
 }
 
-#ifdef SUPPORT_RGX
-
 /*************************************************************************/ /*!
- Firmware Trace DebugFS entry
+ Firmware Translated Page Tables DebugFS entry
 */ /**************************************************************************/
 
-static void *_DebugFWTraceCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
+static void _DocumentFwMapping(OSDI_IMPL_ENTRY *psEntry,
+                                                                PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                IMG_UINT32 ui32FwVA,
+                                                                IMG_CPU_PHYADDR sCpuPA,
+                                                                IMG_DEV_PHYADDR sDevPA,
+                                                                IMG_UINT64 ui64PTE)
 {
-       IMG_UINT64 *pui64CurrentPosition = va_arg(va, IMG_UINT64 *);
-       IMG_UINT64 ui64Position = va_arg(va, IMG_UINT64);
-       IMG_UINT64 ui64CurrentPosition = *pui64CurrentPosition;
-
-       (*pui64CurrentPosition)++;
-
-       return (ui64CurrentPosition == ui64Position) ? psDevNode : NULL;
+#if defined(RGX_FEATURE_MIPS_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       {
+               DIPrintf(psEntry, "|    0x%8X   |   "
+                                                 "0x%16" IMG_UINT64_FMTSPECX "   |   "
+                                                 "0x%16" IMG_UINT64_FMTSPECX "   |   "
+                                                 "%s%s%s   |\n",
+                                                 ui32FwVA,
+                                                 (IMG_UINT64) sCpuPA.uiAddr,
+                                                 sDevPA.uiAddr,
+                                                 gapszMipsPermissionPTFlags[RGXMIPSFW_TLB_GET_INHIBIT(ui64PTE)],
+                                                 gapszMipsDirtyGlobalValidPTFlags[RGXMIPSFW_TLB_GET_DGV(ui64PTE)],
+                                                 gapszMipsCoherencyPTFlags[RGXMIPSFW_TLB_GET_COHERENCY(ui64PTE)]);
+       }
+       else
+#endif
+       {
+               /* META and RISCV use a subset of the GPU's virtual address space */
+               DIPrintf(psEntry, "|    0x%8X   |   "
+                                                 "0x%16" IMG_UINT64_FMTSPECX "   |   "
+                                                 "0x%16" IMG_UINT64_FMTSPECX "   |   "
+                                                 "%s%s%s%s%s%s   |\n",
+                                                 ui32FwVA,
+                                                 (IMG_UINT64) sCpuPA.uiAddr,
+                                                 sDevPA.uiAddr,
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_EN)   ? "P" : " ",
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_PM_SRC_EN)          ? "PM" : "  ",
+#if defined(RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_EN)
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_SLC_BYPASS_CTRL_EN) ? "B" : " ",
+#else
+                                                 " ",
+#endif
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_CC_EN)              ? "C" : " ",
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_READ_ONLY_EN)       ? "RO" : "RW",
+                                                 BITMASK_HAS(ui64PTE, RGX_MMUCTRL_PT_DATA_VALID_EN)           ? "V" : " ");
+       }
 }
 
-static void *_DebugFWTraceDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
+static int _FirmwareMappingsDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32FwVA;
+       IMG_UINT32 ui32FwPageSize;
+       IMG_UINT32 ui32OSID;
 
-       if (*pui64Pos == 0)
+       psDeviceNode = DIGetPrivData(psEntry);
+
+       if ((psDeviceNode == NULL) ||
+           (psDeviceNode->pvDevice == NULL) ||
+           (((PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice)->psKernelMMUCtx == NULL))
        {
-               return DI_START_TOKEN;
+               /* The Kernel MMU context containing the Firmware mappings is not initialised */
+               return 0;
        }
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _DebugFWTraceCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
+       psDevInfo = psDeviceNode->pvDevice;
 
-static void _DebugFWTraceDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       PVR_UNREFERENCED_PARAMETER(psEntry);
-       PVR_UNREFERENCED_PARAMETER(pvData);
-}
+       DIPrintf(psEntry, "+-----------------+------------------------+------------------------+--------------+\n"
+                                         "|    Firmware     |           CPU          |         Device         |      PTE     |\n"
+                                         "| Virtual Address |    Physical Address    |    Physical Address    |     Flags    |\n"
+                                         "+-----------------+------------------------+------------------------+              +\n");
 
-static void *_DebugFWTraceDINext(OSDI_IMPL_ENTRY *psEntry,
-                                                                 void *pvData,
-                                                                 IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
+#if defined(RGX_FEATURE_MIPS_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       {
+               DIPrintf(psEntry, "|                                               RI/XI = Read / Execution Inhibit   |\n"
+                                 "|                                               C     = Cache Coherent             |\n"
+                                 "|                                               D     = Dirty Page Table Entry     |\n"
+                                 "|                                               V     = Valid Page Table Entry     |\n"
+                                 "|                                               G     = Global Page Table Entry    |\n"
+                                 "+-----------------+------------------------+------------------------+--------------+\n");
+
+               /* MIPS uses the same page size as the OS */
+               ui32FwPageSize = OSGetPageSize();
+       }
+       else
+#endif
+       {
+               DIPrintf(psEntry, "|                                               P     = Pending Page Table Entry   |\n"
+                                 "|                                               PM    = Parameter Manager Source   |\n"
+                                 "|                                               B     = Bypass SLC                 |\n"
+                                 "|                                               C     = Cache Coherent             |\n"
+                                 "|                                               RW/RO = Device Access Rights       |\n"
+                                 "|                                               V     = Valid Page Table Entry     |\n"
+                                 "+-----------------+------------------------+------------------------+--------------+\n");
+
+               ui32FwPageSize = BIT(RGX_MMUCTRL_PAGE_4KB_RANGE_SHIFT);
+       }
 
-       PVR_UNREFERENCED_PARAMETER(pvData);
+       for (ui32OSID = 0; ui32OSID < RGX_NUM_OS_SUPPORTED; ui32OSID++)
+       {
+               IMG_UINT32 ui32FwHeapBase = (IMG_UINT32) ((RGX_FIRMWARE_RAW_HEAP_BASE +
+                                            (ui32OSID * RGX_FIRMWARE_RAW_HEAP_SIZE)) & UINT_MAX);
+               IMG_UINT32 ui32FwHeapEnd  = ui32FwHeapBase + (IMG_UINT32) (RGX_FIRMWARE_RAW_HEAP_SIZE & UINT_MAX);
 
-       (*pui64Pos)++;
+               DIPrintf(psEntry, "|                                       OS ID %u                                    |\n"
+                                                 "+-----------------+------------------------+------------------------+--------------+\n", ui32OSID);
 
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _DebugFWTraceCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
+               for (ui32FwVA = ui32FwHeapBase;
+                    ui32FwVA < ui32FwHeapEnd;
+                    ui32FwVA += ui32FwPageSize)
+               {
+                       PVRSRV_ERROR eError;
+                       IMG_UINT64 ui64PTE = 0U;
+                       IMG_CPU_PHYADDR sCpuPA = {0U};
+                       IMG_DEV_PHYADDR sDevPA = {0U};
 
-static void _FWTraceDIPrintf(void *pvDumpDebugFile,
-                               const IMG_CHAR *pszFormat, ...)
-{
-       OSDI_IMPL_ENTRY *psEntry = pvDumpDebugFile;
-       IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
-       va_list ArgList;
+                       eError = RGXGetFwMapping(psDevInfo, ui32FwVA, &sCpuPA, &sDevPA, &ui64PTE);
 
-       va_start(ArgList, pszFormat);
-       vsnprintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, pszFormat, ArgList);
-       va_end(ArgList);
-       DIPrintf(psEntry, "%s\n", szBuffer);
-}
+                       if (eError == PVRSRV_OK)
+                       {
+                               _DocumentFwMapping(psEntry, psDevInfo, ui32FwVA, sCpuPA, sDevPA, ui64PTE);
+                       }
+                       else if (eError != PVRSRV_ERROR_DEVICEMEM_NO_MAPPING)
+                       {
+                               PVR_LOG_ERROR(eError, "RGXGetFwMapping");
+                               return -EIO;
+                       }
+               }
 
-static int _DebugFWTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       if (pvData != NULL  &&  pvData != DI_START_TOKEN)
-       {
-               PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+               DIPrintf(psEntry, "+-----------------+------------------------+------------------------+--------------+\n");
 
-               if (psDeviceNode->pvDevice != NULL)
+               if (PVRSRV_VZ_MODE_IS(NATIVE))
                {
-                       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-
-                       RGXDumpFirmwareTrace(_FWTraceDIPrintf, psEntry, psDevInfo);
+                       break;
                }
        }
 
@@ -980,24 +940,10 @@ static int _DebugFWTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 
 #ifdef SUPPORT_FIRMWARE_GCOV
 
-static PVRSRV_RGXDEV_INFO *getPsDevInfo(OSDI_IMPL_ENTRY *psEntry)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-
-       if (psPVRSRVData != NULL)
-       {
-               if (psPVRSRVData->psDeviceNodeList != NULL)
-               {
-                       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*)psPVRSRVData->psDeviceNodeList->pvDevice;
-                       return psDevInfo;
-               }
-       }
-       return NULL;
-}
-
 static void *_FirmwareGcovDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
 {
-       PVRSRV_RGXDEV_INFO *psDevInfo = getPsDevInfo(psEntry);
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
        if (psDevInfo != NULL)
        {
@@ -1014,7 +960,8 @@ static void *_FirmwareGcovDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos
 
 static void _FirmwareGcovDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       PVRSRV_RGXDEV_INFO *psDevInfo = getPsDevInfo(psEntry);
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
        PVR_UNREFERENCED_PARAMETER(pvData);
 
@@ -1039,7 +986,8 @@ static void *_FirmwareGcovDINext(OSDI_IMPL_ENTRY *psEntry,
 
 static int _FirmwareGcovDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       PVRSRV_RGXDEV_INFO *psDevInfo = getPsDevInfo(psEntry);
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
        if (psDevInfo != NULL)
        {
@@ -1056,81 +1004,16 @@ static int _FirmwareGcovDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
  Power monitoring DebugFS entry
 */ /**************************************************************************/
 
-static void *_PowMonCompare_AnyVaCb(PVRSRV_DEVICE_NODE *psDevNode, va_list va)
-{
-       IMG_UINT64 *pui64CurrentPosition = va_arg(va, IMG_UINT64 *);
-       IMG_UINT64 ui64Position = va_arg(va, IMG_UINT64);
-       IMG_UINT64 ui64CurrentPosition = *pui64CurrentPosition;
-
-       (*pui64CurrentPosition)++;
-
-       return (ui64CurrentPosition == ui64Position) ? psDevNode : NULL;
-}
-
-static void *_PowMonTraceDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
-{
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
-
-       if (*pui64Pos == 0)
-       {
-               return DI_START_TOKEN;
-       }
-
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _PowMonCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
-
-static void _PowMonTraceDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       PVR_UNREFERENCED_PARAMETER(psEntry);
-       PVR_UNREFERENCED_PARAMETER(pvData);
-}
-
-static void *_PowMonTraceDINext(OSDI_IMPL_ENTRY *psEntry,
-                                                                void *pvData,
-                                                                IMG_UINT64 *pui64Pos)
+static int _PowMonTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
-       PVRSRV_DATA *psPVRSRVData = DIGetPrivData(psEntry);
-       IMG_UINT64 uiCurrentPosition = 1;
+       PVRSRV_DEVICE_NODE *psDeviceNode = DIGetPrivData(psEntry);
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
        PVR_UNREFERENCED_PARAMETER(pvData);
 
-       (*pui64Pos)++;
-
-       return List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
-                                                                                 _PowMonCompare_AnyVaCb,
-                                                                                 &uiCurrentPosition,
-                                                                                 *pui64Pos);
-}
-
-static void _PowMonTraceDIPrintf(void *pvDumpDebugFile,
-                               const IMG_CHAR *pszFormat, ...)
-{
-       OSDI_IMPL_ENTRY *psEntry = pvDumpDebugFile;
-       IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
-       va_list ArgList;
-
-       va_start(ArgList, pszFormat);
-       vsnprintf(szBuffer, PVR_MAX_DEBUG_MESSAGE_LEN, pszFormat, ArgList);
-       va_end(ArgList);
-       DIPrintf(psEntry, "%s\n", szBuffer);
-}
-
-static int _PowMonTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
-{
-       if (pvData != NULL  &&  pvData != DI_START_TOKEN)
+       if (psDevInfo != NULL)
        {
-               PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
-
-               if (psDeviceNode->pvDevice != NULL)
-               {
-                       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-
-                       RGXDumpPowerMonitoring(_PowMonTraceDIPrintf, psEntry, psDevInfo);
-               }
+               RGXDumpPowerMonitoring(_DumpDebugDIPrintfWrapper, psEntry, psDevInfo);
        }
 
        return 0;
@@ -1151,12 +1034,12 @@ static int _PowMonTraceDIShow(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 
 static IMG_INT64 _RgxRegsSeek(IMG_UINT64 ui64Offset, void *pvData)
 {
-       PVRSRV_DATA *psPVRSRVData = pvData;
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvData;
        PVRSRV_RGXDEV_INFO *psDevInfo;
 
-       PVR_LOG_RETURN_IF_FALSE(psPVRSRVData != NULL, "psPVRSRVData is NULL", -1);
+       PVR_LOG_RETURN_IF_FALSE(psDeviceNode != NULL, "psDeviceNode is NULL", -1);
 
-       psDevInfo = psPVRSRVData->psDeviceNodeList->pvDevice;
+       psDevInfo = psDeviceNode->pvDevice;
 
        PVR_LOG_RETURN_IF_FALSE(ui64Offset <= (psDevInfo->ui32RegSize - 4),
                                "register offset is too big", -1);
@@ -1167,20 +1050,19 @@ static IMG_INT64 _RgxRegsSeek(IMG_UINT64 ui64Offset, void *pvData)
 static IMG_INT64 _RgxRegsRead(IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
                               IMG_UINT64 *pui64Pos, void *pvData)
 {
-       PVRSRV_DATA *psPVRSRVData = pvData;
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvData;
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_UINT64 ui64RegVal = 0;
        PVRSRV_RGXDEV_INFO *psDevInfo;
        IMG_UINT64 ui64CompRes;
 
-       PVR_LOG_RETURN_IF_FALSE(psPVRSRVData != NULL,
-                               "psPVRSRVData is NULL", -ENXIO);
+       PVR_LOG_RETURN_IF_FALSE(psDeviceNode != NULL, "psDeviceNode is NULL", -ENXIO);
        PVR_LOG_RETURN_IF_FALSE(ui64Count == 4 || ui64Count == 8,
                                "wrong RGX register size", -EIO);
        PVR_LOG_RETURN_IF_FALSE(!(*pui64Pos & (ui64Count - 1)),
                                "register read offset isn't aligned", -EINVAL);
 
-       psDevInfo = psPVRSRVData->psDeviceNodeList->pvDevice;
+       psDevInfo = psDeviceNode->pvDevice;
 
        if (*pui64Pos >= SYS_RGX_DEV_UNMAPPED_FW_REG)
        {
@@ -1230,7 +1112,7 @@ static IMG_INT64 _RgxRegsRead(IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
 static IMG_INT64 _RgxRegsWrite(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
                                IMG_UINT64 *pui64Pos, void *pvData)
 {
-       PVRSRV_DATA *psPVRSRVData = pvData;
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*)pvData;
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_UINT64 ui64RegVal = 0;
        PVRSRV_RGXDEV_INFO *psDevInfo;
@@ -1238,14 +1120,13 @@ static IMG_INT64 _RgxRegsWrite(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
        /* ignore the '\0' character */
        ui64Count -= 1;
 
-       PVR_LOG_RETURN_IF_FALSE(psPVRSRVData != NULL,
-                               "psPVRSRVData == NULL", -ENXIO);
+       PVR_LOG_RETURN_IF_FALSE(psDeviceNode != NULL, "psDeviceNode is NULL", -ENXIO);
        PVR_LOG_RETURN_IF_FALSE(ui64Count == 4 || ui64Count == 8,
                                "wrong RGX register size", -EIO);
        PVR_LOG_RETURN_IF_FALSE(!(*pui64Pos & (ui64Count - 1)),
                                "register read offset isn't aligned", -EINVAL);
 
-       psDevInfo = psPVRSRVData->psDeviceNodeList->pvDevice;
+       psDevInfo = psDeviceNode->pvDevice;
 
        if (*pui64Pos >= SYS_RGX_DEV_UNMAPPED_FW_REG)
        {
@@ -1292,6 +1173,45 @@ static IMG_INT64 _RgxRegsWrite(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
 
 #endif /* SUPPORT_VALIDATION */
 
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+#define RISCV_DMI_SIZE  (8U)
+
+static IMG_INT64 _RiscvDmiRead(IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
+                               IMG_UINT64 *pui64Pos, void *pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+       PVRSRV_DEVICE_DEBUG_INFO *psDebugInfo = &psDeviceNode->sDebugInfo;
+
+       ui64Count = MIN(RISCV_DMI_SIZE, ui64Count);
+       memcpy(pcBuffer, &psDebugInfo->ui64RiscvDmi, ui64Count);
+
+       return ui64Count;
+}
+
+static IMG_INT64 _RiscvDmiWrite(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
+                                IMG_UINT64 *pui64Pos, void *pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_DEVICE_DEBUG_INFO *psDebugInfo = &psDeviceNode->sDebugInfo;
+
+       if (psDevInfo == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: devinfo is NULL", __func__));
+               return 0;
+       }
+
+       ui64Count -= 1; /* Drop `\0` */
+       ui64Count = MIN(RISCV_DMI_SIZE, ui64Count);
+
+       memcpy(&psDebugInfo->ui64RiscvDmi, pcBuffer, ui64Count);
+
+       RGXRiscvDmiOp(psDevInfo, &psDebugInfo->ui64RiscvDmi);
+
+       return ui64Count;
+}
+#endif
+
 #endif /* SUPPORT_RGX */
 
 #ifdef SUPPORT_VALIDATION
@@ -1409,7 +1329,7 @@ static IMG_INT64 DebugLevelSet(const IMG_CHAR *pcBuffer, IMG_UINT64 ui64Count,
 }
 #endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
 
-PVRSRV_ERROR DebugCommonInit(void)
+PVRSRV_ERROR DebugCommonInitDriver(void)
 {
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_ERROR eError;
@@ -1452,22 +1372,106 @@ PVRSRV_ERROR DebugCommonInit(void)
                        .pfnStop = _DebugStatusDIStop,
                        .pfnNext = _DebugStatusDINext,
                        .pfnShow = _DebugStatusDIShow,
-                       .pfnWrite = DebugStatusSet
+                       .pfnWrite = DebugStatusSet,
+                       //'K' expected + Null terminator
+                       .ui32WriteLenMax= ((1U)+1U)
                };
                eError = DICreateEntry("status", NULL, &sIterator, psPVRSRVData,
                                       DI_ENTRY_TYPE_GENERIC, &gpsStatusDIEntry);
                PVR_GOTO_IF_ERROR(eError, return_error_);
        }
 
+#ifdef SUPPORT_VALIDATION
+       {
+               DI_ITERATOR_CB sIterator = {
+                       .pfnShow = TestMemLeakDIShow,
+                       .pfnWrite = TestMemLeakDISet,
+                       //Function only allows max 15 chars + Null terminator
+                       .ui32WriteLenMax = ((15U)+1U)
+               };
+               eError = DICreateEntry("test_memleak", NULL, &sIterator, psPVRSRVData,
+                                      DI_ENTRY_TYPE_GENERIC, &gpsTestMemLeakDIEntry);
+               PVR_GOTO_IF_ERROR(eError, return_error_);
+       }
+#endif /* SUPPORT_VALIDATION */
+
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
        {
                DI_ITERATOR_CB sIterator = {
-                       .pfnStart = _DebugDumpDebugDIStart,
-                       .pfnStop = _DebugDumpDebugDIStop,
-                       .pfnNext = _DebugDumpDebugDINext,
-                       .pfnShow = _DebugDumpDebugDIShow
+                       .pfnShow = DebugLevelDIShow,
+                       .pfnWrite = DebugLevelSet,
+                       //Max value of 255(3 char) + Null terminator
+                       .ui32WriteLenMax =((3U)+1U)
                };
-               eError = DICreateEntry("debug_dump", NULL, &sIterator, psPVRSRVData,
-                                      DI_ENTRY_TYPE_GENERIC, &gpsDumpDebugDIEntry);
+               eError = DICreateEntry("debug_level", NULL, &sIterator, NULL,
+                                      DI_ENTRY_TYPE_GENERIC, &gpsDebugLevelDIEntry);
+               PVR_GOTO_IF_ERROR(eError, return_error_);
+       }
+#endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
+
+       return PVRSRV_OK;
+
+return_error_:
+       DebugCommonDeInitDriver();
+
+       return eError;
+}
+
+void DebugCommonDeInitDriver(void)
+{
+#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
+       if (gpsDebugLevelDIEntry != NULL)
+       {
+               DIDestroyEntry(gpsDebugLevelDIEntry);
+       }
+#endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
+
+#if defined(SUPPORT_RGX) && !defined(NO_HARDWARE)
+       if (ghGpuUtilUserDebugFS != NULL)
+       {
+               SORgxGpuUtilStatsUnregister(ghGpuUtilUserDebugFS);
+               ghGpuUtilUserDebugFS = NULL;
+       }
+#endif /* defined(SUPPORT_RGX) && !defined(NO_HARDWARE) */
+
+#ifdef SUPPORT_VALIDATION
+       if (gpsTestMemLeakDIEntry != NULL)
+       {
+               DIDestroyEntry(gpsTestMemLeakDIEntry);
+       }
+#endif /* SUPPORT_VALIDATION */
+
+       if (gpsStatusDIEntry != NULL)
+       {
+               DIDestroyEntry(gpsStatusDIEntry);
+       }
+
+       if (gpsVersionDIEntry != NULL)
+       {
+               DIDestroyEntry(gpsVersionDIEntry);
+       }
+}
+
+PVRSRV_ERROR DebugCommonInitDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_DEVICE_DEBUG_INFO *psDebugInfo = &psDeviceNode->sDebugInfo;
+       PVRSRV_ERROR eError;
+
+       {
+               IMG_CHAR pszDeviceId[sizeof("gpu4294967296")];
+
+               OSSNPrintf(pszDeviceId, sizeof(pszDeviceId), "gpu%02d",
+                          psDeviceNode->sDevId.ui32InternalID);
+
+               eError = DICreateGroup(pszDeviceId, NULL, &psDebugInfo->psGroup);
+               PVR_GOTO_IF_ERROR(eError, return_error_);
+       }
+
+       {
+               DI_ITERATOR_CB sIterator = {.pfnShow = _DebugDumpDebugDIShow};
+               eError = DICreateEntry("debug_dump", psDebugInfo->psGroup, &sIterator,
+                                      psDeviceNode, DI_ENTRY_TYPE_GENERIC,
+                                      &psDebugInfo->psDumpDebugEntry);
                PVR_GOTO_IF_ERROR(eError, return_error_);
        }
 
@@ -1475,181 +1479,168 @@ PVRSRV_ERROR DebugCommonInit(void)
        if (! PVRSRV_VZ_MODE_IS(GUEST))
        {
                {
-                       DI_ITERATOR_CB sIterator = {
-                               .pfnStart = _DebugFWTraceDIStart,
-                               .pfnStop = _DebugFWTraceDIStop,
-                               .pfnNext = _DebugFWTraceDINext,
-                               .pfnShow = _DebugFWTraceDIShow
-                       };
-                       eError = DICreateEntry("firmware_trace", NULL, &sIterator,
-                                              psPVRSRVData, DI_ENTRY_TYPE_GENERIC,
-                                              &gpsFWTraceDIEntry);
+                       DI_ITERATOR_CB sIterator = {.pfnShow = _DebugFWTraceDIShow};
+                       eError = DICreateEntry("firmware_trace", psDebugInfo->psGroup, &sIterator,
+                                              psDeviceNode, DI_ENTRY_TYPE_GENERIC,
+                                              &psDebugInfo->psFWTraceEntry);
                        PVR_GOTO_IF_ERROR(eError, return_error_);
                }
 
-#ifdef SUPPORT_POWER_VALIDATION_VIA_DEBUGFS
+#ifdef SUPPORT_FIRMWARE_GCOV
                {
                        DI_ITERATOR_CB sIterator = {
-                               .pfnStart = _PowMonTraceDIStart,
-                               .pfnStop = _PowMonTraceDIStop,
-                               .pfnNext = _PowMonTraceDINext,
-                               .pfnShow = _PowMonTraceDIShow
+                               .pfnStart = _FirmwareGcovDIStart,
+                               .pfnStop = _FirmwareGcovDIStop,
+                               .pfnNext = _FirmwareGcovDINext,
+                               .pfnShow = _FirmwareGcovDIShow
                        };
-                       eError = DICreateEntry("power_mon", NULL, &sIterator, psPVRSRVData,
-                                              DI_ENTRY_TYPE_GENERIC, &gpsPowMonDIEntry);
+
+                       eError = DICreateEntry("firmware_gcov", psDebugInfo->psGroup, &sIterator,
+                                              psDeviceNode, DI_ENTRY_TYPE_GENERIC,
+                                              &psDebugInfo->psFWGCOVEntry);
                        PVR_GOTO_IF_ERROR(eError, return_error_);
                }
-#endif /* SUPPORT_POWER_VALIDATION_VIA_DEBUGFS */
-       }
-
-#ifdef SUPPORT_FIRMWARE_GCOV
-       {
-               DI_ITERATOR_CB sIterator = {
-                       .pfnStart = _FirmwareGcovDIStart,
-                       .pfnStop = _FirmwareGcovDIStop,
-                       .pfnNext = _FirmwareGcovDINext,
-                       .pfnShow = _FirmwareGcovDIShow
-               };
-
-               eError = DICreateEntry("firmware_gcov", NULL, &sIterator, psPVRSRVData,
-                                      DI_ENTRY_TYPE_GENERIC, &gpsFirmwareGcovDIEntry);
-               PVR_GOTO_IF_ERROR(eError, return_error_);
-       }
 #endif /* SUPPORT_FIRMWARE_GCOV */
 
-#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
-       {
-               DI_ITERATOR_CB sIterator = {
-                       .pfnStart = _DebugPowerDataDIStart,
-                       .pfnStop = _DebugPowerDataDIStop,
-                       .pfnNext = _DebugPowerDataDINext,
-                       .pfnShow = _DebugPowerDataDIShow,
-                       .pfnWrite = PowerDataSet
-               };
-               eError = DICreateEntry("power_data", NULL, &sIterator, psPVRSRVData,
-                                      DI_ENTRY_TYPE_GENERIC, &gpsPowerDataDIEntry);
-               PVR_GOTO_IF_ERROR(eError, return_error_);
-       }
-#endif /* SUPPORT_POWER_SAMPLING_VIA_DEBUGFS */
+               {
+                       DI_ITERATOR_CB sIterator = {.pfnShow = _FirmwareMappingsDIShow};
+                       eError = DICreateEntry("firmware_mappings", psDebugInfo->psGroup, &sIterator,
+                                              psDeviceNode, DI_ENTRY_TYPE_GENERIC,
+                                              &psDebugInfo->psFWMappingsEntry);
+                       PVR_GOTO_IF_ERROR(eError, return_error_);
+               }
 
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+               {
+                       DI_ITERATOR_CB sIterator = {
+                               .pfnRead = _RiscvDmiRead,
+                               .pfnWrite = _RiscvDmiWrite,
+                               .ui32WriteLenMax = ((RISCV_DMI_SIZE)+1U)
+                       };
+                       eError = DICreateEntry("riscv_dmi", psDebugInfo->psGroup, &sIterator, psDeviceNode,
+                                              DI_ENTRY_TYPE_RANDOM_ACCESS, &psDebugInfo->psRiscvDmiDIEntry);
+                       PVR_GOTO_IF_ERROR(eError, return_error_);
+                       psDebugInfo->ui64RiscvDmi = 0ULL;
+               }
+#endif /* SUPPORT_VALIDATION || SUPPORT_RISCV_GDB */
+       }
 #ifdef SUPPORT_VALIDATION
        {
                DI_ITERATOR_CB sIterator = {
                        .pfnSeek = _RgxRegsSeek,
                        .pfnRead = _RgxRegsRead,
-                       .pfnWrite = _RgxRegsWrite
+                       .pfnWrite = _RgxRegsWrite,
+                       //Max size of input binary data is 4 bytes (UINT32) or 8 bytes (UINT64)
+                       .ui32WriteLenMax = ((8U)+1U)
                };
-               eError = DICreateEntry("rgxregs", NULL, &sIterator, psPVRSRVData,
-                                      DI_ENTRY_TYPE_RANDOM_ACCESS, &gpsRGXRegsDIEntry);
+               eError = DICreateEntry("rgxregs", psDebugInfo->psGroup, &sIterator, psDeviceNode,
+                                      DI_ENTRY_TYPE_RANDOM_ACCESS, &psDebugInfo->psRGXRegsEntry);
 
                PVR_GOTO_IF_ERROR(eError, return_error_);
        }
 #endif /* SUPPORT_VALIDATION */
-#endif /* SUPPORT_RGX */
 
-#ifdef SUPPORT_VALIDATION
+#ifdef SUPPORT_POWER_VALIDATION_VIA_DEBUGFS
+       if (! PVRSRV_VZ_MODE_IS(GUEST))
        {
                DI_ITERATOR_CB sIterator = {
-                       .pfnShow = TestMemLeakDIShow,
-                       .pfnWrite = TestMemLeakDISet
+                       .pfnShow = _PowMonTraceDIShow
                };
-               eError = DICreateEntry("test_memleak", NULL, &sIterator, psPVRSRVData,
-                                      DI_ENTRY_TYPE_GENERIC, &gpsTestMemLeakDIEntry);
+               eError = DICreateEntry("power_mon", psDebugInfo->psGroup, &sIterator, psDeviceNode,
+                                                          DI_ENTRY_TYPE_GENERIC, &psDebugInfo->psPowMonEntry);
                PVR_GOTO_IF_ERROR(eError, return_error_);
        }
-#endif /* SUPPORT_VALIDATION */
-
-#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
+#endif /* SUPPORT_POWER_VALIDATION_VIA_DEBUGFS */
+#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
        {
                DI_ITERATOR_CB sIterator = {
-                       .pfnShow = DebugLevelDIShow,
-                       .pfnWrite = DebugLevelSet
+                       .pfnShow = _DebugPowerDataDIShow,
+                       .pfnWrite = PowerDataSet,
+                       //Expects '0' or '1' plus Null terminator
+                       .ui32WriteLenMax = ((1U)+1U)
                };
-               eError = DICreateEntry("debug_level", NULL, &sIterator, NULL,
-                                      DI_ENTRY_TYPE_GENERIC, &gpsDebugLevelDIEntry);
+               eError = DICreateEntry("power_data", psDebugInfo->psGroup, &sIterator, psDeviceNode,
+                                      DI_ENTRY_TYPE_GENERIC, &psDebugInfo->psPowerDataEntry);
                PVR_GOTO_IF_ERROR(eError, return_error_);
        }
-#endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
+#endif /* SUPPORT_POWER_SAMPLING_VIA_DEBUGFS */
+#endif /* SUPPORT_RGX */
 
        return PVRSRV_OK;
 
 return_error_:
-       DebugCommonDeInit();
+       DebugCommonDeInitDevice(psDeviceNode);
 
        return eError;
 }
 
-void DebugCommonDeInit(void)
+void DebugCommonDeInitDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-#if defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON)
-       if (gpsDebugLevelDIEntry != NULL)
-       {
-               DIDestroyEntry(gpsDebugLevelDIEntry);
-       }
-#endif /* defined(DEBUG) || defined(PVR_DPF_ADHOC_DEBUG_ON) */
+       PVRSRV_DEVICE_DEBUG_INFO *psDebugInfo = &psDeviceNode->sDebugInfo;
 
-#if defined(SUPPORT_RGX) && !defined(NO_HARDWARE)
-       if (ghGpuUtilUserDebugFS != NULL)
-       {
-               SORgxGpuUtilStatsUnregister(ghGpuUtilUserDebugFS);
-               ghGpuUtilUserDebugFS = NULL;
-       }
-#endif /* defined(SUPPORT_RGX) && !defined(NO_HARDWARE) */
-
-#ifdef SUPPORT_RGX
-       if (gpsFWTraceDIEntry != NULL)
+#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
+       if (psDebugInfo->psPowerDataEntry != NULL)
        {
-               DIDestroyEntry(gpsFWTraceDIEntry);
+               DIDestroyEntry(psDebugInfo->psPowerDataEntry);
+               psDebugInfo->psPowerDataEntry = NULL;
        }
+#endif /* SUPPORT_POWER_SAMPLING_VIA_DEBUGFS */
 
 #ifdef SUPPORT_POWER_VALIDATION_VIA_DEBUGFS
-       if (gpsPowMonDIEntry != NULL)
+       if (psDebugInfo->psPowMonEntry != NULL)
        {
-               DIDestroyEntry(gpsPowMonDIEntry);
+               DIDestroyEntry(psDebugInfo->psPowMonEntry);
+               psDebugInfo->psPowMonEntry = NULL;
        }
 #endif /* SUPPORT_POWER_VALIDATION_VIA_DEBUGFS */
 
-#ifdef SUPPORT_FIRMWARE_GCOV
-       if (gpsFirmwareGcovDIEntry != NULL)
+#ifdef SUPPORT_VALIDATION
+       if (psDebugInfo->psRGXRegsEntry != NULL)
        {
-               DIDestroyEntry(gpsFirmwareGcovDIEntry);
+               DIDestroyEntry(psDebugInfo->psRGXRegsEntry);
+               psDebugInfo->psRGXRegsEntry = NULL;
        }
-#endif /* SUPPORT_FIRMWARE_GCOV */
+#endif /* SUPPORT_VALIDATION */
 
-#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
-       if (gpsPowerDataDIEntry != NULL)
+#ifdef SUPPORT_RGX
+       if (psDebugInfo->psFWTraceEntry != NULL)
        {
-               DIDestroyEntry(gpsPowerDataDIEntry);
+               DIDestroyEntry(psDebugInfo->psFWTraceEntry);
+               psDebugInfo->psFWTraceEntry = NULL;
        }
-#endif /* SUPPORT_POWER_SAMPLING_VIA_DEBUGFS */
 
-#ifdef SUPPORT_VALIDATION
-       if (gpsRGXRegsDIEntry != NULL)
+#ifdef SUPPORT_FIRMWARE_GCOV
+       if (psDebugInfo->psFWGCOVEntry != NULL)
        {
-               DIDestroyEntry(gpsRGXRegsDIEntry);
+               DIDestroyEntry(psDebugInfo->psFWGCOVEntry);
+               psDebugInfo->psFWGCOVEntry = NULL;
        }
-#endif /* SUPPORT_VALIDATION */
-#endif /* SUPPORT_RGX */
+#endif
 
-#ifdef SUPPORT_VALIDATION
-       if (gpsTestMemLeakDIEntry != NULL)
+       if (psDebugInfo->psFWMappingsEntry != NULL)
        {
-               DIDestroyEntry(gpsTestMemLeakDIEntry);
+               DIDestroyEntry(psDebugInfo->psFWMappingsEntry);
+               psDebugInfo->psFWMappingsEntry = NULL;
        }
-#endif /* SUPPORT_VALIDATION */
 
-       if (gpsDumpDebugDIEntry != NULL)
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+       if (psDebugInfo->psRiscvDmiDIEntry != NULL)
        {
-               DIDestroyEntry(gpsDumpDebugDIEntry);
+               DIDestroyEntry(psDebugInfo->psRiscvDmiDIEntry);
+               psDebugInfo->psRiscvDmiDIEntry = NULL;
        }
+#endif
+#endif /* SUPPORT_RGX */
 
-       if (gpsStatusDIEntry != NULL)
+       if (psDebugInfo->psDumpDebugEntry != NULL)
        {
-               DIDestroyEntry(gpsStatusDIEntry);
+               DIDestroyEntry(psDebugInfo->psDumpDebugEntry);
+               psDebugInfo->psDumpDebugEntry = NULL;
        }
 
-       if (gpsVersionDIEntry != NULL)
+       if (psDebugInfo->psGroup != NULL)
        {
-               DIDestroyEntry(gpsVersionDIEntry);
+               DIDestroyGroup(psDebugInfo->psGroup);
+               psDebugInfo->psGroup = NULL;
        }
 }
index b94ba21..412a51b 100644 (file)
@@ -299,10 +299,12 @@ static IMG_UINT64 TimeStampUnpack(COMMAND_TIMESTAMP *psTimeStamp)
 
 #if defined(PDUMP)
 
-static void EmitPDumpAllocation(IMG_UINT32 ui32AllocationIndex,
-                                       RECORD_ALLOCATION *psAlloc)
+static void EmitPDumpAllocation(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                IMG_UINT32 ui32AllocationIndex,
+                                RECORD_ALLOCATION *psAlloc)
 {
-       PDUMPCOMMENT("[SrvPFD] Allocation: %u"
+       PDUMPCOMMENT(psDeviceNode,
+                       "[SrvPFD] Allocation: %u"
                        " Addr: " IMG_DEV_VIRTADDR_FMTSPEC
                        " Size: " IMG_DEVMEM_SIZE_FMTSPEC
                        " Page size: %u"
@@ -318,8 +320,9 @@ static void EmitPDumpAllocation(IMG_UINT32 ui32AllocationIndex,
                        psAlloc->szName);
 }
 
-static void EmitPDumpMapUnmapAll(COMMAND_TYPE eType,
-                                       IMG_UINT32 ui32AllocationIndex)
+static void EmitPDumpMapUnmapAll(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 COMMAND_TYPE eType,
+                                 IMG_UINT32 ui32AllocationIndex)
 {
        const IMG_CHAR *pszOpName;
 
@@ -338,12 +341,14 @@ static void EmitPDumpMapUnmapAll(COMMAND_TYPE eType,
 
        }
 
-       PDUMPCOMMENT("[SrvPFD] Op: %s Allocation: %u",
-                                                               pszOpName,
-                                                               ui32AllocationIndex);
+       PDUMPCOMMENT(psDeviceNode,
+                    "[SrvPFD] Op: %s Allocation: %u",
+                    pszOpName,
+                    ui32AllocationIndex);
 }
 
-static void EmitPDumpMapUnmapRange(COMMAND_TYPE eType,
+static void EmitPDumpMapUnmapRange(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       COMMAND_TYPE eType,
                                        IMG_UINT32 ui32AllocationIndex,
                                        IMG_UINT32 ui32StartPage,
                                        IMG_UINT32 ui32Count)
@@ -364,11 +369,12 @@ static void EmitPDumpMapUnmapRange(COMMAND_TYPE eType,
                        return;
        }
 
-       PDUMPCOMMENT("[SrvPFD] Op: %s Allocation: %u Start Page: %u Count: %u",
-                                                                       pszOpName,
-                                                                       ui32AllocationIndex,
-                                                                       ui32StartPage,
-                                                                       ui32Count);
+       PDUMPCOMMENT(psDeviceNode,
+                 "[SrvPFD] Op: %s Allocation: %u Start Page: %u Count: %u",
+                 pszOpName,
+                 ui32AllocationIndex,
+                 ui32StartPage,
+                 ui32Count);
 }
 
 #endif
@@ -390,7 +396,8 @@ static void InsertTimeStampCommand(IMG_UINT64 ui64Now)
 /* InsertMapAllCommand:
  * Insert a "MAP_ALL" command for the given allocation into the circular buffer
  */
-static void InsertMapAllCommand(IMG_UINT32 ui32AllocIndex)
+static void InsertMapAllCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                IMG_UINT32 ui32AllocIndex)
 {
        COMMAND_WRAPPER *psCommand;
 
@@ -400,14 +407,17 @@ static void InsertMapAllCommand(IMG_UINT32 ui32AllocIndex)
        psCommand->u.sMapAll.uiAllocIndex = ui32AllocIndex;
 
 #if defined(PDUMP)
-       EmitPDumpMapUnmapAll(COMMAND_TYPE_MAP_ALL, ui32AllocIndex);
+       EmitPDumpMapUnmapAll(psDeviceNode, COMMAND_TYPE_MAP_ALL, ui32AllocIndex);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 }
 
 /* InsertUnmapAllCommand:
  * Insert a "UNMAP_ALL" command for the given allocation into the circular buffer
  */
-static void InsertUnmapAllCommand(IMG_UINT32 ui32AllocIndex)
+static void InsertUnmapAllCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_UINT32 ui32AllocIndex)
 {
        COMMAND_WRAPPER *psCommand;
 
@@ -417,7 +427,9 @@ static void InsertUnmapAllCommand(IMG_UINT32 ui32AllocIndex)
        psCommand->u.sUnmapAll.uiAllocIndex = ui32AllocIndex;
 
 #if defined(PDUMP)
-       EmitPDumpMapUnmapAll(COMMAND_TYPE_UNMAP_ALL, ui32AllocIndex);
+       EmitPDumpMapUnmapAll(psDeviceNode, COMMAND_TYPE_UNMAP_ALL, ui32AllocIndex);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 }
 
@@ -473,7 +485,8 @@ static void MapRangeUnpack(COMMAND_MAP_RANGE *psMapRange,
  * Insert a MAP_RANGE command into the circular buffer with the given
  * StartPage and Count values.
  */
-static void InsertMapRangeCommand(IMG_UINT32 ui32AllocIndex,
+static void InsertMapRangeCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_UINT32 ui32AllocIndex,
                                                IMG_UINT32 ui32StartPage,
                                                IMG_UINT32 ui32Count)
 {
@@ -487,10 +500,13 @@ static void InsertMapRangeCommand(IMG_UINT32 ui32AllocIndex,
        MapRangePack(&psCommand->u.sMapRange, ui32StartPage, ui32Count);
 
 #if defined(PDUMP)
-       EmitPDumpMapUnmapRange(COMMAND_TYPE_MAP_RANGE,
-                                                       ui32AllocIndex,
-                                                       ui32StartPage,
-                                                       ui32Count);
+       EmitPDumpMapUnmapRange(psDeviceNode,
+                              COMMAND_TYPE_MAP_RANGE,
+                              ui32AllocIndex,
+                              ui32StartPage,
+                              ui32Count);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 }
 
@@ -498,7 +514,8 @@ static void InsertMapRangeCommand(IMG_UINT32 ui32AllocIndex,
  * Insert a UNMAP_RANGE command into the circular buffer with the given
  * StartPage and Count values.
  */
-static void InsertUnmapRangeCommand(IMG_UINT32 ui32AllocIndex,
+static void InsertUnmapRangeCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_UINT32 ui32AllocIndex,
                                                IMG_UINT32 ui32StartPage,
                                                IMG_UINT32 ui32Count)
 {
@@ -512,10 +529,13 @@ static void InsertUnmapRangeCommand(IMG_UINT32 ui32AllocIndex,
        MapRangePack(&psCommand->u.sMapRange, ui32StartPage, ui32Count);
 
 #if defined(PDUMP)
-       EmitPDumpMapUnmapRange(COMMAND_TYPE_UNMAP_RANGE,
-                                                       ui32AllocIndex,
-                                                       ui32StartPage,
-                                                       ui32Count);
+       EmitPDumpMapUnmapRange(psDeviceNode,
+                              COMMAND_TYPE_UNMAP_RANGE,
+                              ui32AllocIndex,
+                              ui32StartPage,
+                              ui32Count);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 }
 
@@ -668,7 +688,8 @@ static void InitialiseAllocation(RECORD_ALLOCATION *psAlloc,
  * Creates a new allocation with the given properties then outputs the
  * index of the allocation
  */
-static PVRSRV_ERROR CreateAllocation(const IMG_CHAR *pszName,
+static PVRSRV_ERROR CreateAllocation(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       const IMG_CHAR *pszName,
                                                        IMG_UINT64 ui64Serial,
                                                        IMG_PID uiPID,
                                                        IMG_DEV_VIRTADDR sDevVAddr,
@@ -698,7 +719,9 @@ static PVRSRV_ERROR CreateAllocation(const IMG_CHAR *pszName,
        *puiAllocationIndex = ui32Alloc;
 
 #if defined(PDUMP)
-       EmitPDumpAllocation(ui32Alloc, psAlloc);
+       EmitPDumpAllocation(psDeviceNode, ui32Alloc, psAlloc);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 
        return PVRSRV_OK;
@@ -733,7 +756,8 @@ static IMG_BOOL MatchAllocation(IMG_UINT32 ui32AllocationIndex,
  * this function will look for an existing record of this allocation and
  * create the allocation if there is no existing record
  */
-static PVRSRV_ERROR FindOrCreateAllocation(IMG_UINT32 ui32AllocationIndexHint,
+static PVRSRV_ERROR FindOrCreateAllocation(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_UINT32 ui32AllocationIndexHint,
                                                        IMG_UINT64 ui64Serial,
                                                        IMG_DEV_VIRTADDR sDevVAddr,
                                                        IMG_DEVMEM_SIZE_T uiSize,
@@ -773,7 +797,8 @@ static PVRSRV_ERROR FindOrCreateAllocation(IMG_UINT32 ui32AllocationIndexHint,
        /* if there is no record of the allocation then we
         * create it now
         */
-       eError = CreateAllocation(pszName,
+       eError = CreateAllocation(psDeviceNode,
+                                       pszName,
                                        ui64Serial,
                                        uiPID,
                                        sDevVAddr,
@@ -859,15 +884,17 @@ static void GenerateMapUnmapCommandsForSparsePMR(PMR *psPMR,
                        {
                                if (bMap)
                                {
-                                       InsertMapRangeCommand(ui32AllocIndex,
-                                                                               ui32CurrentStart,
-                                                                               ui32RunCount);
+                                       InsertMapRangeCommand(PMR_DeviceNode(psPMR),
+                                                             ui32AllocIndex,
+                                                             ui32CurrentStart,
+                                                             ui32RunCount);
                                }
                                else
                                {
-                                       InsertUnmapRangeCommand(ui32AllocIndex,
-                                                                               ui32CurrentStart,
-                                                                               ui32RunCount);
+                                       InsertUnmapRangeCommand(PMR_DeviceNode(psPMR),
+                                                               ui32AllocIndex,
+                                                               ui32CurrentStart,
+                                                               ui32RunCount);
                                }
 
                                ui32DonePages += ui32RunCount;
@@ -896,7 +923,8 @@ static void GenerateMapUnmapCommandsForSparsePMR(PMR *psPMR,
  * This function goes through every page in the list and looks for
  * virtually contiguous ranges to record as being mapped or unmapped.
  */
-static void GenerateMapUnmapCommandsForChangeList(IMG_UINT32 ui32NumPages,
+static void GenerateMapUnmapCommandsForChangeList(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_UINT32 ui32NumPages,
                                                        IMG_UINT32 *pui32PageList,
                                                        IMG_UINT32 ui32AllocIndex,
                                                        IMG_BOOL bMap)
@@ -927,13 +955,15 @@ static void GenerateMapUnmapCommandsForChangeList(IMG_UINT32 ui32NumPages,
                {
                        if (bMap)
                        {
-                               InsertMapRangeCommand(ui32AllocIndex,
+                               InsertMapRangeCommand(psDeviceNode,
+                                                                       ui32AllocIndex,
                                                                        ui32CurrentStart,
                                                                        ui32RunCount);
                        }
                        else
                        {
-                               InsertUnmapRangeCommand(ui32AllocIndex,
+                               InsertUnmapRangeCommand(psDeviceNode,
+                                                                       ui32AllocIndex,
                                                                        ui32CurrentStart,
                                                                        ui32RunCount);
                        }
@@ -987,7 +1017,8 @@ PVRSRV_ERROR DevicememHistoryMapKM(PMR *psPMR,
 
        DevicememHistoryLock();
 
-       eError = FindOrCreateAllocation(ui32AllocationIndex,
+       eError = FindOrCreateAllocation(PMR_DeviceNode(psPMR),
+                                               ui32AllocationIndex,
                                                ui64Serial,
                                                sDevVAddr,
                                                uiSize,
@@ -1014,7 +1045,7 @@ PVRSRV_ERROR DevicememHistoryMapKM(PMR *psPMR,
 
        if (!bSparse)
        {
-               InsertMapAllCommand(ui32AllocationIndex);
+               InsertMapAllCommand(PMR_DeviceNode(psPMR), ui32AllocationIndex);
        }
        else
        {
@@ -1033,7 +1064,8 @@ out_unlock:
        return eError;
 }
 
-static void VRangeInsertMapUnmapCommands(IMG_BOOL bMap,
+static void VRangeInsertMapUnmapCommands(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_BOOL bMap,
                                                        IMG_UINT32 ui32AllocationIndex,
                                                        IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                        IMG_UINT32 ui32StartPage,
@@ -1058,13 +1090,15 @@ static void VRangeInsertMapUnmapCommands(IMG_BOOL bMap,
 
                if (bMap)
                {
-                       InsertMapRangeCommand(ui32AllocationIndex,
+                       InsertMapRangeCommand(psDeviceNode,
+                                                               ui32AllocationIndex,
                                                                ui32StartPage,
                                                                ui32PagesToAdd);
                }
                else
                {
-                       InsertUnmapRangeCommand(ui32AllocationIndex,
+                       InsertUnmapRangeCommand(psDeviceNode,
+                                                               ui32AllocationIndex,
                                                                ui32StartPage,
                                                                ui32PagesToAdd);
                }
@@ -1074,7 +1108,9 @@ static void VRangeInsertMapUnmapCommands(IMG_BOOL bMap,
        }
 }
 
-PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+PVRSRV_ERROR DevicememHistoryMapVRangeKM(CONNECTION_DATA *psConnection,
+                                               PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                IMG_UINT32 ui32StartPage,
                                                IMG_UINT32 ui32NumPages,
                                                IMG_DEVMEM_SIZE_T uiAllocSize,
@@ -1087,6 +1123,8 @@ PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
        PVRSRV_ERROR eError;
        IMG_BOOL bCreated;
 
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
        if ((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
                !CHECK_ALLOC_INDEX(ui32AllocationIndex))
        {
@@ -1098,7 +1136,8 @@ PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
 
        DevicememHistoryLock();
 
-       eError = FindOrCreateAllocation(ui32AllocationIndex,
+       eError = FindOrCreateAllocation(psDeviceNode,
+                                               ui32AllocationIndex,
                                                0,
                                                sBaseDevVAddr,
                                                uiAllocSize,
@@ -1123,7 +1162,8 @@ PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
                goto out_unlock;
        }
 
-       VRangeInsertMapUnmapCommands(IMG_TRUE,
+       VRangeInsertMapUnmapCommands(psDeviceNode,
+                                               IMG_TRUE,
                                                ui32AllocationIndex,
                                                sBaseDevVAddr,
                                                ui32StartPage,
@@ -1139,7 +1179,9 @@ out_unlock:
 
 }
 
-PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(CONNECTION_DATA *psConnection,
+                                               PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                IMG_UINT32 ui32StartPage,
                                                IMG_UINT32 ui32NumPages,
                                                IMG_DEVMEM_SIZE_T uiAllocSize,
@@ -1152,6 +1194,8 @@ PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
        PVRSRV_ERROR eError;
        IMG_BOOL bCreated;
 
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
        if ((ui32AllocationIndex != DEVICEMEM_HISTORY_ALLOC_INDEX_NONE) &&
                !CHECK_ALLOC_INDEX(ui32AllocationIndex))
        {
@@ -1163,7 +1207,8 @@ PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
 
        DevicememHistoryLock();
 
-       eError = FindOrCreateAllocation(ui32AllocationIndex,
+       eError = FindOrCreateAllocation(psDeviceNode,
+                                               ui32AllocationIndex,
                                                0,
                                                sBaseDevVAddr,
                                                uiAllocSize,
@@ -1188,7 +1233,8 @@ PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
                goto out_unlock;
        }
 
-       VRangeInsertMapUnmapCommands(IMG_FALSE,
+       VRangeInsertMapUnmapCommands(psDeviceNode,
+                                               IMG_FALSE,
                                                ui32AllocationIndex,
                                                sBaseDevVAddr,
                                                ui32StartPage,
@@ -1248,7 +1294,8 @@ PVRSRV_ERROR DevicememHistoryUnmapKM(PMR *psPMR,
 
        DevicememHistoryLock();
 
-       eError = FindOrCreateAllocation(ui32AllocationIndex,
+       eError = FindOrCreateAllocation(PMR_DeviceNode(psPMR),
+                                               ui32AllocationIndex,
                                                ui64Serial,
                                                sDevVAddr,
                                                uiSize,
@@ -1275,7 +1322,7 @@ PVRSRV_ERROR DevicememHistoryUnmapKM(PMR *psPMR,
 
        if (!bSparse)
        {
-               InsertUnmapAllCommand(ui32AllocationIndex);
+               InsertUnmapAllCommand(PMR_DeviceNode(psPMR), ui32AllocationIndex);
        }
        else
        {
@@ -1345,7 +1392,8 @@ PVRSRV_ERROR DevicememHistorySparseChangeKM(PMR *psPMR,
 
        DevicememHistoryLock();
 
-       eError = FindOrCreateAllocation(ui32AllocationIndex,
+       eError = FindOrCreateAllocation(PMR_DeviceNode(psPMR),
+                                               ui32AllocationIndex,
                                                ui64Serial,
                                                sDevVAddr,
                                                uiSize,
@@ -1370,12 +1418,14 @@ PVRSRV_ERROR DevicememHistorySparseChangeKM(PMR *psPMR,
                goto out_unlock;
        }
 
-       GenerateMapUnmapCommandsForChangeList(ui32AllocPageCount,
+       GenerateMapUnmapCommandsForChangeList(PMR_DeviceNode(psPMR),
+                                                       ui32AllocPageCount,
                                                        paui32AllocPageIndices,
                                                        ui32AllocationIndex,
                                                        IMG_TRUE);
 
-       GenerateMapUnmapCommandsForChangeList(ui32FreePageCount,
+       GenerateMapUnmapCommandsForChangeList(PMR_DeviceNode(psPMR),
+                                                       ui32FreePageCount,
                                                        paui32FreePageIndices,
                                                        ui32AllocationIndex,
                                                        IMG_FALSE);
index c0eae7e..089fa9c 100644 (file)
@@ -61,7 +61,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "osfunc.h"
 #include "lock.h"
 
+#include "pvrsrv.h" /* for PVRSRVGetPVRSRVData() */
+
 #define DEVMEMCTX_FLAGS_FAULT_ADDRESS_AVAILABLE (1 << 0)
+#define DEVMEMHEAP_REFCOUNT_MIN 1
+#define DEVMEMHEAP_REFCOUNT_MAX IMG_INT32_MAX
 
 struct _DEVMEMINT_CTX_
 {
@@ -109,7 +113,7 @@ struct _DEVMEMINT_HEAP_
 {
        struct _DEVMEMINT_CTX_ *psDevmemCtx;
        IMG_UINT32 uiLog2PageSize;
-       ATOMIC_T hRefCount;
+       ATOMIC_T uiRefCount;
 };
 
 struct _DEVMEMINT_RESERVATION_
@@ -191,11 +195,21 @@ static INLINE void DevmemIntCtxRelease(DEVMEMINT_CTX *psDevmemCtx)
 /*************************************************************************/ /*!
 @Function       DevmemIntHeapAcquire
 @Description    Acquire a reference to the provided device memory heap.
-@Return         None
+@Return         IMG_TRUE if referenced and IMG_FALSE in case of error
 */ /**************************************************************************/
-static INLINE void DevmemIntHeapAcquire(DEVMEMINT_HEAP *psDevmemHeap)
+static INLINE IMG_BOOL DevmemIntHeapAcquire(DEVMEMINT_HEAP *psDevmemHeap)
 {
-       OSAtomicIncrement(&psDevmemHeap->hRefCount);
+       IMG_BOOL bSuccess = OSAtomicAddUnless(&psDevmemHeap->uiRefCount, 1,
+                                             DEVMEMHEAP_REFCOUNT_MAX);
+
+       if (!bSuccess)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s(): Failed to acquire the device memory "
+                        "heap, reference count has overflowed.", __func__));
+               return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
 }
 
 /*************************************************************************/ /*!
@@ -207,7 +221,14 @@ static INLINE void DevmemIntHeapAcquire(DEVMEMINT_HEAP *psDevmemHeap)
 */ /**************************************************************************/
 static INLINE void DevmemIntHeapRelease(DEVMEMINT_HEAP *psDevmemHeap)
 {
-       OSAtomicDecrement(&psDevmemHeap->hRefCount);
+       IMG_BOOL bSuccess = OSAtomicSubtractUnless(&psDevmemHeap->uiRefCount, 1,
+                                                  DEVMEMHEAP_REFCOUNT_MIN);
+
+       if (!bSuccess)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s(): Failed to acquire the device memory "
+                        "heap, reference count has underflowed.", __func__));
+       }
 }
 
 PVRSRV_ERROR
@@ -493,7 +514,7 @@ DevmemIntHeapCreate(DEVMEMINT_CTX *psDevmemCtx,
 
        DevmemIntCtxAcquire(psDevmemHeap->psDevmemCtx);
 
-       OSAtomicWrite(&psDevmemHeap->hRefCount, 1);
+       OSAtomicWrite(&psDevmemHeap->uiRefCount, 1);
 
        psDevmemHeap->uiLog2PageSize = uiLog2DataPageSize;
 
@@ -521,7 +542,7 @@ PVRSRV_ERROR DevmemIntAllocDefBackingPage(PVRSRV_DEVICE_NODE *psDevNode,
                IMG_DEV_PHYADDR sDevPhysAddr = {0};
 
 #if defined(PDUMP)
-               PDUMPCOMMENT("Alloc %s page object", pcDefPageName);
+               PDUMPCOMMENT(psDevNode, "Alloc %s page object", pcDefPageName);
 #endif
 
                /* Allocate the dummy page required for sparse backing */
@@ -571,7 +592,7 @@ void DevmemIntFreeDefBackingPage(PVRSRV_DEVICE_NODE *psDevNode,
 
                if (0 == ui32RefCnt)
                {
-                       PDUMPCOMMENT("Free %s page object", pcDefPageName);
+                       PDUMPCOMMENT(psDevNode, "Free %s page object", pcDefPageName);
 
                        /* Free the dummy page when refcount reaches zero */
                        DevPhysMemFree(psDevNode,
@@ -601,6 +622,9 @@ DevmemIntMapPages(DEVMEMINT_RESERVATION *psReservation,
 {
        PVRSRV_ERROR eError;
 
+       PVR_LOG_RETURN_IF_INVALID_PARAM((ui32PageCount < PMR_MAX_SUPPORTED_PAGE_COUNT), "ui32PageCount");
+       PVR_LOG_RETURN_IF_INVALID_PARAM((ui32PhysicalPgOffset < PMR_MAX_SUPPORTED_PAGE_COUNT), "ui32PhysicalPgOffset");
+
        if (psReservation->psDevmemHeap->uiLog2PageSize > PMR_GetLog2Contiguity(psPMR))
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -630,6 +654,8 @@ DevmemIntUnmapPages(DEVMEMINT_RESERVATION *psReservation,
                     IMG_DEV_VIRTADDR sDevVAddrBase,
                     IMG_UINT32 ui32PageCount)
 {
+       PVR_LOG_RETURN_IF_INVALID_PARAM((ui32PageCount < PMR_MAX_SUPPORTED_PAGE_COUNT), "ui32PageCount");
+
        /* Unmap the pages and mark them invalid in the MMU PTE */
        MMU_UnmapPages(psReservation->psDevmemHeap->psDevmemCtx->psMMUContext,
                       0,
@@ -672,13 +698,21 @@ DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
                         __func__,
                         uiLog2HeapContiguity,
                         PMR_GetLog2Contiguity(psPMR) ));
-               PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_INVALID_PARAMS, e0);
+               PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_INVALID_PARAMS, ErrorReturnError);
        }
        psDevNode = psDevmemHeap->psDevmemCtx->psDevNode;
 
+       /* Don't bother with refcount on reservation, as a reservation
+          only ever holds one mapping, so we directly increment the
+          refcount on the heap instead */
+       if (!DevmemIntHeapAcquire(psDevmemHeap))
+       {
+               PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_REFCOUNT_OVERFLOW, ErrorReturnError);
+       }
+
        /* allocate memory to record the mapping info */
        psMapping = OSAllocMem(sizeof(*psMapping));
-       PVR_LOG_GOTO_IF_NOMEM(psMapping, eError, e0);
+       PVR_LOG_GOTO_IF_NOMEM(psMapping, eError, ErrorUnreference);
 
        uiAllocationSize = psReservation->uiLength;
 
@@ -686,7 +720,7 @@ DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
        PVR_ASSERT((IMG_DEVMEM_SIZE_T) ui32NumDevPages << uiLog2HeapContiguity == uiAllocationSize);
 
        eError = PMRLockSysPhysAddresses(psPMR);
-       PVR_GOTO_IF_ERROR(eError, e2);
+       PVR_GOTO_IF_ERROR(eError, ErrorFreeMapping);
 
        sAllocationDevVAddr = psReservation->sBase;
 
@@ -729,7 +763,7 @@ DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
                                                              uiInitValue,
                                                              pszPageName,
                                                              IMG_TRUE);
-                       PVR_GOTO_IF_ERROR(eError, e3);
+                       PVR_GOTO_IF_ERROR(eError, ErrorUnlockPhysAddr);
                }
 
                /* N.B. We pass mapping permission flags to MMU_MapPages and let
@@ -742,7 +776,7 @@ DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
                                      ui32NumDevPages,
                                      NULL,
                                      uiLog2HeapContiguity);
-               PVR_GOTO_IF_ERROR(eError, e4);
+               PVR_GOTO_IF_ERROR(eError, ErrorFreeDefBackingPage);
        }
        else
        {
@@ -752,22 +786,18 @@ DevmemIntMapPMR(DEVMEMINT_HEAP *psDevmemHeap,
                                        (IMG_DEVMEM_SIZE_T) ui32NumDevPages << uiLog2HeapContiguity,
                                        uiMapFlags,
                                        uiLog2HeapContiguity);
-               PVR_GOTO_IF_ERROR(eError, e3);
+               PVR_GOTO_IF_ERROR(eError, ErrorUnlockPhysAddr);
        }
 
        psMapping->psReservation = psReservation;
        psMapping->uiNumPages = ui32NumDevPages;
        psMapping->psPMR = psPMR;
 
-       /* Don't bother with refcount on reservation, as a reservation
-          only ever holds one mapping, so we directly increment the
-          refcount on the heap instead */
-       DevmemIntHeapAcquire(psMapping->psReservation->psDevmemHeap);
-
        *ppsMappingPtr = psMapping;
 
        return PVRSRV_OK;
-e4:
+
+ErrorFreeDefBackingPage:
        if (bNeedBacking)
        {
                /*if the mapping failed, the allocated dummy ref count need
@@ -776,18 +806,24 @@ e4:
                                            psDefPage,
                                            pszPageName);
        }
-e3:
+
+ErrorUnlockPhysAddr:
        {
-               PVRSRV_ERROR eError1=PVRSRV_OK;
+               PVRSRV_ERROR eError1 = PVRSRV_OK;
                eError1 = PMRUnlockSysPhysAddresses(psPMR);
                PVR_LOG_IF_ERROR(eError1, "PMRUnlockSysPhysAddresses");
 
                *ppsMappingPtr = NULL;
        }
-e2:
+
+ErrorFreeMapping:
        OSFreeMem(psMapping);
 
-e0:
+ErrorUnreference:
+       /* if fails there's not much to do (the function will print an error) */
+       DevmemIntHeapRelease(psDevmemHeap);
+
+ErrorReturnError:
        PVR_ASSERT (eError != PVRSRV_OK);
        return eError;
 }
@@ -849,14 +885,13 @@ DevmemIntUnmapPMR(DEVMEMINT_MAPPING *psMapping)
                                 psMapping->psReservation->psDevmemHeap->uiLog2PageSize);
        }
 
-
-
        eError = PMRUnlockSysPhysAddresses(psMapping->psPMR);
        PVR_ASSERT(eError == PVRSRV_OK);
 
-       /* Don't bother with refcount on reservation, as a reservation
-          only ever holds one mapping, so we directly decrement the
-          refcount on the heap instead */
+       /* Don't bother with refcount on reservation, as a reservation only ever
+        * holds one mapping, so we directly decrement the refcount on the heap
+        * instead.
+        * Function will print an error if the heap could not be unreferenced. */
        DevmemIntHeapRelease(psDevmemHeap);
 
        OSFreeMem(psMapping);
@@ -874,9 +909,15 @@ DevmemIntReserveRange(DEVMEMINT_HEAP *psDevmemHeap,
        PVRSRV_ERROR eError;
        DEVMEMINT_RESERVATION *psReservation;
 
+       if (!DevmemIntHeapAcquire(psDevmemHeap))
+       {
+               PVR_GOTO_WITH_ERROR(eError, PVRSRV_ERROR_REFCOUNT_OVERFLOW,
+                                   ErrorReturnError);
+       }
+
        /* allocate memory to record the reservation info */
        psReservation = OSAllocMem(sizeof(*psReservation));
-       PVR_LOG_GOTO_IF_NOMEM(psReservation, eError, e0);
+       PVR_LOG_GOTO_IF_NOMEM(psReservation, eError, ErrorUnreference);
 
        psReservation->sBase = sAllocationDevVAddr;
        psReservation->uiLength = uiAllocationSize;
@@ -888,14 +929,12 @@ DevmemIntReserveRange(DEVMEMINT_HEAP *psDevmemHeap,
                           0, /* alignment is n/a since we supply devvaddr */
                           &sAllocationDevVAddr,
                           psDevmemHeap->uiLog2PageSize);
-       PVR_GOTO_IF_ERROR(eError, e1);
+       PVR_GOTO_IF_ERROR(eError, ErrorFreeReservation);
 
        /* since we supplied the virt addr, MMU_Alloc shouldn't have
           chosen a new one for us */
        PVR_ASSERT(sAllocationDevVAddr.uiAddr == psReservation->sBase.uiAddr);
 
-       DevmemIntHeapAcquire(psDevmemHeap);
-
        psReservation->psDevmemHeap = psDevmemHeap;
        *ppsReservationPtr = psReservation;
 
@@ -905,10 +944,14 @@ DevmemIntReserveRange(DEVMEMINT_HEAP *psDevmemHeap,
         *  error exit paths follow
         */
 
-e1:
+ErrorFreeReservation:
        OSFreeMem(psReservation);
 
-e0:
+ErrorUnreference:
+       /* if fails there's not much to do (the function will print an error) */
+       DevmemIntHeapRelease(psDevmemHeap);
+
+ErrorReturnError:
        PVR_ASSERT(eError != PVRSRV_OK);
        return eError;
 }
@@ -925,22 +968,27 @@ DevmemIntUnreserveRange(DEVMEMINT_RESERVATION *psReservation)
                 uiLength,
                 uiLog2DataPageSize);
 
+       /* Don't bother with refcount on reservation, as a reservation only ever
+        * holds one mapping, so we directly decrement the refcount on the heap
+        * instead.
+        * Function will print an error if the heap could not be unreferenced. */
        DevmemIntHeapRelease(psReservation->psDevmemHeap);
+
        OSFreeMem(psReservation);
 
-    return PVRSRV_OK;
+       return PVRSRV_OK;
 }
 
 
 PVRSRV_ERROR
 DevmemIntHeapDestroy(DEVMEMINT_HEAP *psDevmemHeap)
 {
-       if (OSAtomicRead(&psDevmemHeap->hRefCount) != 1)
+       if (OSAtomicRead(&psDevmemHeap->uiRefCount) != DEVMEMHEAP_REFCOUNT_MIN)
        {
                PVR_DPF((PVR_DBG_ERROR, "BUG!  %s called but has too many references (%d) "
-                        "which probably means allocations have been made from the heap and not freed",
-                        __func__,
-                        OSAtomicRead(&psDevmemHeap->hRefCount)));
+                        "which probably means reservations & mappings have been made from "
+                        "the heap and not freed", __func__,
+                        OSAtomicRead(&psDevmemHeap->uiRefCount)));
 
                /*
                 * Try again later when you've freed all the memory
@@ -956,7 +1004,7 @@ DevmemIntHeapDestroy(DEVMEMINT_HEAP *psDevmemHeap)
                return PVRSRV_ERROR_RETRY;
        }
 
-       PVR_ASSERT(OSAtomicRead(&psDevmemHeap->hRefCount) == 1);
+       PVR_ASSERT(OSAtomicRead(&psDevmemHeap->uiRefCount) == DEVMEMHEAP_REFCOUNT_MIN);
 
        DevmemIntCtxRelease(psDevmemHeap->psDevmemCtx);
 
@@ -1410,31 +1458,33 @@ PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
        DLLIST_NODE         *psNode, *psNodeNext;
        DEVMEMINT_PF_NOTIFY *psNotifyNode;
        IMG_BOOL            bPresent = IMG_FALSE;
+       PVRSRV_ERROR        eError;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(psDevmemCtx, "psDevmemCtx");
 
+       /* Acquire write lock for the duration, to avoid resource free
+        * while trying to read (no need to then also acquire the read lock
+        * as we have exclusive access while holding the write lock)
+        */
+       OSWRLockAcquireWrite(psDevmemCtx->hListLock);
+
        psDevNode = psDevmemCtx->psDevNode;
 
        if (bRegister)
        {
-               OSWRLockAcquireRead(psDevmemCtx->hListLock);
                /* If this is the first PID in the list, the device memory context
                 * needs to be registered for notification */
                if (dllist_is_empty(&psDevmemCtx->sProcessNotifyListHead))
                {
-                       OSWRLockReleaseRead(psDevmemCtx->hListLock);
+                       OSWRLockAcquireWrite(psDevNode->hMemoryContextPageFaultNotifyListLock);
                        dllist_add_to_tail(&psDevNode->sMemoryContextPageFaultNotifyListHead,
                                           &psDevmemCtx->sPageFaultNotifyListElem);
-               }
-               else
-               {
-                       OSWRLockReleaseRead(psDevmemCtx->hListLock);
+                       OSWRLockReleaseWrite(psDevNode->hMemoryContextPageFaultNotifyListLock);
                }
        }
 
        /* Loop through the registered PIDs and check whether this one is
         * present */
-       OSWRLockAcquireRead(psDevmemCtx->hListLock);
        dllist_foreach_node(&(psDevmemCtx->sProcessNotifyListHead), psNode, psNodeNext)
        {
                psNotifyNode = IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
@@ -1445,7 +1495,6 @@ PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
                        break;
                }
        }
-       OSWRLockReleaseRead(psDevmemCtx->hListLock);
 
        if (bRegister)
        {
@@ -1454,7 +1503,8 @@ PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
                        PVR_DPF((PVR_DBG_ERROR,
                                 "%s: Trying to register a PID that is already registered",
                                 __func__));
-                       return PVRSRV_ERROR_PID_ALREADY_REGISTERED;
+                       eError = PVRSRV_ERROR_PID_ALREADY_REGISTERED;
+                       goto err_already_registered;
                }
 
                psNotifyNode = OSAllocMem(sizeof(*psNotifyNode));
@@ -1463,12 +1513,12 @@ PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
                        PVR_DPF((PVR_DBG_ERROR,
                                 "%s: Unable to allocate memory for the notify list",
                                  __func__));
-                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                       goto err_out_of_mem;
                }
                psNotifyNode->ui32PID = ui32PID;
-               OSWRLockAcquireWrite(psDevmemCtx->hListLock);
+               /* Write lock is already held */
                dllist_add_to_tail(&(psDevmemCtx->sProcessNotifyListHead), &(psNotifyNode->sProcessNotifyListElem));
-               OSWRLockReleaseWrite(psDevmemCtx->hListLock);
        }
        else
        {
@@ -1477,26 +1527,31 @@ PVRSRV_ERROR DevmemIntRegisterPFNotifyKM(DEVMEMINT_CTX *psDevmemCtx,
                        PVR_DPF((PVR_DBG_ERROR,
                                 "%s: Trying to unregister a PID that is not registered",
                                 __func__));
-                       return PVRSRV_ERROR_PID_NOT_REGISTERED;
+                       eError = PVRSRV_ERROR_PID_NOT_REGISTERED;
+                       goto err_not_registered;
                }
+               /* Write lock is already held */
                dllist_remove_node(psNode);
                psNotifyNode = IMG_CONTAINER_OF(psNode, DEVMEMINT_PF_NOTIFY, sProcessNotifyListElem);
                OSFreeMem(psNotifyNode);
-       }
 
-       if (!bRegister)
-       {
                /* If the last process in the list is being unregistered, then also
                 * unregister the device memory context from the notify list. */
-               OSWRLockAcquireWrite(psDevmemCtx->hListLock);
                if (dllist_is_empty(&psDevmemCtx->sProcessNotifyListHead))
                {
+                       OSWRLockAcquireWrite(psDevNode->hMemoryContextPageFaultNotifyListLock);
                        dllist_remove_node(&psDevmemCtx->sPageFaultNotifyListElem);
+                       OSWRLockReleaseWrite(psDevNode->hMemoryContextPageFaultNotifyListLock);
                }
-               OSWRLockReleaseWrite(psDevmemCtx->hListLock);
        }
+       eError = PVRSRV_OK;
 
-       return PVRSRV_OK;
+err_already_registered:
+err_out_of_mem:
+err_not_registered:
+
+       OSWRLockReleaseWrite(psDevmemCtx->hListLock);
+       return eError;
 }
 
 /*************************************************************************/ /*!
@@ -1615,6 +1670,15 @@ DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
 
        PVR_UNREFERENCED_PARAMETER(ui32ArraySize);
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored in PVRSRV_DATA.
+        */
+       if (psDevmemCtx->psDevNode->sDevId.ui32InternalID !=
+           (PVRSRVGetPVRSRVData())->ui32PDumpBoundDevice)
+       {
+               return PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE;
+       }
+
        eError = MMU_AcquirePDumpMMUContext(psDevmemCtx->psMMUContext,
                        &uiPDumpMMUCtx,
                        ui32PDumpFlags);
@@ -1628,7 +1692,8 @@ DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
           From a PDump P.O.V. it doesn't matter which name space we use as long
           as that MemSpace is used on the 'MMU Context' we're dumping from
           */
-       eError = PDumpMMUSAB(psDevmemCtx->psDevNode->sDevId.pszPDumpDevName,
+       eError = PDumpMMUSAB(psDevmemCtx->psDevNode,
+                            psDevmemCtx->psDevNode->sDevId.pszPDumpDevName,
                             uiPDumpMMUCtx,
                             sDevAddrStart,
                             uiSize,
@@ -1641,54 +1706,6 @@ DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
        return PVRSRV_OK;
 }
 
-
-PVRSRV_ERROR
-DevmemIntPDumpBitmap(CONNECTION_DATA * psConnection,
-                     PVRSRV_DEVICE_NODE *psDeviceNode,
-                     IMG_CHAR *pszFileName,
-                     IMG_UINT32 ui32FileOffset,
-                     IMG_UINT32 ui32Width,
-                     IMG_UINT32 ui32Height,
-                     IMG_UINT32 ui32StrideInBytes,
-                     IMG_DEV_VIRTADDR sDevBaseAddr,
-                     DEVMEMINT_CTX *psDevMemContext,
-                     IMG_UINT32 ui32Size,
-                     PDUMP_PIXEL_FORMAT ePixelFormat,
-                     IMG_UINT32 ui32AddrMode,
-                     IMG_UINT32 ui32PDumpFlags)
-{
-       IMG_UINT32 ui32ContextID;
-       PVRSRV_ERROR eError;
-
-       PVR_UNREFERENCED_PARAMETER(psConnection);
-
-       eError = MMU_AcquirePDumpMMUContext(psDevMemContext->psMMUContext, &ui32ContextID, ui32PDumpFlags);
-
-       if (eError != PVRSRV_OK)
-       {
-               PVR_LOG_ERROR(eError, "MMU_AcquirePDumpMMUContext");
-               return PVRSRV_ERROR_FAILED_TO_ALLOC_MMUCONTEXT_ID;
-       }
-
-       eError = PDumpBitmapKM(psDeviceNode,
-                              pszFileName,
-                              ui32FileOffset,
-                              ui32Width,
-                              ui32Height,
-                              ui32StrideInBytes,
-                              sDevBaseAddr,
-                              ui32ContextID,
-                              ui32Size,
-                              ePixelFormat,
-                              ui32AddrMode,
-                              ui32PDumpFlags);
-
-       /* Don't care about return value */
-       MMU_ReleasePDumpMMUContext(psDevMemContext->psMMUContext, ui32PDumpFlags);
-
-       return eError;
-}
-
 PVRSRV_ERROR
 DevmemIntPDumpImageDescriptor(CONNECTION_DATA * psConnection,
                                                          PVRSRV_DEVICE_NODE *psDeviceNode,
index ebfe361..5670af0 100644 (file)
@@ -193,6 +193,12 @@ static void _WriteWithRetires(void *pvNativeHandle, const IMG_CHAR *pszStr,
        PVR_LOG_IF_ERROR(eError, "TLStreamWrite");
 }
 
+static void _WriteData(void *pvNativeHandle, const void *pvData,
+                       IMG_UINT32 uiSize)
+{
+       _WriteWithRetires(pvNativeHandle, pvData, uiSize);
+}
+
 __printf(2, 0)
 static void _VPrintf(void *pvNativeHandle, const IMG_CHAR *pszFmt,
                      va_list pArgs)
@@ -216,6 +222,7 @@ static IMG_BOOL _HasOverflowed(void *pvNativeHandle)
 }
 
 static OSDI_IMPL_ENTRY_CB _g_sEntryCallbacks = {
+       .pfnWrite = _WriteData,
        .pfnVPrintf = _VPrintf,
        .pfnPuts = _Puts,
        .pfnHasOverflowed = _HasOverflowed,
@@ -557,7 +564,7 @@ return_:
 }
 
 PVRSRV_ERROR DIWriteEntryKM(DI_CONTEXT *psContext, const IMG_CHAR *pszEntryPath,
-                           IMG_UINT64 ui64ValueSize, const IMG_CHAR *pszValue)
+                           IMG_UINT32 ui32ValueSize, const IMG_CHAR *pszValue)
 {
        DIIB_ENTRY *psEntry;
        DI_PFN_WRITE pfnEntryPuts;
@@ -574,7 +581,7 @@ PVRSRV_ERROR DIWriteEntryKM(DI_CONTEXT *psContext, const IMG_CHAR *pszEntryPath,
        pfnEntryPuts = psEntry->sIterCb.pfnWrite;
        if (pfnEntryPuts != NULL)
        {
-               i64Length = pfnEntryPuts(pszValue, ui64ValueSize, (IMG_UINT64*)&i64Length, psEntry->pvPrivData);
+               i64Length = pfnEntryPuts(pszValue, ui32ValueSize, (IMG_UINT64*)&i64Length, psEntry->pvPrivData);
 
                /* To deal with -EINVAL being returned */
                PVR_LOG_RETURN_IF_INVALID_PARAM(i64Length >= 0, pszValue);
index 3d24818..7d5a6ca 100644 (file)
@@ -85,7 +85,7 @@ PVRSRV_ERROR DIReadEntryKM(DI_CONTEXT *psContext, const IMG_CHAR *pszEntryPath,
                            IMG_UINT64 ui64Offset, IMG_UINT64 ui64Size);
 
 PVRSRV_ERROR DIWriteEntryKM(DI_CONTEXT *psContext, const IMG_CHAR *pszEntryPath,
-                            IMG_UINT64 ui64ValueSize, const IMG_CHAR *pszValue);
+                            IMG_UINT32 ui32ValueSize, const IMG_CHAR *pszValue);
 
 PVRSRV_ERROR DIListAllEntriesKM(DI_CONTEXT *psContext);
 
index db54c65..391f3aa 100644 (file)
@@ -46,6 +46,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dllist.h"
 #include "lock.h"
 #include "allocmem.h"
+#include "osfunc.h"
 
 #define ROOT_GROUP_NAME PVR_DRM_NAME
 
@@ -95,7 +96,7 @@ struct DI_ENTRY
  */
 struct DI_GROUP
 {
-       const IMG_CHAR *pszName;         /*!< name of the group */
+       IMG_CHAR *pszName;               /*!< name of the group */
        const struct DI_GROUP *psParent; /*!< parent groups */
 
        DLLIST_NODE sListNode;           /*!< node element of group's group list */
@@ -128,7 +129,10 @@ PVRSRV_ERROR DIInit(void)
        _g_psRootGroup = OSAllocMem(sizeof(*_g_psRootGroup));
        PVR_LOG_GOTO_IF_NOMEM(_g_psRootGroup, eError, destroy_lock_);
 
-       _g_psRootGroup->pszName = ROOT_GROUP_NAME;
+       _g_psRootGroup->pszName = OSAllocMem(sizeof(ROOT_GROUP_NAME));
+       PVR_LOG_GOTO_IF_NOMEM(_g_psRootGroup->pszName, eError, cleanup_name_);
+       OSStringLCopy(_g_psRootGroup->pszName, ROOT_GROUP_NAME,
+                                 sizeof(ROOT_GROUP_NAME));
 
        dllist_init(&_g_psRootGroup->sListNode);
        dllist_init(&_g_psRootGroup->sGroupList);
@@ -137,6 +141,8 @@ PVRSRV_ERROR DIInit(void)
 
        return PVRSRV_OK;
 
+cleanup_name_:
+       OSFreeMem(_g_psRootGroup);
 destroy_lock_:
        OSLockDestroy(_g_hLock);
 return_:
@@ -259,7 +265,7 @@ static PVRSRV_ERROR _CreateNativeEntry(DI_ENTRY *psEntry,
                                            psEntry->pvPrivData,
                                            psNativeParent->pvHandle,
                                            &psNativeEntry->pvHandle);
-       PVR_LOG_GOTO_IF_ERROR(eError, "psImpl->sCb.pfnCreateGroup", free_memory_);
+       PVR_LOG_GOTO_IF_ERROR(eError, "psImpl->sCb.pfnCreateEntry", free_memory_);
 
        psNativeEntry->psDiImpl = psImpl;
 
@@ -422,6 +428,7 @@ PVRSRV_ERROR DICreateGroup(const IMG_CHAR *pszName,
        PVRSRV_ERROR eError;
        DLLIST_NODE *psThis, *psNext;
        DI_GROUP *psGroup;
+       size_t uSize;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(pszName != NULL, "pszName");
        PVR_LOG_RETURN_IF_INVALID_PARAM(ppsGroup != NULL, "ppsDiGroup");
@@ -434,7 +441,11 @@ PVRSRV_ERROR DICreateGroup(const IMG_CHAR *pszName,
                psParent = _g_psRootGroup;
        }
 
-       psGroup->pszName = pszName;
+       uSize = OSStringLength(pszName) + 1;
+       psGroup->pszName = OSAllocMem(uSize * sizeof(*psGroup->pszName));
+       PVR_LOG_GOTO_IF_NOMEM(psGroup->pszName, eError, cleanup_name_);
+       OSStringLCopy(psGroup->pszName, pszName, uSize);
+
        psGroup->psParent = psParent;
        dllist_init(&psGroup->sGroupList);
        dllist_init(&psGroup->sEntryList);
@@ -475,6 +486,8 @@ cleanup_:
                OSFreeMem(psNativeGroup);
        }
 
+       OSFreeMem(psGroup->pszName);
+cleanup_name_:
        OSFreeMem(psGroup);
 
        return eError;
@@ -502,6 +515,7 @@ void DIDestroyGroup(DI_GROUP *psGroup)
 
        dllist_remove_node(&psGroup->sListNode);
 
+       OSFreeMem(psGroup->pszName);
        OSFreeMem(psGroup);
 }
 
@@ -512,6 +526,17 @@ void *DIGetPrivData(const OSDI_IMPL_ENTRY *psEntry)
        return psEntry->pvPrivData;
 }
 
+void DIWrite(const OSDI_IMPL_ENTRY *psEntry, const void *pvData,
+             IMG_UINT32 uiSize)
+{
+       PVR_ASSERT(psEntry != NULL);
+       PVR_ASSERT(psEntry->psCb != NULL);
+       PVR_ASSERT(psEntry->psCb->pfnWrite != NULL);
+       PVR_ASSERT(psEntry->pvNative != NULL);
+
+       psEntry->psCb->pfnWrite(psEntry->pvNative, pvData, uiSize);
+}
+
 void DIPrintf(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszFmt, ...)
 {
        va_list args;
@@ -526,6 +551,17 @@ void DIPrintf(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszFmt, ...)
        va_end(args);
 }
 
+void DIVPrintf(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszFmt,
+               va_list pArgs)
+{
+       PVR_ASSERT(psEntry != NULL);
+       PVR_ASSERT(psEntry->psCb != NULL);
+       PVR_ASSERT(psEntry->psCb->pfnVPrintf != NULL);
+       PVR_ASSERT(psEntry->pvNative != NULL);
+
+       psEntry->psCb->pfnVPrintf(psEntry->pvNative, pszFmt, pArgs);
+}
+
 void DIPuts(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszStr)
 {
        PVR_ASSERT(psEntry != NULL);
index a32385d..c5dd5d7 100644 (file)
@@ -62,10 +62,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "handle_impl.h"
 #include "allocmem.h"
 #include "pvr_debug.h"
+#include "osfunc.h"
+#include "lock.h"
 #include "connection_server.h"
-#include "pvrsrv.h"
 
-#define        HANDLE_HASH_TAB_INIT_SIZE               32
+#define        HANDLE_HASH_TAB_INIT_SIZE 32
+#define HANDLE_PROC_HANDLE_HASH_INIT_SIZE 10
 
 #define        TEST_FLAG(v, f) BITMASK_HAS(v, f)
 #define        TEST_ALLOC_FLAG(psHandleData, f) BITMASK_HAS((psHandleData)->eFlag, f)
@@ -107,10 +109,13 @@ typedef struct _HANDLE_DATA_
        /* List entry for sibling subhandles */
        HANDLE_LIST sSiblings;
 
-       /* Reference count. The pfnReleaseData callback gets called when the
-        * reference count hits zero
-        */
-       IMG_UINT32 ui32RefCount;
+       /* Reference count of lookups made. It helps track which resources are in
+        * use in concurrent bridge calls. */
+       IMG_INT32 iLookupCount;
+       /* State of a handle. If the handle was already destroyed this is false.
+        * If this is false and iLookupCount is 0 the pfnReleaseData callback is
+        * called on the handle. */
+       IMG_BOOL bCanLookup;
 
 #if defined(PVRSRV_DEBUG_HANDLE_LOCK)
        /* Store the handle base used for this handle, so we
@@ -179,6 +184,12 @@ static HANDLE_IMPL_FUNCTAB const *gpsHandleFuncs;
 
 static POS_LOCK gKernelHandleLock;
 static IMG_BOOL gbLockInitialised = IMG_FALSE;
+/* Pointer to process handle base currently being freed */
+static PVRSRV_HANDLE_BASE *g_psProcessHandleBaseBeingFreed;
+/* Lock for the process handle base table */
+static POS_LOCK g_hProcessHandleBaseLock;
+/* Hash table with process handle bases */
+static HASH_TABLE *g_psProcessHandleBaseTable;
 
 void LockHandle(PVRSRV_HANDLE_BASE *psBase)
 {
@@ -196,40 +207,60 @@ void UnlockHandle(PVRSRV_HANDLE_BASE *psBase)
  */
 PVRSRV_HANDLE_BASE *gpsKernelHandleBase = NULL;
 
-/* Increase the reference count on the given handle.
+/* Increase the lookup reference count on the given handle.
  * The handle lock must already be acquired.
  * Returns: the reference count after the increment
  */
-static inline IMG_UINT32 _HandleRef(HANDLE_DATA *psHandleData)
+static inline IMG_UINT32 HandleGet(HANDLE_DATA *psHandleData)
 {
 #if defined(PVRSRV_DEBUG_HANDLE_LOCK)
        if (!OSLockIsLocked(psHandleData->psBase->hLock))
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
-               //OSDumpStack();
+               OSDumpStack();
        }
 #endif
-       psHandleData->ui32RefCount++;
-       return psHandleData->ui32RefCount;
+
+#ifdef DEBUG_REFCNT
+       PVR_DPF((PVR_DBG_ERROR, "%s: bCanLookup = %u, iLookupCount %d -> %d",
+               __func__, psHandleData->bCanLookup, psHandleData->iLookupCount,
+               psHandleData->iLookupCount + 1));
+#endif /* DEBUG_REFCNT */
+
+       PVR_ASSERT(psHandleData->bCanLookup);
+
+       return ++psHandleData->iLookupCount;
 }
 
-/* Decrease the reference count on the given handle.
+/* Decrease the lookup reference count on the given handle.
  * The handle lock must already be acquired.
  * Returns: the reference count after the decrement
  */
-static inline IMG_UINT32 _HandleUnref(HANDLE_DATA *psHandleData)
+static inline IMG_UINT32 HandlePut(HANDLE_DATA *psHandleData)
 {
 #if defined(PVRSRV_DEBUG_HANDLE_LOCK)
        if (!OSLockIsLocked(psHandleData->psBase->hLock))
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Handle lock is not locked", __func__));
-               //OSDumpStack();
+               OSDumpStack();
        }
 #endif
-       PVR_ASSERT(psHandleData->ui32RefCount > 0);
-       psHandleData->ui32RefCount--;
 
-       return psHandleData->ui32RefCount;
+#ifdef DEBUG_REFCNT
+       PVR_DPF((PVR_DBG_ERROR, "%s: bCanLookup = %u, iLookupCount %d -> %d",
+               __func__, psHandleData->bCanLookup, psHandleData->iLookupCount,
+               psHandleData->iLookupCount - 1));
+#endif /* DEBUG_REFCNT */
+
+       /* psHandleData->bCanLookup can be false at this point */
+       PVR_ASSERT(psHandleData->iLookupCount > 0);
+
+       return --psHandleData->iLookupCount;
+}
+
+static inline IMG_BOOL IsRetryError(PVRSRV_ERROR eError)
+{
+       return eError == PVRSRV_ERROR_RETRY || eError == PVRSRV_ERROR_KERNEL_CCB_FULL;
 }
 
 #if defined(PVRSRV_NEED_PVR_DPF)
@@ -266,6 +297,21 @@ static const IMG_CHAR *HandleBaseTypeToString(PVRSRV_HANDLE_BASE_TYPE eType)
 }
 #endif
 
+static PVRSRV_ERROR HandleUnrefAndMaybeMarkForFree(PVRSRV_HANDLE_BASE *psBase,
+                                                   HANDLE_DATA *psHandleData,
+                                                   IMG_HANDLE hHandle,
+                                                   PVRSRV_HANDLE_TYPE eType);
+
+static PVRSRV_ERROR HandleFreePrivData(PVRSRV_HANDLE_BASE *psBase,
+                                       HANDLE_DATA *psHandleData,
+                                       IMG_HANDLE hHandle,
+                                       PVRSRV_HANDLE_TYPE eType);
+
+static PVRSRV_ERROR HandleFreeDestroy(PVRSRV_HANDLE_BASE *psBase,
+                                      HANDLE_DATA *psHandleData,
+                                      IMG_HANDLE hHandle,
+                                      PVRSRV_HANDLE_TYPE eType);
+
 /*!
 *******************************************************************************
  @Function      GetHandleData
@@ -817,107 +863,6 @@ void InitKey(HAND_KEY aKey,
        aKey[HAND_KEY_PARENT] = (uintptr_t)hParent;
 }
 
-static PVRSRV_ERROR FreeHandleWrapper(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle);
-
-/*!
-*******************************************************************************
- @Function      FreeHandle
- @Description   Free a handle data structure.
- @Input         psBase - Pointer to handle base structure
-                hHandle - Handle to be freed
-                eType - Type of the handle to be freed
-                ppvData - Location for data associated with the freed handle
- @Output        ppvData - Points to the data associated with the freed handle
- @Return        PVRSRV_OK or PVRSRV_ERROR
-******************************************************************************/
-static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase,
-                              IMG_HANDLE hHandle,
-                              PVRSRV_HANDLE_TYPE eType,
-                              void **ppvData)
-{
-       HANDLE_DATA *psHandleData = NULL;
-       HANDLE_DATA *psReleasedHandleData;
-       PVRSRV_ERROR eError;
-
-       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
-       PVR_LOG_RETURN_IF_ERROR(eError, "GetHandleData");
-
-       if (_HandleUnref(psHandleData) > 0)
-       {
-               /* this handle still has references so do not destroy it
-                * or the underlying object yet
-                */
-               return PVRSRV_OK;
-       }
-
-       /* Call the release data callback for each reference on the handle */
-       if (psHandleData->pfnReleaseData != NULL)
-       {
-               eError = psHandleData->pfnReleaseData(psHandleData->pvData);
-               if (eError == PVRSRV_ERROR_RETRY)
-               {
-                       PVR_DPF((PVR_DBG_MESSAGE,
-                                "%s: "
-                                "Got retry while calling release data callback for %p (type = %d)",
-                                __func__,
-                                hHandle,
-                                (IMG_UINT32)psHandleData->eType));
-
-                       /* the caller should retry, so retain a reference on the handle */
-                       _HandleRef(psHandleData);
-
-                       return eError;
-               }
-               else if (eError != PVRSRV_OK)
-               {
-                       return eError;
-               }
-       }
-
-       if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
-       {
-               HAND_KEY aKey;
-               IMG_HANDLE hRemovedHandle;
-
-               InitKey(aKey, psBase, psHandleData->pvData, psHandleData->eType, ParentIfPrivate(psHandleData));
-
-               hRemovedHandle = (IMG_HANDLE)HASH_Remove_Extended(psBase->psHashTab, aKey);
-
-               PVR_ASSERT(hRemovedHandle != NULL);
-               PVR_ASSERT(hRemovedHandle == psHandleData->hHandle);
-               PVR_UNREFERENCED_PARAMETER(hRemovedHandle);
-       }
-
-       eError = UnlinkFromParent(psBase, psHandleData);
-       PVR_LOG_RETURN_IF_ERROR(eError, "UnlinkFromParent");
-
-       /* Free children */
-       eError = IterateOverChildren(psBase, psHandleData, FreeHandleWrapper);
-       PVR_LOG_RETURN_IF_ERROR(eError, "IterateOverChildren");
-
-       eError = gpsHandleFuncs->pfnReleaseHandle(psBase->psImplBase,
-                                                 psHandleData->hHandle,
-                                                 (void **)&psReleasedHandleData);
-       if (unlikely(eError == PVRSRV_OK))
-       {
-               PVR_ASSERT(psReleasedHandleData == psHandleData);
-       }
-
-       if (ppvData)
-       {
-               *ppvData = psHandleData->pvData;
-       }
-
-       OSFreeMem(psHandleData);
-
-       return eError;
-}
-
-static PVRSRV_ERROR FreeHandleWrapper(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle)
-{
-       return FreeHandle(psBase, hHandle, PVRSRV_HANDLE_TYPE_NONE, NULL);
-}
-
 /*!
 *******************************************************************************
  @Function      FindHandle
@@ -1013,7 +958,12 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase,
        psNewHandleData->eFlag = eFlag;
        psNewHandleData->pvData = pvData;
        psNewHandleData->pfnReleaseData = pfnReleaseData;
-       psNewHandleData->ui32RefCount = 1;
+       psNewHandleData->iLookupCount = 0;
+       psNewHandleData->bCanLookup = IMG_TRUE;
+
+#ifdef DEBUG_REFCNT
+       PVR_DPF((PVR_DBG_ERROR, "%s: bCanLookup = true", __func__));
+#endif /* DEBUG_REFCNT */
 
        InitParentList(psNewHandleData);
 #if defined(DEBUG)
@@ -1197,7 +1147,7 @@ PVRSRV_ERROR PVRSRVAllocSubHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
        return PVRSRV_OK;
 
 ExitFreeHandle:
-       (void) FreeHandle(psBase, hHandle, eType, NULL);
+       PVRSRVDestroyHandleUnlocked(psBase, hHandle, eType);
 Exit:
        return eError;
 }
@@ -1337,14 +1287,16 @@ PVRSRV_ERROR PVRSRVLookupHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
                return eError;
        }
 
-       if (psHandleData->ui32RefCount == 0)
+       /* If bCanLookup is false it means that a destroy operation was already
+        * called on this handle; therefore it can no longer be looked up. */
+       if (!psHandleData->bCanLookup)
        {
-               return PVRSRV_ERROR_HANDLE_INDEX_OUT_OF_RANGE;
+               return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
        }
 
        if (bRef)
        {
-               _HandleRef(psHandleData);
+               HandleGet(psHandleData);
        }
 
        *ppvData = psHandleData->pvData;
@@ -1424,17 +1376,13 @@ ExitUnlock:
                 eType - handle type
  @Return        Error code or PVRSRV_OK
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
-                                IMG_HANDLE hHandle,
-                                PVRSRV_HANDLE_TYPE eType)
+void PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+                         IMG_HANDLE hHandle,
+                         PVRSRV_HANDLE_TYPE eType)
 {
-       PVRSRV_ERROR eError;
-
        LockHandle(psBase);
-       eError = PVRSRVReleaseHandleUnlocked(psBase, hHandle, eType);
+       PVRSRVReleaseHandleUnlocked(psBase, hHandle, eType);
        UnlockHandle(psBase);
-
-       return eError;
 }
 
 
@@ -1446,19 +1394,40 @@ PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
                 hold the lock when called.
  @Input         hHandle - handle from client
                 eType - handle type
- @Return        Error code or PVRSRV_OK
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
-                                IMG_HANDLE hHandle,
-                                PVRSRV_HANDLE_TYPE eType)
+void PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+                                 IMG_HANDLE hHandle,
+                                 PVRSRV_HANDLE_TYPE eType)
 {
+       HANDLE_DATA *psHandleData = NULL;
+       PVRSRV_ERROR eError;
+
        /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+       PVR_ASSERT(psBase != NULL);
        PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
        PVR_ASSERT(gpsHandleFuncs);
 
-       PVR_LOG_RETURN_IF_INVALID_PARAM(psBase != NULL, "psBase");
+       PVR_LOG_RETURN_VOID_IF_FALSE(psBase != NULL, "invalid psBase");
+
+       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Error (%s) looking up handle %p of type %s "
+                       "for base %p of type %s.", __func__, PVRSRVGetErrorString(eError),
+                       (void*) hHandle, HandleTypeToString(eType), psBase,
+                       HandleBaseTypeToString(psBase->eType)));
+
+               PVR_ASSERT(eError == PVRSRV_OK);
 
-       return FreeHandle(psBase, hHandle, eType, NULL);
+               return;
+       }
+
+       PVR_ASSERT(psHandleData->bCanLookup);
+       PVR_ASSERT(psHandleData->iLookupCount > 0);
+
+       /* If there are still outstanding lookups for this handle or the handle
+        * has not been destroyed yet, return early */
+       HandlePut(psHandleData);
 }
 
 /*!
@@ -1483,88 +1452,94 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
        return eError;
 }
 
-static PVRSRV_ERROR HandleUnrefAndMaybeMarkForFree(PVRSRV_HANDLE_BASE *psBase,
-                                      IMG_HANDLE hHandle,
-                                      PVRSRV_HANDLE_TYPE eType);
-
 static PVRSRV_ERROR HandleUnrefAndMaybeMarkForFreeWrapper(PVRSRV_HANDLE_BASE *psBase,
                                                           IMG_HANDLE hHandle)
 {
-       return HandleUnrefAndMaybeMarkForFree(psBase, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+       HANDLE_DATA *psHandleData;
+       PVRSRV_ERROR eError = GetHandleData(psBase, &psHandleData, hHandle,
+                                           PVRSRV_HANDLE_TYPE_NONE);
+       PVR_RETURN_IF_ERROR(eError);
+
+       return HandleUnrefAndMaybeMarkForFree(psBase, psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
 }
 
 static PVRSRV_ERROR HandleUnrefAndMaybeMarkForFree(PVRSRV_HANDLE_BASE *psBase,
+                                                   HANDLE_DATA *psHandleData,
                                                    IMG_HANDLE hHandle,
                                                    PVRSRV_HANDLE_TYPE eType)
 {
-       HANDLE_DATA *psHandleData = NULL;
        PVRSRV_ERROR eError;
 
-       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
-       PVR_RETURN_IF_ERROR(eError);
-
-       if (psHandleData->ui32RefCount == 0)
+       /* If bCanLookup is false it means that the destructor was called more than
+        * once on this handle. */
+       if (!psHandleData->bCanLookup)
        {
-               /* the handle is already in the destruction phase
-                * i.e. its refcount has already reached 0
-                */
-               return PVRSRV_OK;
+               PVR_DPF((PVR_DBG_ERROR, "%s: Handle %p of type %s already freed.",
+                       __func__, psHandleData->hHandle,
+                       HandleTypeToString(psHandleData->eType)));
+               return PVRSRV_ERROR_HANDLE_NOT_FOUND;
        }
 
-       if (_HandleUnref(psHandleData) > 0)
+       if (psHandleData->iLookupCount > 0)
        {
-               /* this handle still has references so do not destroy it
-                * or the underlying object yet
-                */
                return PVRSRV_ERROR_OBJECT_STILL_REFERENCED;
        }
 
+       /* Mark this handle as freed only if it's no longer referenced by any
+        * lookup. The user space should retry freeing this handle once there are
+        * no outstanding lookups. */
+       psHandleData->bCanLookup = IMG_FALSE;
+
+#ifdef DEBUG_REFCNT
+       PVR_DPF((PVR_DBG_ERROR, "%s: bCanLookup = false, iLookupCount = %d", __func__,
+               psHandleData->iLookupCount));
+#endif /* DEBUG_REFCNT */
+
        /* Prepare children for destruction */
        eError = IterateOverChildren(psBase, psHandleData,
                                     HandleUnrefAndMaybeMarkForFreeWrapper);
-       PVR_LOG_RETURN_IF_ERROR(eError, "IterateOverChildren->HandleUnrefAndMaybeMarkForFree");
+       PVR_LOG_RETURN_IF_ERROR(eError, "HandleUnrefAndMaybeMarkForFreeWrapper");
 
        return PVRSRV_OK;
 }
 
-static PVRSRV_ERROR HandleFreePrivData(PVRSRV_HANDLE_BASE *psBase,
-                                       IMG_HANDLE hHandle,
-                                       PVRSRV_HANDLE_TYPE eType);
-
 static PVRSRV_ERROR HandleFreePrivDataWrapper(PVRSRV_HANDLE_BASE *psBase,
                                               IMG_HANDLE hHandle)
 {
-       return HandleFreePrivData(psBase, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+       HANDLE_DATA *psHandleData;
+       PVRSRV_ERROR eError = GetHandleData(psBase, &psHandleData, hHandle,
+                                           PVRSRV_HANDLE_TYPE_NONE);
+       PVR_RETURN_IF_ERROR(eError);
+
+       return HandleFreePrivData(psBase, psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
 }
 
 static PVRSRV_ERROR HandleFreePrivData(PVRSRV_HANDLE_BASE *psBase,
+                                       HANDLE_DATA *psHandleData,
                                        IMG_HANDLE hHandle,
                                        PVRSRV_HANDLE_TYPE eType)
 {
-       HANDLE_DATA *psHandleData = NULL;
        PVRSRV_ERROR eError;
 
-       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
-       PVR_RETURN_IF_ERROR(eError);
-
        /* Call the release data callback for each reference on the handle */
        if (psHandleData->pfnReleaseData != NULL)
        {
                eError = psHandleData->pfnReleaseData(psHandleData->pvData);
-               if (eError == PVRSRV_ERROR_RETRY)
+               if (eError != PVRSRV_OK)
                {
-                       PVR_DPF((PVR_DBG_MESSAGE,
-                                "FreeHandle: "
-                                "Got retry while calling release data callback for %p (type = %d)",
-                                hHandle,
-                                (IMG_UINT32)psHandleData->eType));
+                       if (IsRetryError(eError))
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE, "%s: Got retry while calling release "
+                                               "data callback for handle %p of type = %s", __func__,
+                                               hHandle, HandleTypeToString(psHandleData->eType)));
+                       }
+                       else
+                       {
+                               PVR_LOG_ERROR(eError, "pfnReleaseData");
+                       }
 
                        return eError;
                }
-               else if (eError != PVRSRV_OK)
-               {
-                       return eError;
-               }
 
                /* we don't need this so make sure it's not called on
                 * the pvData for the second time
@@ -1580,27 +1555,25 @@ static PVRSRV_ERROR HandleFreePrivData(PVRSRV_HANDLE_BASE *psBase,
        return PVRSRV_OK;
 }
 
-static PVRSRV_ERROR HandleFreeDestroy(PVRSRV_HANDLE_BASE *psBase,
-                                     IMG_HANDLE hHandle,
-                                     PVRSRV_HANDLE_TYPE eType);
-
 static PVRSRV_ERROR HandleFreeDestroyWrapper(PVRSRV_HANDLE_BASE *psBase,
-                                         IMG_HANDLE hHandle)
+                                             IMG_HANDLE hHandle)
 {
-       return HandleFreeDestroy(psBase, hHandle, PVRSRV_HANDLE_TYPE_NONE);
+       HANDLE_DATA *psHandleData;
+       PVRSRV_ERROR eError = GetHandleData(psBase, &psHandleData, hHandle,
+                                           PVRSRV_HANDLE_TYPE_NONE);
+       PVR_RETURN_IF_ERROR(eError);
+
+       return HandleFreeDestroy(psBase, psHandleData, hHandle, PVRSRV_HANDLE_TYPE_NONE);
 }
 
 static PVRSRV_ERROR HandleFreeDestroy(PVRSRV_HANDLE_BASE *psBase,
+                                      HANDLE_DATA *psHandleData,
                                       IMG_HANDLE hHandle,
                                       PVRSRV_HANDLE_TYPE eType)
 {
-       HANDLE_DATA *psHandleData = NULL;
        HANDLE_DATA *psReleasedHandleData;
        PVRSRV_ERROR eError;
 
-       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
-       PVR_RETURN_IF_ERROR(eError);
-
        eError = UnlinkFromParent(psBase, psHandleData);
        PVR_LOG_RETURN_IF_ERROR(eError, "UnlinkFromParent");
 
@@ -1633,40 +1606,122 @@ static PVRSRV_ERROR HandleFreeDestroy(PVRSRV_HANDLE_BASE *psBase,
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR PVRSRVReleaseHandleStagedUnlock(PVRSRV_HANDLE_BASE *psBase,
-                                             IMG_HANDLE hHandle,
-                                             PVRSRV_HANDLE_TYPE eType)
+static PVRSRV_ERROR DestroyHandle(PVRSRV_HANDLE_BASE *psBase,
+                                  IMG_HANDLE hHandle,
+                                  PVRSRV_HANDLE_TYPE eType,
+                                  IMG_BOOL bReleaseLock)
 {
        PVRSRV_ERROR eError;
+       HANDLE_DATA *psHandleData = NULL;
 
        PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
        PVR_ASSERT(gpsHandleFuncs);
 
-       PVR_LOG_RETURN_IF_FALSE(psBase != NULL, "psBase invalid",
-                               PVRSRV_ERROR_INVALID_PARAMS);
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psBase != NULL, "psBase");
 
-       eError = HandleUnrefAndMaybeMarkForFree(psBase, hHandle, eType);
-       if (eError == PVRSRV_ERROR_OBJECT_STILL_REFERENCED)
+       eError = GetHandleData(psBase, &psHandleData, hHandle, eType);
+       PVR_RETURN_IF_ERROR(eError);
+
+       eError = HandleUnrefAndMaybeMarkForFree(psBase, psHandleData, hHandle, eType);
+       PVR_RETURN_IF_ERROR(eError);
+
+       if (bReleaseLock)
        {
-               return PVRSRV_OK;
+               UnlockHandle(psBase);
        }
-       else if (eError != PVRSRV_OK)
+
+       eError = HandleFreePrivData(psBase, psHandleData, hHandle, eType);
+       if (eError != PVRSRV_OK)
        {
+               if (bReleaseLock)
+               {
+                       LockHandle(psBase);
+               }
+
+               /* If the data could not be freed due to a temporary condition the
+                * handle must be kept alive so that the next destroy call can try again */
+               if (IsRetryError(eError))
+               {
+                       psHandleData->bCanLookup = IMG_TRUE;
+               }
+
                return eError;
        }
 
-       UnlockHandle(psBase);
-
-       eError = HandleFreePrivData(psBase, hHandle, eType);
-       if (eError != PVRSRV_OK)
+       if (bReleaseLock)
        {
                LockHandle(psBase);
-               return eError;
        }
 
+       return HandleFreeDestroy(psBase, psHandleData, hHandle, eType);
+}
+
+/*!
+*******************************************************************************
+ @Function      PVRSRVDestroyHandle
+ @Description   Destroys a handle that is no longer needed. Will
+                acquiring the handle lock for duration of the call.
+                Can return RETRY or KERNEL_CCB_FULL if resource could not be
+                destroyed, caller should retry sometime later.
+ @Input         psBase - pointer to handle base structure
+                hHandle - handle from client
+                eType - handle type
+ @Return        Error code or PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR PVRSRVDestroyHandle(PVRSRV_HANDLE_BASE *psBase,
+                                 IMG_HANDLE hHandle,
+                                 PVRSRV_HANDLE_TYPE eType)
+{
+       PVRSRV_ERROR eError;
+
        LockHandle(psBase);
+       eError = DestroyHandle(psBase, hHandle, eType, IMG_FALSE);
+       UnlockHandle(psBase);
 
-       return HandleFreeDestroy(psBase, hHandle, eType);
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function      PVRSRVDestroyHandleUnlocked
+ @Description   Destroys a handle that is no longer needed without
+                acquiring/releasing the handle lock. The function assumes you
+                hold the lock when called.
+                Can return RETRY or KERNEL_CCB_FULL if resource could not be
+                destroyed, caller should retry sometime later.
+ @Input         psBase - pointer to handle base structure
+                hHandle - handle from client
+                eType - handle type
+ @Return        Error code or PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR PVRSRVDestroyHandleUnlocked(PVRSRV_HANDLE_BASE *psBase,
+                                         IMG_HANDLE hHandle,
+                                         PVRSRV_HANDLE_TYPE eType)
+{
+       return DestroyHandle(psBase, hHandle, eType, IMG_FALSE);
+}
+
+/*!
+*******************************************************************************
+ @Function      PVRSRVDestroyHandleStagedUnlocked
+ @Description   Destroys a handle that is no longer needed without
+                acquiring/releasing the handle lock. The function assumes you
+                hold the lock when called. This function, unlike
+                PVRSRVDestroyHandleUnlocked(), releases the handle lock while
+                destroying handle private data. This is done to open the
+                bridge for other bridge calls.
+                Can return RETRY or KERNEL_CCB_FULL if resource could not be
+                destroyed, caller should retry sometime later.
+ @Input         psBase - pointer to handle base structure
+                hHandle - handle from client
+                eType - handle type
+ @Return        Error code or PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR PVRSRVDestroyHandleStagedUnlocked(PVRSRV_HANDLE_BASE *psBase,
+                                               IMG_HANDLE hHandle,
+                                               PVRSRV_HANDLE_TYPE eType)
+{
+       return DestroyHandle(psBase, hHandle, eType, IMG_TRUE);
 }
 
 /*!
@@ -1778,12 +1833,11 @@ static PVRSRV_ERROR ListHandlesInBase(IMG_HANDLE hHandle, void *pvData)
 
        if (psHandleData != NULL)
        {
-               PVR_DPF((PVR_DBG_WARNING, "    Handle: %6u, Refs: %3u, Type: %s (%u), pvData<%p>",
-                               (IMG_UINT32) (uintptr_t) psHandleData->hHandle,
-                               psHandleData->ui32RefCount,
-                               HandleTypeToString(psHandleData->eType),
-                               psHandleData->eType,
-                               psHandleData->pvData));
+               PVR_DPF((PVR_DBG_WARNING,
+                       "    Handle: %6u, CanLookup: %u, LookupCount: %3u, Type: %s (%u), pvData<%p>",
+                      (IMG_UINT32) (uintptr_t) psHandleData->hHandle, psHandleData->bCanLookup,
+                      psHandleData->iLookupCount, HandleTypeToString(psHandleData->eType),
+                      psHandleData->eType, psHandleData->pvData));
        }
 
        return PVRSRV_OK;
@@ -1794,7 +1848,7 @@ static PVRSRV_ERROR ListHandlesInBase(IMG_HANDLE hHandle, void *pvData)
 static INLINE IMG_BOOL _CheckIfMaxTimeExpired(IMG_UINT64 ui64TimeStart, IMG_UINT64 ui64MaxBridgeTime)
 {
        /* unsigned arithmetic is well defined so this will wrap around correctly */
-       return (OSClockns64() - ui64TimeStart) >= ui64MaxBridgeTime;
+       return (IMG_BOOL)((OSClockns64() - ui64TimeStart) >= ui64MaxBridgeTime);
 }
 
 static PVRSRV_ERROR FreeKernelHandlesWrapperIterKernel(IMG_HANDLE hHandle, void *pvData)
@@ -1888,21 +1942,18 @@ static PVRSRV_ERROR FreeHandleDataWrapper(IMG_HANDLE hHandle, void *pvData)
                return PVRSRV_OK;
        }
 
-       PVR_ASSERT(psHandleData->ui32RefCount > 0);
+       PVR_ASSERT(psHandleData->bCanLookup && psHandleData->iLookupCount == 0);
 
-       while (psHandleData->ui32RefCount != 0)
+       if (psHandleData->bCanLookup)
        {
                if (psHandleData->pfnReleaseData != NULL)
                {
                        eError = psHandleData->pfnReleaseData(psHandleData->pvData);
                        if (eError == PVRSRV_ERROR_RETRY)
                        {
-                               PVR_DPF((PVR_DBG_MESSAGE,
-                                        "%s: "
-                                        "Got retry while calling release data callback for %p (type = %d)",
-                                        __func__,
-                                        hHandle,
-                                        (IMG_UINT32)psHandleData->eType));
+                               PVR_DPF((PVR_DBG_MESSAGE, "%s: Got retry while calling release "
+                                       "data callback for handle %p of type = %s", __func__,
+                                       hHandle, HandleTypeToString(psHandleData->eType)));
 
                                return eError;
                        }
@@ -1912,7 +1963,7 @@ static PVRSRV_ERROR FreeHandleDataWrapper(IMG_HANDLE hHandle, void *pvData)
                        }
                }
 
-               _HandleUnref(psHandleData);
+               psHandleData->bCanLookup = IMG_FALSE;
        }
 
        if (!TEST_ALLOC_FLAG(psHandleData, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
@@ -1946,10 +1997,10 @@ static PVRSRV_ERROR FreeHandleDataWrapper(IMG_HANDLE hHandle, void *pvData)
                         "%s: Lock timeout (timeout: %" IMG_UINT64_FMTSPEC")",
                         __func__,
                         psData->ui64MaxBridgeTime));
-               /* UnlockHandle(psData->psBase); - func only run in single thread ctx */
+               UnlockHandle(psData->psBase);
                /* Invoke the scheduler to check if other processes are waiting for the lock */
                OSReleaseThreadQuanta();
-               /* LockHandle(psData->psBase); - func only run in single thread ctx */
+               LockHandle(psData->psBase);
                /* Set again lock timeout and reset the counter */
                psData->ui64TimeStart = OSClockns64();
                PVR_DPF((PVR_DBG_MESSAGE, "%s: Lock acquired again", __func__));
@@ -1998,6 +2049,9 @@ static const PVRSRV_HANDLE_TYPE g_aeOrderedFreeList[] =
        PVRSRV_HANDLE_TYPE_RGX_SERVER_COMPUTE_CONTEXT,
        PVRSRV_HANDLE_TYPE_RGX_SERVER_RAY_CONTEXT,
        PVRSRV_HANDLE_TYPE_RGX_SERVER_KICKSYNC_CONTEXT,
+#if defined(PVR_TESTING_UTILS) && defined(SUPPORT_VALIDATION)
+       PVRSRV_HANDLE_TYPE_RGX_SERVER_GPUMAP_CONTEXT,
+#endif
        PVRSRV_HANDLE_TYPE_RI_HANDLE,
        PVRSRV_HANDLE_TYPE_SYNC_RECORD_HANDLE,
        PVRSRV_HANDLE_TYPE_SYNC_PRIMITIVE_BLOCK,
@@ -2069,19 +2123,21 @@ PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void)
 {
        PVRSRV_HANDLE_BASE *psHandleBase = NULL;
        PROCESS_HANDLE_BASE *psProcHandleBase = NULL;
-       PVRSRV_DATA *psPvrData = PVRSRVGetPVRSRVData();
        IMG_PID ui32PurgePid = PVRSRVGetPurgeConnectionPid();
+       IMG_PID uiCleanupPid = PVRSRVCleanupThreadGetPid();
+       uintptr_t uiCleanupTid = PVRSRVCleanupThreadGetTid();
 
-       OSLockAcquire(psPvrData->hProcessHandleBase_Lock);
+       OSLockAcquire(g_hProcessHandleBaseLock);
 
        /* Check to see if we're being called from the cleanup thread... */
-       if ((OSGetCurrentClientProcessIDKM() == psPvrData->cleanupThreadPid) &&
-               (ui32PurgePid > 0))
+       if ((OSGetCurrentProcessID() == uiCleanupPid) &&
+           (OSGetCurrentThreadID() == uiCleanupTid) &&
+           (ui32PurgePid > 0))
        {
                /* Check to see if the cleanup thread has already removed the
                 * process handle base from the HASH table.
                 */
-               psHandleBase = psPvrData->psProcessHandleBaseBeingFreed;
+               psHandleBase = g_psProcessHandleBaseBeingFreed;
                /* psHandleBase shouldn't be null, as cleanup thread
                 * should be removing this from the HASH table before
                 * we get here, so assert if not.
@@ -2093,10 +2149,11 @@ PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void)
                /* Not being called from the cleanup thread, so return the process
                 * handle base for the current process.
                 */
-               psProcHandleBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(psPvrData->psProcessHandleBase_Table,
-                                                                                                                               OSGetCurrentClientProcessIDKM());
+               psProcHandleBase = (PROCESS_HANDLE_BASE *)
+                   HASH_Retrieve(g_psProcessHandleBaseTable, OSGetCurrentClientProcessIDKM());
        }
-       OSLockRelease(psPvrData->hProcessHandleBase_Lock);
+
+       OSLockRelease(g_hProcessHandleBaseLock);
 
        if (psHandleBase == NULL && psProcHandleBase != NULL)
        {
@@ -2107,6 +2164,112 @@ PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void)
 
 /*!
 *******************************************************************************
+ @Function      PVRSRVAcquireProcessHandleBase
+ @Description   Increments reference count on a process handle base identified
+                by uiPid and returns pointer to the base. If the handle base
+                does not exist it will be allocated.
+ @Inout         uiPid - PID of a process
+ @Output        ppsBase - pointer to a handle base for the process identified by
+                          uiPid
+ @Return        Error code or PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE **ppsBase)
+{
+       PROCESS_HANDLE_BASE *psBase;
+       PVRSRV_ERROR eError;
+
+       OSLockAcquire(g_hProcessHandleBaseLock);
+
+       psBase = (PROCESS_HANDLE_BASE*) HASH_Retrieve(g_psProcessHandleBaseTable, uiPid);
+
+       /* In case there is none we are going to allocate one */
+       if (psBase == NULL)
+       {
+               IMG_BOOL bSuccess;
+
+               psBase = OSAllocZMem(sizeof(*psBase));
+               PVR_LOG_GOTO_IF_NOMEM(psBase, eError, ErrorUnlock);
+
+               /* Allocate handle base for this process */
+               eError = PVRSRVAllocHandleBase(&psBase->psHandleBase, PVRSRV_HANDLE_BASE_TYPE_PROCESS);
+               PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandleBase", ErrorFreeProcessHandleBase);
+
+               /* Insert the handle base into the global hash table */
+               bSuccess = HASH_Insert(g_psProcessHandleBaseTable, uiPid, (uintptr_t) psBase);
+               PVR_LOG_GOTO_IF_FALSE(bSuccess, "HASH_Insert failed", ErrorFreeHandleBase);
+       }
+
+       OSAtomicIncrement(&psBase->iRefCount);
+
+       OSLockRelease(g_hProcessHandleBaseLock);
+
+       *ppsBase = psBase;
+
+       return PVRSRV_OK;
+
+ErrorFreeHandleBase:
+       PVRSRVFreeHandleBase(psBase->psHandleBase, 0);
+ErrorFreeProcessHandleBase:
+       OSFreeMem(psBase);
+ErrorUnlock:
+       OSLockRelease(g_hProcessHandleBaseLock);
+
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function      PVRSRVReleaseProcessHandleBase
+ @Description   Decrements reference count on a process handle base psBase
+                for a process identified by uiPid. If the reference count
+                reaches 0 the handle base will be freed..
+ @Input         psBase - pointer to a process handle base
+ @Inout         uiPid - PID of a process
+ @Inout         ui64MaxBridgeTime - maximum time a handle destroy operation
+                                    can hold the handle base lock (after that
+                                    time a lock will be release and reacquired
+                                    for another time slice)
+ @Return        Error code or PVRSRV_OK
+******************************************************************************/
+PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID uiPid,
+                                            IMG_UINT64 ui64MaxBridgeTime)
+{
+       PVRSRV_ERROR eError;
+       IMG_INT iRefCount;
+       uintptr_t uiHashValue;
+
+       OSLockAcquire(g_hProcessHandleBaseLock);
+
+       iRefCount = OSAtomicDecrement(&psBase->iRefCount);
+
+       if (iRefCount != 0)
+       {
+               OSLockRelease(g_hProcessHandleBaseLock);
+               return PVRSRV_OK;
+       }
+
+       /* in case the refcount becomes 0 we can remove the process handle base
+        * and all related objects */
+
+       uiHashValue = HASH_Remove(g_psProcessHandleBaseTable, uiPid);
+       OSLockRelease(g_hProcessHandleBaseLock);
+
+       PVR_LOG_RETURN_IF_FALSE(uiHashValue != 0, "HASH_Remove failed",
+                               PVRSRV_ERROR_UNABLE_TO_REMOVE_HASH_VALUE);
+
+       eError = PVRSRVFreeKernelHandles(psBase->psHandleBase);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVFreeKernelHandles");
+
+       eError = PVRSRVFreeHandleBase(psBase->psHandleBase, ui64MaxBridgeTime);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVFreeHandleBase");
+
+       OSFreeMem(psBase);
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
  @Function      PVRSRVFreeHandleBase
  @Description   Free a handle base structure
  @Input         psBase - pointer to handle base structure
@@ -2120,20 +2283,21 @@ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase, IMG_UINT64 ui64Max
        FREE_HANDLE_DATA sHandleData = {NULL};
        IMG_UINT32 i;
        PVRSRV_ERROR eError;
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-       IMG_PID uiCleanupPid = psPVRSRVData->cleanupThreadPid;
+       IMG_PID uiCleanupPid = PVRSRVCleanupThreadGetPid();
+       uintptr_t uiCleanupTid = PVRSRVCleanupThreadGetTid();
 
        PVR_ASSERT(gpsHandleFuncs);
 
-       /* LockHandle(psBase); - func only run in single thread ctx */
+       LockHandle(psBase);
 
        /* If this is a process handle base being freed by the cleanup
-        * thread, store this in psPVRSRVData->psProcessHandleBaseBeingFreed
+        * thread, store this in g_psProcessHandleBaseBeingFreed
         */
-       if ((OSGetCurrentClientProcessIDKM() == uiCleanupPid) &&
+       if ((OSGetCurrentProcessID() == uiCleanupPid) &&
+           (OSGetCurrentThreadID() == uiCleanupTid) &&
            (psBase->eType == PVRSRV_HANDLE_BASE_TYPE_PROCESS))
        {
-               psPVRSRVData->psProcessHandleBaseBeingFreed = psBase;
+               g_psProcessHandleBaseBeingFreed = psBase;
        }
 
        sHandleData.psBase = psBase;
@@ -2152,7 +2316,7 @@ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase, IMG_UINT64 ui64Max
 
        if (sCountData.uiHandleDataCount != 0)
        {
-               IMG_BOOL bList = sCountData.uiHandleDataCount < HANDLE_DEBUG_LISTING_MAX_NUM;
+               IMG_BOOL bList = (IMG_BOOL)(sCountData.uiHandleDataCount < HANDLE_DEBUG_LISTING_MAX_NUM);
 
                PVR_DPF((PVR_DBG_WARNING,
                         "%s: %u remaining handles in handle base 0x%p "
@@ -2200,18 +2364,19 @@ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase, IMG_UINT64 ui64Max
        eError = gpsHandleFuncs->pfnDestroyHandleBase(psBase->psImplBase);
        PVR_GOTO_IF_ERROR(eError, ExitUnlock);
 
-       /* UnlockHandle(psBase); - func only run in single thread ctx */
+       UnlockHandle(psBase);
        OSLockDestroy(psBase->hLock);
        OSFreeMem(psBase);
 
        return eError;
 
 ExitUnlock:
-       if (OSGetCurrentClientProcessIDKM() == uiCleanupPid)
+       if ((OSGetCurrentProcessID() == uiCleanupPid) &&
+               (OSGetCurrentThreadID() == uiCleanupTid))
        {
-               psPVRSRVData->psProcessHandleBaseBeingFreed = NULL;
+               g_psProcessHandleBaseBeingFreed = NULL;
        }
-       /* UnlockHandle(psBase); - func only run in single thread ctx */
+       UnlockHandle(psBase);
 
        return eError;
 }
@@ -2228,10 +2393,15 @@ PVRSRV_ERROR PVRSRVHandleInit(void)
 
        PVR_ASSERT(gpsKernelHandleBase == NULL);
        PVR_ASSERT(gpsHandleFuncs == NULL);
+       PVR_ASSERT(g_hProcessHandleBaseLock == NULL);
+       PVR_ASSERT(g_psProcessHandleBaseTable == NULL);
        PVR_ASSERT(!gbLockInitialised);
 
        eError = OSLockCreate(&gKernelHandleLock);
-       PVR_LOG_RETURN_IF_ERROR(eError, "OSLockCreate");
+       PVR_LOG_RETURN_IF_ERROR(eError, "OSLockCreate:1");
+
+       eError = OSLockCreate(&g_hProcessHandleBaseLock);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate:2", ErrorHandleDeinit);
 
        gbLockInitialised = IMG_TRUE;
 
@@ -2242,9 +2412,11 @@ PVRSRV_ERROR PVRSRVHandleInit(void)
                                       PVRSRV_HANDLE_BASE_TYPE_GLOBAL);
        PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandleBase", ErrorHandleDeinit);
 
+       g_psProcessHandleBaseTable = HASH_Create(HANDLE_PROC_HANDLE_HASH_INIT_SIZE);
+       PVR_LOG_GOTO_IF_NOMEM(g_psProcessHandleBaseTable, eError, ErrorHandleDeinit);
+
        eError = gpsHandleFuncs->pfnEnableHandlePurging(gpsKernelHandleBase->psImplBase);
-       PVR_LOG_GOTO_IF_ERROR(eError, "pfnEnableHandlePurging",
-                         ErrorHandleDeinit);
+       PVR_LOG_GOTO_IF_ERROR(eError, "pfnEnableHandlePurging", ErrorHandleDeinit);
 
        return PVRSRV_OK;
 
@@ -2290,7 +2462,19 @@ PVRSRV_ERROR PVRSRVHandleDeInit(void)
                PVR_ASSERT(gpsKernelHandleBase == NULL);
        }
 
-       if (gbLockInitialised)
+       if (g_psProcessHandleBaseTable != NULL)
+       {
+               HASH_Delete(g_psProcessHandleBaseTable);
+               g_psProcessHandleBaseTable = NULL;
+       }
+
+       if (g_hProcessHandleBaseLock != NULL)
+       {
+               OSLockDestroy(g_hProcessHandleBaseLock);
+               g_hProcessHandleBaseLock = NULL;
+       }
+
+       if (gKernelHandleLock != NULL)
        {
                OSLockDestroy(gKernelHandleLock);
                gbLockInitialised = IMG_FALSE;
index 6d3becc..2ada5ab 100644 (file)
@@ -157,6 +157,8 @@ static HTB_CTRL_INFO g_sCtrl;
 static IMG_BOOL g_bConfigured = IMG_FALSE;
 static IMG_HANDLE g_hTLStream;
 
+static IMG_HANDLE hHtbDbgReqNotify;
+
 
 /************************************************************************/ /*!
  @Function      _LookupFlags
@@ -222,49 +224,6 @@ static void _HTBLogDebugInfo(
        }
 }
 
-/************************************************************************/ /*!
- @Function      HTBDeviceCreate
- @Description   Initialisation actions for HTB at device creation.
-
- @Input         psDeviceNode    Reference to the device node in context
-
- @Return        eError          Internal services call returned eError error
-                                number
-*/ /**************************************************************************/
-PVRSRV_ERROR
-HTBDeviceCreate(
-               PVRSRV_DEVICE_NODE *psDeviceNode
-)
-{
-       PVRSRV_ERROR eError;
-
-       eError = PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hHtbDbgReqNotify,
-                        psDeviceNode, &_HTBLogDebugInfo, DEBUG_REQUEST_HTB, NULL);
-       PVR_LOG_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify");
-
-       return eError;
-}
-
-/************************************************************************/ /*!
- @Function      HTBIDeviceDestroy
- @Description   De-initialisation actions for HTB at device destruction.
-
- @Input         psDeviceNode    Reference to the device node in context
-
-*/ /**************************************************************************/
-void
-HTBDeviceDestroy(
-               PVRSRV_DEVICE_NODE *psDeviceNode
-)
-{
-       if (psDeviceNode->hHtbDbgReqNotify)
-       {
-               /* No much we can do if it fails, driver unloading */
-               (void)PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hHtbDbgReqNotify);
-               psDeviceNode->hHtbDbgReqNotify = NULL;
-       }
-}
-
 static IMG_UINT32 g_ui32HTBufferSize = HTB_TL_BUFFER_SIZE_MIN;
 
 /*
@@ -332,7 +291,7 @@ HTBInit(void)
         */
        OSCreateKMAppHintState(&pvAppHintState);
        ui32AppHintDefault = HTB_TL_BUFFER_SIZE_MIN / 1024;
-       OSGetKMAppHintUINT32(pvAppHintState, HTBufferSizeInKB,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, HTBufferSizeInKB,
                                                 &ui32AppHintDefault, &g_ui32HTBufferSize);
        OSFreeKMAppHintState(pvAppHintState);
 
@@ -353,6 +312,10 @@ HTBInit(void)
        eError = OSSpinLockCreate(&g_sCtrl.hRepeatMarkerLock);
        PVR_LOG_RETURN_IF_ERROR(eError, "OSSpinLockCreate");
 
+       eError = PVRSRVRegisterDriverDbgRequestNotify(&hHtbDbgReqNotify,
+                        _HTBLogDebugInfo, DEBUG_REQUEST_HTB, NULL);
+       PVR_LOG_IF_ERROR(eError, "PVRSRVRegisterDeviceDbgRequestNotify");
+
        g_sCtrl.bInitDone = IMG_TRUE;
 
        /* Log the current driver parameter setting for the HTBufferSizeInKB.
@@ -364,6 +327,7 @@ HTBInit(void)
                PVR_LOG(("Increasing HTBufferSize to %uKB", g_ui32HTBufferSize));
        }
 
+
        return PVRSRV_OK;
 }
 
@@ -381,6 +345,13 @@ HTBDeInit( void )
        if (!g_sCtrl.bInitDone)
                return PVRSRV_OK;
 
+       if (hHtbDbgReqNotify)
+       {
+               /* Not much we can do if it fails, driver unloading */
+               (void)PVRSRVUnregisterDriverDbgRequestNotify(hHtbDbgReqNotify);
+               hHtbDbgReqNotify = NULL;
+       }
+
        if (g_hTLStream)
        {
                TLStreamClose( g_hTLStream );
index 1609ed6..77471b3 100644 (file)
@@ -47,19 +47,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv.h"
 #include "devicemem.h"
 #include "pmr.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 PVRSRV_ERROR InfoPageCreate(PVRSRV_DATA *psData)
 {
-#ifdef CACHE_TEST
-    struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
     const PVRSRV_MEMALLOCFLAGS_T uiMemFlags = PVRSRV_MEMALLOCFLAG_CPU_READABLE |
                                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
-                                              PVRSRV_MEMALLOCFLAG_CPU_UNCACHED |/* zz  chage to uncahed wc */
+                                              PVRSRV_MEMALLOCFLAG_CPU_UNCACHED |
                                               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(CPU_LOCAL);
     PVRSRV_ERROR eError;
@@ -79,15 +73,6 @@ PVRSRV_ERROR InfoPageCreate(PVRSRV_DATA *psData)
     eError =  DevmemAcquireCpuVirtAddr(psData->psInfoPageMemDesc,
                                        (void **) &psData->pui32InfoPage);
     PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAllocateExportable", e0);
-#ifdef CACHE_TEST
-    pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psData->psInfoPageMemDesc;
-    printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-    if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-    {
-        printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-        BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psData->pui32InfoPage - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-    }
-#endif
 
     /* Look-up the memory descriptor PMR handle */
     eError = DevmemLocalGetImportHandle(psData->psInfoPageMemDesc,
index 39c2985..1d9bfd7 100644 (file)
@@ -337,7 +337,7 @@ _FreeMMUMapping(PVRSRV_DEVICE_NODE *psDevNode,
                                                                 MMU_MEMORY_MAPPING,
                                                                 sMMUMappingItem);
 
-               psDevNode->sDevMMUPxSetup.pfnDevPxFree(psDevNode, &psMapping->sMemHandle);
+               PhysHeapPagesFree(psDevNode->psMMUPhysHeap, &psMapping->sMemHandle);
                dllist_remove_node(psNode);
                OSFreeMem(psMapping);
        }
@@ -722,10 +722,10 @@ void RGXMapBRN71422TargetPhysicalAddress(MMU_CONTEXT *psMMUContext)
        {
                PVRSRV_ERROR eError;
                PVRSRV_DEVICE_NODE *psDevNode = (PVRSRV_DEVICE_NODE *)psMMUContext->psPhysMemCtx->psDevNode;
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                                                                &psMemDesc->psMapping->sMemHandle,
-                                                                                                                psMemDesc->uiOffset,
-                                                                                                                psMemDesc->uiSize);
+               eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                           &psMemDesc->psMapping->sMemHandle,
+                                           psMemDesc->uiOffset,
+                                           psMemDesc->uiSize);
                PVR_LOG_IF_ERROR(eError, "pfnDevPxClean");
        }
 
@@ -795,18 +795,18 @@ static PVRSRV_ERROR _MMU_PhysMem_RAImportAlloc(RA_PERARENA_HANDLE hArenaHandle,
         * pfnDevPxFree() routine.
         */
        psMapping->sMemHandle.uiOSid = psPhysMemCtx->ui32OSid;
-       eError = psDevNode->sDevMMUPxSetup.pfnDevPxAllocGPV(psDevNode,
-                                                           TRUNCATE_64BITS_TO_SIZE_T(uiSize),
-                                                           &psMapping->sMemHandle,
-                                                           &psMapping->sDevPAddr,
-                                                           psPhysMemCtx->ui32OSid,
-                                                           uiPid);
+       eError = PhysHeapPagesAllocGPV(psDevNode->psMMUPhysHeap,
+                                      TRUNCATE_64BITS_TO_SIZE_T(uiSize),
+                                      &psMapping->sMemHandle,
+                                      &psMapping->sDevPAddr,
+                                      psPhysMemCtx->ui32OSid,
+                                      uiPid);
 #else
-       eError = psDevNode->sDevMMUPxSetup.pfnDevPxAlloc(psDevNode,
-                                                        TRUNCATE_64BITS_TO_SIZE_T(uiSize),
-                                                        &psMapping->sMemHandle,
-                                                        &psMapping->sDevPAddr,
-                                                        uiPid);
+       eError = PhysHeapPagesAlloc(psDevNode->psMMUPhysHeap,
+                                   TRUNCATE_64BITS_TO_SIZE_T(uiSize),
+                                   &psMapping->sMemHandle,
+                                   &psMapping->sDevPAddr,
+                                   uiPid);
 #endif
        if (eError != PVRSRV_OK)
        {
@@ -915,11 +915,11 @@ static PVRSRV_ERROR _MMU_PhysMemAlloc(MMU_PHYSMEM_CONTEXT *psPhysMemCtx,
 
        if (psMemDesc->psMapping->uiCpuVAddrRefCount == 0)
        {
-               eError = psPhysMemCtx->psDevNode->sDevMMUPxSetup.pfnDevPxMap(psPhysMemCtx->psDevNode,
-                                                                            &psMemDesc->psMapping->sMemHandle,
-                                                                            psMemDesc->psMapping->uiSize,
-                                                                            &psMemDesc->psMapping->sDevPAddr,
-                                                                            &psMemDesc->psMapping->pvCpuVAddr);
+               eError = PhysHeapPagesMap(psPhysMemCtx->psDevNode->psMMUPhysHeap,
+                                         &psMemDesc->psMapping->sMemHandle,
+                                         psMemDesc->psMapping->uiSize,
+                                         &psMemDesc->psMapping->sDevPAddr,
+                                         &psMemDesc->psMapping->pvCpuVAddr);
                if (eError != PVRSRV_OK)
                {
                        RA_Free(psPhysMemCtx->psPhysMemRA, psMemDesc->sDevPAddr.uiAddr);
@@ -957,9 +957,9 @@ static void _MMU_PhysMemFree(MMU_PHYSMEM_CONTEXT *psPhysMemCtx,
 
        if (--psMemDesc->psMapping->uiCpuVAddrRefCount == 0)
        {
-               psPhysMemCtx->psDevNode->sDevMMUPxSetup.pfnDevPxUnMap(psPhysMemCtx->psDevNode,
-                                                                     &psMemDesc->psMapping->sMemHandle,
-                                                                     psMemDesc->psMapping->pvCpuVAddr);
+               PhysHeapPagesUnMap(psPhysMemCtx->psDevNode->psMMUPhysHeap,
+                                  &psMemDesc->psMapping->sMemHandle,
+                                  psMemDesc->psMapping->pvCpuVAddr);
        }
 
        psMemDesc->pvCpuVAddr = NULL;
@@ -1125,23 +1125,25 @@ static PVRSRV_ERROR _PxMemAlloc(MMU_CONTEXT *psMMUContext,
         */
        OSCachedMemSet(psMemDesc->pvCpuVAddr, 0, uiBytes);
 
-       eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                        &psMemDesc->psMapping->sMemHandle,
-                                                        psMemDesc->uiOffset,
-                                                        psMemDesc->uiSize);
+       eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                   &psMemDesc->psMapping->sMemHandle,
+                                   psMemDesc->uiOffset,
+                                   psMemDesc->uiSize);
        PVR_GOTO_IF_ERROR(eError, e1);
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Alloc MMU object");
+       PDUMPCOMMENT(psDevNode, "Alloc MMU object");
 
-       PDumpMMUMalloc(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+       PDumpMMUMalloc(psDevNode,
+                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                       eMMULevel,
                       &psMemDesc->sDevPAddr,
                       uiBytes,
                       uiAlign,
                       psMMUContext->psDevAttrs->eMMUType);
 
-       PDumpMMUDumpPxEntries(eMMULevel,
+       PDumpMMUDumpPxEntries(psDevNode,
+                             eMMULevel,
                              psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                              psMemDesc->pvCpuVAddr,
                              psMemDesc->sDevPAddr,
@@ -1193,13 +1195,14 @@ static void _PxMemFree(MMU_CONTEXT *psMMUContext,
        OSCachedMemSet(psMemDesc->pvCpuVAddr, 0, psMemDesc->ui32Bytes);
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Clear MMU object before freeing it");
+       PDUMPCOMMENT(psMMUContext->psPhysMemCtx->psDevNode, "Clear MMU object before freeing it");
 #endif
 #endif/* MMU_CLEARMEM_ON_FREE */
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Free MMU object");
-       PDumpMMUFree(psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
+       PDUMPCOMMENT(psMMUContext->psPhysMemCtx->psDevNode, "Free MMU object");
+       PDumpMMUFree(psMMUContext->psPhysMemCtx->psDevNode,
+                    psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                     eMMULevel,
                     &psMemDesc->sDevPAddr,
                     psMMUContext->psDevAttrs->eMMUType);
@@ -1275,7 +1278,8 @@ static INLINE PVRSRV_ERROR _SetupPTE(MMU_CONTEXT *psMMUContext,
                !bUnmap);
 
 #if defined(PDUMP)
-       PDumpMMUDumpPxEntries(MMU_LEVEL_1,
+       PDumpMMUDumpPxEntries(psDevNode,
+                             MMU_LEVEL_1,
                              psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                              psMemDesc->pvCpuVAddr,
                              psMemDesc->sDevPAddr,
@@ -1446,7 +1450,8 @@ static PVRSRV_ERROR _SetupPxE(MMU_CONTEXT *psMMUContext,
        }
 
 #if defined(PDUMP)
-       PDumpMMUDumpPxEntries(eMMULevel,
+       PDumpMMUDumpPxEntries(psDevNode,
+                             eMMULevel,
                              psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                              psMemDesc->pvCpuVAddr,
                              psMemDesc->sDevPAddr,
@@ -1649,10 +1654,10 @@ static IMG_BOOL _MMU_FreeLevel(MMU_CONTEXT *psMMUContext,
        /* Level one flushing is done when we actually write the table entries */
        if ((aeMMULevel[uiThisLevel] != MMU_LEVEL_1) && (psLevel != NULL))
        {
-               psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                       &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                       uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                       (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
+               PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                  &psLevel->sMemDesc.psMapping->sMemHandle,
+                                  uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                  (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
        }
 
        MMU_OBJ_DBG((PVR_DBG_ERROR, "_MMU_FreeLevel end: level = %d, refcount = %d",
@@ -1867,10 +1872,10 @@ static PVRSRV_ERROR _MMU_AllocLevel(MMU_CONTEXT *psMMUContext,
        /* Level one flushing is done when we actually write the table entries */
        if (aeMMULevel[uiThisLevel] != MMU_LEVEL_1)
        {
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                                uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                                (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
+               eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                           &psLevel->sMemDesc.psMapping->sMemHandle,
+                                           uiStartIndex * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                           (uiEndIndex - uiStartIndex) * psConfig->uiBytesPerEntry);
                PVR_GOTO_IF_ERROR(eError, e0);
        }
 
@@ -2149,7 +2154,8 @@ _AllocPageTables(MMU_CONTEXT *psMMUContext,
        ));
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Allocating page tables for %"IMG_UINT64_FMTSPEC" bytes virtual range: "
+       PDUMPCOMMENT(psMMUContext->psPhysMemCtx->psDevNode,
+                    "Allocating page tables for %"IMG_UINT64_FMTSPEC" bytes virtual range: "
                     IMG_DEV_VIRTADDR_FMTSPEC":"IMG_DEV_VIRTADDR_FMTSPEC,
                     (IMG_UINT64)sDevVAddrEnd.uiAddr - (IMG_UINT64)sDevVAddrStart.uiAddr,
                     (IMG_UINT64)sDevVAddrStart.uiAddr,
@@ -2261,7 +2267,7 @@ static void _FreePageTables(MMU_CONTEXT *psMMUContext,
 static INLINE void _MMU_GetPTInfo(MMU_CONTEXT                *psMMUContext,
                                   IMG_DEV_VIRTADDR            sDevVAddr,
                                   const MMU_DEVVADDR_CONFIG  *psDevVAddrConfig,
-                                  MMU_Levelx_INFO           **psLevel,
+                                  MMU_Levelx_INFO           **ppsLevel,
                                   IMG_UINT32                 *pui32PTEIndex)
 {
        MMU_Levelx_INFO *psLocalLevel = NULL;
@@ -2272,8 +2278,7 @@ static INLINE void _MMU_GetPTInfo(MMU_CONTEXT                *psMMUContext,
        if ((eMMULevel <= MMU_LEVEL_0) || (eMMULevel >= MMU_LEVEL_LAST))
        {
                PVR_DPF((PVR_DBG_ERROR, "_MMU_GetPTEInfo: Invalid MMU level"));
-               psLevel = NULL;
-               return;
+               PVR_ASSERT(0);
        }
 
        for (; eMMULevel > MMU_LEVEL_0; eMMULevel--)
@@ -2313,7 +2318,7 @@ static INLINE void _MMU_GetPTInfo(MMU_CONTEXT                *psMMUContext,
                        }
                }
        }
-       *psLevel = psLocalLevel;
+       *ppsLevel = psLocalLevel;
 }
 
 /*************************************************************************/ /*!
@@ -2417,7 +2422,7 @@ MMU_ContextCreate(CONNECTION_DATA *psConnection,
        PVRSRV_ERROR eError = PVRSRV_OK;
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("MMU context create");
+       PDUMPCOMMENT(psDevNode, "MMU context create");
 #endif
 
        psConfig = psDevAttrs->psBaseConfig;
@@ -2493,7 +2498,7 @@ MMU_ContextCreate(CONNECTION_DATA *psConnection,
 
        psPhysMemCtx->psPhysMemRA = RA_Create(psPhysMemCtx->pszPhysMemRAName,
                                              /* subsequent import */
-                                             psDevNode->sDevMMUPxSetup.uiMMUPxLog2AllocGran,
+                                             PhysHeapGetPageShift(psDevNode->psMMUPhysHeap),
                                              RA_LOCKCLASS_1,
                                              _MMU_PhysMem_RAImportAlloc,
                                              _MMU_PhysMem_RAImportFree,
@@ -2833,21 +2838,10 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext,
        IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
 
-       PDUMPCOMMENT("Wire up Page Table entries to point to the Data Pages (%"IMG_INT64_FMTSPECd" bytes)",
+       PDUMPCOMMENT(psMMUContext->psPhysMemCtx->psDevNode, "Wire up Page Table entries to point to the Data Pages (%"IMG_INT64_FMTSPECd" bytes)",
                     (IMG_UINT64)(ui32MapPageCount * uiPageSize));
 #endif /*PDUMP*/
 
-#if defined(TC_MEMORY_CONFIG) || defined(PLATO_MEMORY_CONFIG)
-       /* We're aware that on TC based platforms, accesses from GPU to CPU_LOCAL
-        * allocated DevMem fail, so we forbid mapping such a PMR into device mmu */
-       if (PVRSRV_CHECK_PHYS_HEAP(CPU_LOCAL, PMR_Flags(psPMR)))
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Mapping a CPU_LOCAL PMR to device is forbidden on this platform", __func__));
-               return PVRSRV_ERROR_PMR_NOT_PERMITTED;
-       }
-#endif
-
        /* Validate the most essential parameters */
        PVR_LOG_GOTO_IF_INVALID_PARAM(psMMUContext, eError, e0);
        PVR_LOG_GOTO_IF_INVALID_PARAM(psPMR, eError, e0);
@@ -2946,17 +2940,11 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext,
                        {
                                uiDummyProtFlags = psMMUContext->psDevAttrs->pfnDerivePTEProt8(uiMMUProtFlags , uiLog2HeapPageSize);
                        }
-                       else if (psConfig->uiBytesPerEntry == 4)
-                       {
-                               uiDummyProtFlags = psMMUContext->psDevAttrs->pfnDerivePTEProt4(uiMMUProtFlags);
-                       }
                        else
                        {
-                               PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: The page table entry byte length is not supported",
-                                        __func__));
-                               eError = PVRSRV_ERROR_INVALID_PARAMS;
-                               goto e2;
+                               /* We've already validated possible values of uiBytesPerEntry at the start of this function */
+                               PVR_ASSERT(psConfig->uiBytesPerEntry == 4);
+                               uiDummyProtFlags = psMMUContext->psDevAttrs->pfnDerivePTEProt4(uiMMUProtFlags);
                        }
                }
        }
@@ -3080,10 +3068,10 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext,
                                /* Flush if we moved to another psLevel, i.e. page table */
                                if (psPrevLevel != NULL)
                                {
-                                       eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                                        &psPrevLevel->sMemDesc.psMapping->sMemHandle,
-                                                                                        uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
-                                                                                        (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+                                       eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                                                   &psPrevLevel->sMemDesc.psMapping->sMemHandle,
+                                                                   uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
+                                                                   (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
                                        PVR_GOTO_IF_ERROR(eError, e3);
                                }
 
@@ -3130,10 +3118,10 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext,
        /* Flush the last level we touched */
        if (psLevel != NULL)
        {
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                                uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                                (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+               eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                           &psLevel->sMemDesc.psMapping->sMemHandle,
+                                           uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                           (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
                PVR_GOTO_IF_ERROR(eError, e3);
        }
 
@@ -3154,7 +3142,7 @@ MMU_MapPages(MMU_CONTEXT *psMMUContext,
                                         IMG_FALSE);
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Wired up %d Page Table entries (out of %d)", ui32MappedCount, ui32MapPageCount);
+       PDUMPCOMMENT(psDevNode, "Wired up %d Page Table entries (out of %d)", ui32MappedCount, ui32MapPageCount);
 #endif /*PDUMP*/
 
        return PVRSRV_OK;
@@ -3215,7 +3203,8 @@ MMU_UnmapPages(MMU_CONTEXT *psMMUContext,
        PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psPhysMemCtx->psDevNode;
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Invalidate %d entries in page tables for virtual range: 0x%010"IMG_UINT64_FMTSPECX" to 0x%010"IMG_UINT64_FMTSPECX,
+       PDUMPCOMMENT(psDevNode,
+                    "Invalidate %d entries in page tables for virtual range: 0x%010"IMG_UINT64_FMTSPECX" to 0x%010"IMG_UINT64_FMTSPECX,
                     ui32PageCount,
                     (IMG_UINT64)sDevVAddr.uiAddr,
                     ((IMG_UINT64)sDevVAddr.uiAddr) + (uiPageSize*ui32PageCount)-1);
@@ -3296,10 +3285,10 @@ MMU_UnmapPages(MMU_CONTEXT *psMMUContext,
                        /* Flush if we moved to another psLevel, i.e. page table */
                        if (psPrevLevel != NULL)
                        {
-                               psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                       &psPrevLevel->sMemDesc.psMapping->sMemHandle,
-                                                                       uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
-                                                                       (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+                               PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                                  &psPrevLevel->sMemDesc.psMapping->sMemHandle,
+                                                  uiFlushStart * psConfig->uiBytesPerEntry + psPrevLevel->sMemDesc.uiOffset,
+                                                  (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
                        }
 
                        uiFlushStart = uiPTEIndex;
@@ -3335,10 +3324,10 @@ MMU_UnmapPages(MMU_CONTEXT *psMMUContext,
        /* Flush the last level we touched */
        if (psLevel != NULL)
        {
-               psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                       &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                       uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                       (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+               PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                  &psLevel->sMemDesc.psMapping->sMemHandle,
+                                  uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                  (uiFlushEnd+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
        }
 
        OSLockRelease(psMMUContext->hLock);
@@ -3392,7 +3381,7 @@ MMU_MapPMRFast (MMU_CONTEXT *psMMUContext,
        IMG_CHAR aszSymbolicAddress[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
        IMG_UINT32 ui32MappedCount = 0;
-       PDUMPCOMMENT("Wire up Page Table entries to point to the Data Pages (%"IMG_INT64_FMTSPECd" bytes)", uiSizeBytes);
+       PDUMPCOMMENT(psDevNode, "Wire up Page Table entries to point to the Data Pages (%"IMG_INT64_FMTSPECd" bytes)", uiSizeBytes);
 #endif /*PDUMP*/
 
        /* We should verify the size and contiguity when supporting variable page size */
@@ -3400,17 +3389,6 @@ MMU_MapPMRFast (MMU_CONTEXT *psMMUContext,
        PVR_ASSERT (psMMUContext != NULL);
        PVR_ASSERT (psPMR != NULL);
 
-#if defined(TC_MEMORY_CONFIG) || defined(PLATO_MEMORY_CONFIG)
-       /* We're aware that on TC based platforms, accesses from GPU to CPU_LOCAL
-        * allocated DevMem fail, so we forbid mapping such a PMR into device mmu */
-       if (PVRSRV_CHECK_PHYS_HEAP(CPU_LOCAL, PMR_Flags(psPMR)))
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Mapping a CPU_LOCAL PMR to device is forbidden on this platform", __func__));
-               return PVRSRV_ERROR_PMR_NOT_PERMITTED;
-       }
-#endif
-
        /* Allocate memory for page-frame-numbers and validity states,
           N.B. assert could be triggered by an illegal uiSizeBytes */
        uiCount = uiSizeBytes >> uiLog2HeapPageSize;
@@ -3544,10 +3522,10 @@ MMU_MapPMRFast (MMU_CONTEXT *psMMUContext,
                }
                else
                {
-                       eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                        &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                                        uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                                        (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+                       eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                                   &psLevel->sMemDesc.psMapping->sMemHandle,
+                                                   uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                                   (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
                        PVR_GOTO_IF_ERROR(eError, unlock_mmu_context);
 
 
@@ -3575,7 +3553,7 @@ MMU_MapPMRFast (MMU_CONTEXT *psMMUContext,
                                         IMG_FALSE);
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Wired up %d Page Table entries (out of %d)", ui32MappedCount, i);
+       PDUMPCOMMENT(psDevNode, "Wired up %d Page Table entries (out of %d)", ui32MappedCount, i);
 #endif /*PDUMP*/
 
        return PVRSRV_OK;
@@ -3629,7 +3607,8 @@ MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
        PVRSRV_DEVICE_NODE *psDevNode = psMMUContext->psPhysMemCtx->psDevNode;
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Invalidate %d entries in page tables for virtual range: 0x%010"IMG_UINT64_FMTSPECX" to 0x%010"IMG_UINT64_FMTSPECX,
+       PDUMPCOMMENT(psDevNode,
+                    "Invalidate %d entries in page tables for virtual range: 0x%010"IMG_UINT64_FMTSPECX" to 0x%010"IMG_UINT64_FMTSPECX,
                     ui32PageCount,
                     (IMG_UINT64)sDevVAddr.uiAddr,
                     ((IMG_UINT64)sDevVAddr.uiAddr) + (uiPageSize*ui32PageCount)-1);
@@ -3687,16 +3666,10 @@ MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
                {
                        ((IMG_UINT64*)psLevel->sMemDesc.pvCpuVAddr)[uiPTEIndex] = uiEntry;
                }
-               else if (psConfig->uiBytesPerEntry == 4)
-               {
-                       ((IMG_UINT32*)psLevel->sMemDesc.pvCpuVAddr)[uiPTEIndex] = (IMG_UINT32) uiEntry;
-               }
                else
                {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                       "%s: The page table entry byte length is not supported",
-                                       __func__));
-                       goto e1;
+                       PVR_ASSERT(psConfig->uiBytesPerEntry == 4);
+                       ((IMG_UINT32*)psLevel->sMemDesc.pvCpuVAddr)[uiPTEIndex] = (IMG_UINT32) uiEntry;
                }
 
                /* Log modifications */
@@ -3710,7 +3683,8 @@ MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
                        IMG_FALSE);
 
 #if defined(PDUMP)
-               PDumpMMUDumpPxEntries(MMU_LEVEL_1,
+               PDumpMMUDumpPxEntries(psDevNode,
+                                     MMU_LEVEL_1,
                                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                                      psLevel->sMemDesc.pvCpuVAddr,
                                      psLevel->sMemDesc.sDevPAddr,
@@ -3739,10 +3713,10 @@ MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
                }
                else
                {
-                       psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                               &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                               uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                               (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+                       PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                          &psLevel->sMemDesc.psMapping->sMemHandle,
+                                          uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                          (uiPTEIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
 
                        _MMU_GetPTInfo(psMMUContext, sDevVAddr, psDevVAddrConfig,
                                       &psLevel, &uiPTEIndex);
@@ -3762,9 +3736,6 @@ MMU_UnmapPMRFast(MMU_CONTEXT *psMMUContext,
 
        return;
 
-e1:
-       OSLockRelease(psMMUContext->hLock);
-       _MMU_PutPTConfig(psMMUContext, hPriv);
 e0:
        PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map/unmap page table", __func__));
        PVR_ASSERT(0);
@@ -3802,7 +3773,8 @@ MMU_ChangeValidity(MMU_CONTEXT *psMMUContext,
        IMG_DEVMEM_OFFSET_T uiSymbolicAddrOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
 
-       PDUMPCOMMENT("Change valid bit of the data pages to %d (0x%"IMG_UINT64_FMTSPECX" - 0x%"IMG_UINT64_FMTSPECX")",
+       PDUMPCOMMENT(psDevNode,
+                    "Change valid bit of the data pages to %d (0x%"IMG_UINT64_FMTSPECX" - 0x%"IMG_UINT64_FMTSPECX")",
                     bMakeValid,
                     sDevVAddr.uiAddr,
                     sDevVAddr.uiAddr + (uiNumPages<<uiLog2PageSize) - 1);
@@ -3870,7 +3842,8 @@ MMU_ChangeValidity(MMU_CONTEXT *psMMUContext,
                                      &uiSymbolicAddrOffset,
                                      &uiNextSymName);
 
-               PDumpMMUDumpPxEntries(MMU_LEVEL_1,
+               PDumpMMUDumpPxEntries(psDevNode,
+                                     MMU_LEVEL_1,
                                      psMMUContext->psDevAttrs->pszMMUPxPDumpMemSpaceName,
                                      psLevel->sMemDesc.pvCpuVAddr,
                                      psLevel->sMemDesc.sDevPAddr,
@@ -3900,10 +3873,10 @@ MMU_ChangeValidity(MMU_CONTEXT *psMMUContext,
                else
                {
 
-                       eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                        &psLevel->sMemDesc.psMapping->sMemHandle,
-                                                                        uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
-                                                                        (uiPTIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
+                       eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                                   &psLevel->sMemDesc.psMapping->sMemHandle,
+                                                   uiFlushStart * psConfig->uiBytesPerEntry + psLevel->sMemDesc.uiOffset,
+                                                   (uiPTIndex+1 - uiFlushStart) * psConfig->uiBytesPerEntry);
                        PVR_GOTO_IF_ERROR(eError, e_exit);
 
                        _MMU_GetPTInfo(psMMUContext, sDevVAddr, psDevVAddrConfig,
@@ -3945,6 +3918,23 @@ MMU_AcquireBaseAddr(MMU_CONTEXT *psMMUContext, IMG_DEV_PHYADDR *psPhysAddr)
 }
 
 /*
+       MMU_AcquireCPUBaseAddr
+ */
+PVRSRV_ERROR
+MMU_AcquireCPUBaseAddr(MMU_CONTEXT *psMMUContext, void **ppvCPUVAddr)
+{
+       if (!psMMUContext)
+       {
+               *ppvCPUVAddr = NULL;
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       *ppvCPUVAddr = psMMUContext->sBaseLevelInfo.sMemDesc.pvCpuVAddr;
+
+       return PVRSRV_OK;
+}
+
+/*
        MMU_ReleaseBaseAddr
  */
 void
@@ -4006,6 +3996,9 @@ void MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext,
 {
        /* Ideally the RGX defs should be via callbacks, but the function is only called from RGX. */
 #if defined(SUPPORT_RGX)
+# define MMU_MASK_VALID_FOR_32BITS(level) \
+               ((RGX_MMUCTRL_##level##_DATA_ENTRY_PENDING_EN | \
+                 RGX_MMUCTRL_##level##_DATA_VALID_EN) <= 0xFFFFFFFF)
 # define MMU_VALID_STR(entry,level) \
                (apszMMUValidStr[((((entry)&(RGX_MMUCTRL_##level##_DATA_ENTRY_PENDING_EN))!=0) << 1)| \
                                 ((((entry)&(RGX_MMUCTRL_##level##_DATA_VALID_EN))!=0) << 0)])
@@ -4014,6 +4007,7 @@ void MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext,
                                                         /*P-*/ "pending",
                                                         /*PV*/ "inconsistent (pending and valid)"};
 #else
+# define MMU_MASK_VALID_FOR_32BITS(level) 0
 # define MMU_VALID_STR(entry,level) ("??")
 #endif
        MMU_DEVICEATTRIBS *psDevAttrs = psMMUContext->psDevAttrs;
@@ -4082,8 +4076,15 @@ void MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext,
                                IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
 
                                psMMULevelData->ui64Address = pui32Ptr[ui32PCIndex];
-                               psMMULevelData->psDebugStr  = MMU_VALID_STR(pui32Ptr[ui32PCIndex] & psConfig->uiProtMask, PC);
-
+                               if (MMU_MASK_VALID_FOR_32BITS(PC))
+                               {
+                                       psMMULevelData->psDebugStr = MMU_VALID_STR(pui32Ptr[ui32PCIndex] & psConfig->uiProtMask, PC);
+                               }
+                               else
+                               {
+                                       psMMULevelData->psDebugStr = "";
+                                       PVR_LOG(("Invalid RGX_MMUCTRL_PC_DATA_ENTRY mask for 32-bit entry"));
+                               }
                        }
                        else
                        {
@@ -4127,8 +4128,15 @@ void MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext,
                                IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
 
                                psMMULevelData->ui64Address = pui32Ptr[ui32PDIndex];
-                               psMMULevelData->psDebugStr  = MMU_VALID_STR(pui32Ptr[ui32PDIndex] & psMMUPDEConfig->uiProtMask, PD);
-
+                               if (MMU_MASK_VALID_FOR_32BITS(PD))
+                               {
+                                       psMMULevelData->psDebugStr = MMU_VALID_STR(pui32Ptr[ui32PDIndex] & psMMUPDEConfig->uiProtMask, PD);
+                               }
+                               else
+                               {
+                                       psMMULevelData->psDebugStr = "";
+                                       PVR_LOG(("Invalid RGX_MMUCTRL_PD_DATA_ENTRY mask for 32-bit entry"));
+                               }
 
                                if (psDevAttrs->pfnGetPageSizeFromPDE4(pui32Ptr[ui32PDIndex], &ui32Log2PageSize) != PVRSRV_OK)
                                {
@@ -4212,8 +4220,15 @@ void MMU_CheckFaultAddress(MMU_CONTEXT *psMMUContext,
                                IMG_UINT32 *pui32Ptr = psLevel->sMemDesc.pvCpuVAddr;
 
                                psMMULevelData->ui64Address = pui32Ptr[ui32PTIndex];
-                               psMMULevelData->psDebugStr  = MMU_VALID_STR(pui32Ptr[ui32PTIndex] & psMMUPTEConfig->uiProtMask, PT);
-
+                               if (MMU_MASK_VALID_FOR_32BITS(PT))
+                               {
+                                       psMMULevelData->psDebugStr = MMU_VALID_STR(pui32Ptr[ui32PTIndex] & psMMUPTEConfig->uiProtMask, PT);
+                               }
+                               else
+                               {
+                                       psMMULevelData->psDebugStr = "";
+                                       PVR_LOG(("Invalid RGX_MMUCTRL_PT_DATA_ENTRY mask for 32-bit entry"));
+                               }
                        }
                        else
                        {
@@ -4381,7 +4396,8 @@ MMU_PDumpWritePageCatBase(MMU_CONTEXT *psMMUContext,
                                                 sizeof(aszPageCatBaseSymbolicAddr));
        if (eError == PVRSRV_OK)
        {
-               eError = PDumpWriteSymbAddress(pszSpaceName,
+               eError = PDumpWriteSymbAddress(psMMUContext->psPhysMemCtx->psDevNode,
+                                              pszSpaceName,
                                               uiOffset,
                                               aszPageCatBaseSymbolicAddr,
                                               0, /* offset -- Could be non-zero for var. pgsz */
@@ -4406,7 +4422,8 @@ PVRSRV_ERROR MMU_AcquirePDumpMMUContext(MMU_CONTEXT *psMMUContext,
 
        if (!psMMUContext->ui32PDumpContextIDRefCount)
        {
-               PDUMP_MMU_ALLOC_MMUCONTEXT(psDevId->pszPDumpDevName,
+               PDUMP_MMU_ALLOC_MMUCONTEXT(psMMUContext->psPhysMemCtx->psDevNode,
+                                          psDevId->pszPDumpDevName,
                                           psMMUContext->sBaseLevelInfo.sMemDesc.sDevPAddr,
                                           psMMUContext->psDevAttrs->eMMUType,
                                           &psMMUContext->uiPDumpContextID,
@@ -4432,7 +4449,8 @@ PVRSRV_ERROR MMU_ReleasePDumpMMUContext(MMU_CONTEXT *psMMUContext,
 
        if (psMMUContext->ui32PDumpContextIDRefCount == 0)
        {
-               PDUMP_MMU_FREE_MMUCONTEXT(psDevId->pszPDumpDevName,
+               PDUMP_MMU_FREE_MMUCONTEXT(psMMUContext->psPhysMemCtx->psDevNode,
+                                         psDevId->pszPDumpDevName,
                                          psMMUContext->uiPDumpContextID,
                                          ui32PDumpFlags);
        }
index bc1547d..5b195d6 100644 (file)
@@ -71,7 +71,8 @@ static const IMG_CHAR * const apszMMULevelStringLookup[MMU_LEVEL_LAST] =
 };
 
 static PVRSRV_ERROR
-_ContiguousPDumpBytes(const IMG_CHAR *pszSymbolicName,
+_ContiguousPDumpBytes(PVRSRV_DEVICE_NODE *psDeviceNode,
+                     const IMG_CHAR *pszSymbolicName,
                      IMG_UINT32 ui32SymAddrOffset,
                      IMG_BOOL bFlush,
                      IMG_UINT32 uiNumBytes,
@@ -106,7 +107,8 @@ _ContiguousPDumpBytes(const IMG_CHAR *pszSymbolicName,
        /* Flush if necessary */
        if (bFlush && uiAccumulatedBytes > 0)
        {
-               eErr = PDumpWriteParameter((IMG_UINT8 *)(uintptr_t)pvBasePointer,
+               eErr = PDumpWriteParameter(psDeviceNode,
+                                          (IMG_UINT8 *)(uintptr_t)pvBasePointer,
                                           uiAccumulatedBytes, ui32Flags,
                                           &ui32ParamOutPos, pszFileName);
                if (eErr == PVRSRV_OK)
@@ -124,7 +126,7 @@ _ContiguousPDumpBytes(const IMG_CHAR *pszSymbolicName,
                                             pszFileName);
                        PVR_LOG_GOTO_IF_ERROR(eErr, "PDumpSNPrintf", ErrOut);
 
-                       PDumpWriteScript(hScript, ui32Flags);
+                       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                }
                else if (eErr != PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
                {
@@ -166,7 +168,8 @@ ErrOut:
  * Returns        : PVRSRV_ERROR
  * Description    :
 **************************************************************************/
-PVRSRV_ERROR PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
+PVRSRV_ERROR PDumpMMUMalloc(PVRSRV_DEVICE_NODE *psDeviceNode,
+                           const IMG_CHAR *pszPDumpDevName,
                            MMU_LEVEL eMMULevel,
                            IMG_DEV_PHYADDR *psDevPAddr,
                            IMG_UINT32 ui32Size,
@@ -197,7 +200,7 @@ PVRSRV_ERROR PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
                             psDevPAddr->uiAddr);
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        /*
          construct the symbolic address
@@ -223,7 +226,7 @@ PVRSRV_ERROR PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
                             ui32Align
                             /* don't need this sDevPAddr.uiAddr*/);
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 ErrUnlock:
        PDUMP_UNLOCK(ui32Flags);
@@ -239,7 +242,8 @@ ErrOut:
  * Returns        : PVRSRV_ERROR
  * Description    :
 **************************************************************************/
-PVRSRV_ERROR PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
+PVRSRV_ERROR PDumpMMUFree(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       const IMG_CHAR *pszPDumpDevName,
                          MMU_LEVEL eMMULevel,
                          IMG_DEV_PHYADDR *psDevPAddr,
                          PDUMP_MMU_TYPE eMMUType)
@@ -261,7 +265,7 @@ PVRSRV_ERROR PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
                             pszPDumpDevName, apszMMULevelStringLookup[eMMULevel]);
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        /*
          construct the symbolic address
@@ -284,7 +288,7 @@ PVRSRV_ERROR PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
                             pszMMUPX,
                             ui64SymbolicAddr);
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 ErrUnlock:
        PDUMP_UNLOCK(ui32Flags);
@@ -337,7 +341,7 @@ PVRSRV_ERROR PDumpPTBaseObjectToMem64(const IMG_CHAR *pszPDumpDevName,
        PVR_GOTO_IF_ERROR(eErr, Err);
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(PMR_DeviceNode(psPMRDest), hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
 Err:
@@ -352,7 +356,8 @@ Err:
  * Returns        : PVRSRV_ERROR
  * Description    :
 **************************************************************************/
-PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
+PVRSRV_ERROR PDumpMMUDumpPxEntries(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  MMU_LEVEL eMMULevel,
                                   const IMG_CHAR *pszPDumpDevName,
                                   void *pvPxMem,
                                   IMG_DEV_PHYADDR sPxDevPAddr,
@@ -470,7 +475,8 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                {
                        /* If the entry was "invalid", simply write the actual
                           value found to the memory location */
-                       eErr = _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_FALSE,
+                       eErr = _ContiguousPDumpBytes(psDeviceNode,aszPxSymbolicAddr,
+                                                    ui32SymAddrOffset, IMG_FALSE,
                                                     uiBytesPerEntry, pvRawBytes,
                                                     ui32Flags);
                        if (eErr == PVRSRV_OK)
@@ -483,7 +489,8 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                        }
                }
 
-               _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE,
+               _ContiguousPDumpBytes(psDeviceNode, aszPxSymbolicAddr,
+                                     ui32SymAddrOffset, IMG_TRUE,
                                      0, NULL,
                                      ui32Flags);
 
@@ -564,7 +571,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                }
 
                PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-               PDumpWriteScript(hScript, ui32Flags);
+               PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
                /* Now shift it to the right place, if necessary: */
                /* Now shift that value down, by the "Align shift"
@@ -589,7 +596,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                             /* src B */
                                             iShiftAmount);
                        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                       PDumpWriteScript(hScript, ui32Flags);
+                       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                }
                else if (iShiftAmount < 0)
                {
@@ -605,7 +612,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                             /* src B */
                                             -iShiftAmount);
                        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                       PDumpWriteScript(hScript, ui32Flags);
+                       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                }
 
                if (eMMULevel == MMU_LEVEL_1)
@@ -623,7 +630,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                                     /* src B */
                                                     ui64Protflags64);
                                PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                               PDumpWriteScript(hScript, ui32Flags);
+                               PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                                eErr = PDumpSNPrintf(hScript,
                                                     ui32MaxLen,
                                                     "WRW%s :%s:%s%016"IMG_UINT64_FMTSPECX":0x%08X :%s:$1",
@@ -636,7 +643,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                                     /* src */
                                                     pszPDumpDevName);
                                PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                               PDumpWriteScript(hScript, ui32Flags);
+                               PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                        }
                }
                else
@@ -652,7 +659,7 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                             /* src B */
                                             ui64Protflags64);
                        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                       PDumpWriteScript(hScript, ui32Flags);
+                       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
                        /* Finally, we write the register into the actual PxE */
                        eErr = PDumpSNPrintf(hScript,
@@ -667,13 +674,14 @@ PVRSRV_ERROR PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                                             /* src */
                                             pszPDumpDevName);
                        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
-                       PDumpWriteScript(hScript, ui32Flags);
+                       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                }
        }
 
 done:
        /* flush out any partly accumulated stuff for LDB */
-       _ContiguousPDumpBytes(aszPxSymbolicAddr, ui32SymAddrOffset, IMG_TRUE,
+       _ContiguousPDumpBytes(psDeviceNode, aszPxSymbolicAddr,
+                             ui32SymAddrOffset, IMG_TRUE,
                              0, NULL,
                              ui32Flags);
 
@@ -741,7 +749,8 @@ static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
  * Returns        : PVRSRV_ERROR
  * Description    : Alloc MMU Context
 **************************************************************************/
-PVRSRV_ERROR PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+PVRSRV_ERROR PDumpMMUAllocMMUContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+                               const IMG_CHAR *pszPDumpMemSpaceName,
                                     IMG_DEV_PHYADDR sPCDevPAddr,
                                     PDUMP_MMU_TYPE eMMUType,
                                     IMG_UINT32 *pui32MMUContextID,
@@ -797,7 +806,7 @@ PVRSRV_ERROR PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        /* return the MMU Context ID */
@@ -815,7 +824,8 @@ ErrOut:
  * Returns        : PVRSRV_ERROR
  * Description    : Free MMU Context
 **************************************************************************/
-PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+PVRSRV_ERROR PDumpMMUFreeMMUContext(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const IMG_CHAR *pszPDumpMemSpaceName,
                                    IMG_UINT32 ui32MMUContextID,
                                    IMG_UINT32 ui32PDumpFlags)
 {
@@ -828,7 +838,7 @@ PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
                             "-- Clear MMU Context for memory space %s", pszPDumpMemSpaceName);
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
 
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode,hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                             ui32MaxLen,
@@ -838,7 +848,7 @@ PVRSRV_ERROR PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
 
        PVR_GOTO_IF_ERROR(eErr, ErrUnlock);
 
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = _PdumpFreeMMUContext(ui32MMUContextID);
        PVR_LOG_GOTO_IF_ERROR(eErr, "_PdumpFreeMMUContext", ErrUnlock);
@@ -850,7 +860,8 @@ ErrUnlock:
 }
 
 PVRSRV_ERROR
-PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
+PDumpMMUSAB(PVRSRV_DEVICE_NODE *psDeviceNode,
+           const IMG_CHAR *pszPDumpMemNamespace,
            IMG_UINT32 uiPDumpMMUCtx,
            IMG_DEV_VIRTADDR sDevAddrStart,
            IMG_DEVMEM_SIZE_T uiSize,
@@ -886,7 +897,7 @@ PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
        PVR_GOTO_IF_ERROR(eErr, ErrOut);
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
 ErrOut:
index f6cc98f..32b0463 100644 (file)
@@ -60,6 +60,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "allocmem.h"
 #include "osfunc.h"
 
+#include "pvrsrv.h"
+
 /* #define MAX_PDUMP_MMU_CONTEXTS      (10) */
 /* static IMG_UINT32 guiPDumpMMUContextAvailabilityMask = (1<<MAX_PDUMP_MMU_CONTEXTS)-1; */
 
@@ -140,7 +142,8 @@ PVRSRV_ERROR PDumpGetSymbolicAddr(const IMG_HANDLE hPhysmemPDumpHandle,
  * Returns        : PVRSRV_ERROR
  * Description    :
  **************************************************************************/
-PVRSRV_ERROR PDumpMalloc(const IMG_CHAR *pszDevSpace,
+PVRSRV_ERROR PDumpMalloc(PVRSRV_DEVICE_NODE *psDeviceNode,
+                         const IMG_CHAR *pszDevSpace,
                          const IMG_CHAR *pszSymbolicAddress,
                          IMG_UINT64 ui64Size,
                          IMG_DEVMEM_ALIGN_T uiAlign,
@@ -208,7 +211,7 @@ PVRSRV_ERROR PDumpMalloc(const IMG_CHAR *pszDevSpace,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        psPDumpAllocationInfo->ui64Size = ui64Size;
@@ -229,7 +232,8 @@ _return:
  * Returns        : PVRSRV_ERROR
  * Description    :
  **************************************************************************/
-PVRSRV_ERROR PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle)
+PVRSRV_ERROR PDumpFree(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       IMG_HANDLE hPDumpAllocationInfoHandle)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_BLKDATA;
@@ -248,7 +252,7 @@ PVRSRV_ERROR PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle)
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        OSFreeMem(psPDumpAllocationInfo);
        PDUMP_UNLOCK(ui32Flags);
 
@@ -257,8 +261,13 @@ _return:
        return eError;
 }
 
+
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRWRW32(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW32(PVRSRV_DEVICE_NODE *psDeviceNode,
+              const IMG_CHAR *pszDevSpace,
               const IMG_CHAR *pszSymbolicName,
               IMG_DEVMEM_OFFSET_T uiOffset,
               IMG_UINT32 ui32Value,
@@ -279,7 +288,7 @@ PDumpPMRWRW32(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -287,8 +296,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRWRW32InternalVarToMem(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW32InternalVarToMem(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               const IMG_CHAR *pszInternalVar,
@@ -308,7 +321,7 @@ PDumpPMRWRW32InternalVarToMem(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -316,8 +329,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRRDW32MemToInternalVar(const IMG_CHAR *pszInternalVar,
+PDumpPMRRDW32MemToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszInternalVar,
                               const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
@@ -337,7 +354,7 @@ PDumpPMRRDW32MemToInternalVar(const IMG_CHAR *pszInternalVar,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -345,8 +362,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRWRW64(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW64(PVRSRV_DEVICE_NODE *psDeviceNode,
+              const IMG_CHAR *pszDevSpace,
               const IMG_CHAR *pszSymbolicName,
               IMG_DEVMEM_OFFSET_T uiOffset,
               IMG_UINT64 ui64Value,
@@ -367,7 +388,7 @@ PDumpPMRWRW64(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -375,8 +396,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRWRW64InternalVarToMem(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW64InternalVarToMem(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               const IMG_CHAR *pszInternalVar,
@@ -396,7 +421,7 @@ PDumpPMRWRW64InternalVarToMem(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -404,8 +429,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRRDW64MemToInternalVar(const IMG_CHAR *pszInternalVar,
+PDumpPMRRDW64MemToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszInternalVar,
                               const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
@@ -425,7 +454,7 @@ PDumpPMRRDW64MemToInternalVar(const IMG_CHAR *pszInternalVar,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -433,8 +462,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
+PDumpPMRLDB(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszDevSpace,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiOffset,
             IMG_DEVMEM_SIZE_T uiSize,
@@ -460,7 +493,7 @@ PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -468,7 +501,11 @@ _return:
        return eError;
 }
 
-PVRSRV_ERROR PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
+PVRSRV_ERROR PDumpPMRSAB(PVRSRV_DEVICE_NODE *psDeviceNode,
+                         const IMG_CHAR *pszDevSpace,
                          const IMG_CHAR *pszSymbolicName,
                          IMG_DEVMEM_OFFSET_T uiOffset,
                          IMG_DEVMEM_SIZE_T uiSize,
@@ -496,7 +533,7 @@ PVRSRV_ERROR PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -504,8 +541,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRPOL(const IMG_CHAR *pszMemspaceName,
+PDumpPMRPOL(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszMemspaceName,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiOffset,
             IMG_UINT32 ui32Value,
@@ -534,7 +575,7 @@ PDumpPMRPOL(const IMG_CHAR *pszMemspaceName,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -542,8 +583,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
+PDumpPMRCBP(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszMemspaceName,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiReadOffset,
             IMG_DEVMEM_OFFSET_T uiWriteOffset,
@@ -569,7 +614,7 @@ PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
        PVR_GOTO_IF_ERROR(eError, _return);
 
        PDUMP_LOCK(uiPDumpFlags);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
 _return:
@@ -577,8 +622,12 @@ _return:
        return eError;
 }
 
+/* Checking that the request is for the PDump-bound device
+ * should be done before the following function is called
+ */
 PVRSRV_ERROR
-PDumpWriteParameterBlob(IMG_UINT8 *pcBuffer,
+PDumpWriteParameterBlob(PVRSRV_DEVICE_NODE *psDeviceNode,
+                        IMG_UINT8 *pcBuffer,
                         size_t uiNumBytes,
                         PDUMP_FLAGS_T uiPDumpFlags,
                         IMG_CHAR *pszFilenameOut,
@@ -604,7 +653,8 @@ PDumpWriteParameterBlob(IMG_UINT8 *pcBuffer,
 
        PDUMP_LOCK(uiPDumpFlags);
 
-       eError = PDumpWriteParameter(pcBuffer, uiNumBytes, uiPDumpFlags, puiOffsetOut, pszFilenameOut);
+       eError = PDumpWriteParameter(psDeviceNode, pcBuffer, uiNumBytes,
+                                    uiPDumpFlags, puiOffsetOut, pszFilenameOut);
        PDUMP_UNLOCK(uiPDumpFlags);
 
        if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_PDUMP_NOT_ALLOWED))
index 17612b4..f5f2f55 100644 (file)
@@ -41,10 +41,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
 #if defined(PDUMP)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
 
+#if defined(__linux__)
+ #include <linux/version.h>
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+  #include <linux/stdarg.h>
+ #else
+  #include <stdarg.h>
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+#else
+ #include <stdarg.h>
+#endif /* __linux__ */
 
 #include "pvrversion.h"
 #include "allocmem.h"
@@ -82,6 +89,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define MAX_PDUMP_WRITE_RETRIES        200     /*!< Max number of retries to dump pdump data in to respective buffers */
 
+/* 'Magic' cookie used in this file only, where no psDeviceNode is available
+ * but writing to the PDump log should be permitted
+ */
+#define PDUMP_MAGIC_COOKIE 0x9E0FF
+
 static ATOMIC_T                g_sConnectionCount;
 
 /*
@@ -167,9 +179,9 @@ ATOMIC_T g_sEveryLineCounter;
 
 // #define PDUMP_DEBUG_TRANSITION
 #if defined(PDUMP_DEBUG_TRANSITION)
-# define DEBUG_OUTFILES_COMMENT(fmt, ...) (void)PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, fmt, __VA_ARGS__)
+# define DEBUG_OUTFILES_COMMENT(dev, fmt, ...) (void)PDumpCommentWithFlags(dev, PDUMP_FLAGS_CONTINUOUS, fmt, __VA_ARGS__)
 #else
-# define DEBUG_OUTFILES_COMMENT(fmt, ...)
+# define DEBUG_OUTFILES_COMMENT(dev, fmt, ...)
 #endif
 
 #if defined(PDUMP_DEBUG) || defined(REFCOUNT_DEBUG)
@@ -179,8 +191,9 @@ ATOMIC_T g_sEveryLineCounter;
 #endif
 
 /* Prototype for the test/debug state dump routine used in debugging */
+#if defined(PDUMP_TRACE_STATE) || defined(PVR_TESTING_UTILS)
 void PDumpCommonDumpState(void);
-#undef PDUMP_TRACE_STATE
+#endif
 
 
 /*****************************************************************************/
@@ -235,6 +248,7 @@ typedef enum _PDUMP_SM_
 /*! PDump control flags */
 #define FLAG_IS_DRIVER_IN_INIT_PHASE 0x1  /*! Control flag that keeps track of State of driver initialisation phase */
 #define FLAG_IS_IN_CAPTURE_RANGE     0x2  /*! Control flag that keeps track of Current capture status, is current frame in range */
+#define FLAG_IS_IN_CAPTURE_INTERVAL  0x4  /*! Control flag that keeps track of Current capture status, is current frame in an interval where no capture takes place. */
 
 #define CHECK_PDUMP_CONTROL_FLAG(PDUMP_CONTROL_FLAG) BITMASK_HAS(g_PDumpCtrl.ui32Flags, PDUMP_CONTROL_FLAG)
 #define SET_PDUMP_CONTROL_FLAG(PDUMP_CONTROL_FLAG)   BITMASK_SET(g_PDumpCtrl.ui32Flags, PDUMP_CONTROL_FLAG)
@@ -409,27 +423,39 @@ static void PDumpCtrlUpdateCaptureStatus(void)
        if (g_PDumpCtrl.ui32DefaultCapMode == PDUMP_CAPMODE_FRAMED)
        {
                if ((g_PDumpCtrl.ui32CurrentFrame >= g_PDumpCtrl.sCaptureRange.ui32Start) &&
-                       (g_PDumpCtrl.ui32CurrentFrame <= g_PDumpCtrl.sCaptureRange.ui32End) &&
-                       (((g_PDumpCtrl.ui32CurrentFrame - g_PDumpCtrl.sCaptureRange.ui32Start) % g_PDumpCtrl.sCaptureRange.ui32Interval) == 0))
+                       (g_PDumpCtrl.ui32CurrentFrame <= g_PDumpCtrl.sCaptureRange.ui32End))
                {
-                       SET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+                       if (((g_PDumpCtrl.ui32CurrentFrame - g_PDumpCtrl.sCaptureRange.ui32Start) % g_PDumpCtrl.sCaptureRange.ui32Interval) == 0)
+                       {
+                               SET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+                               UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
+                       }
+                       else
+                       {
+                               UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+                               SET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
+                       }
                }
                else
                {
                        UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+                       UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
                }
        }
        else if ((g_PDumpCtrl.ui32DefaultCapMode == PDUMP_CAPMODE_CONTINUOUS) || (g_PDumpCtrl.ui32DefaultCapMode == PDUMP_CAPMODE_BLOCKED))
        {
                SET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+               UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
        }
        else if (g_PDumpCtrl.ui32DefaultCapMode == PDUMP_CAPMODE_UNSET)
        {
                UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+               UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
        }
        else
        {
                UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE);
+               UNSET_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL);
                PVR_DPF((PVR_DBG_ERROR, "PDumpCtrlUpdateCaptureStatus: Unexpected capture mode (%x)", g_PDumpCtrl.ui32DefaultCapMode));
        }
 
@@ -459,7 +485,7 @@ static void PDumpCtrlSetBlock(IMG_UINT32 ui32BlockNum)
 
 static INLINE IMG_UINT32 PDumpCtrlGetBlock(void)
 {
-       return (PDumpCtrlCapModIsBlocked()? g_PDumpCtrl.sBlockCtrl.ui32CurrentBlock : PDUMP_BLOCKNUM_INVALID);
+       return PDumpCtrlCapModIsBlocked()? g_PDumpCtrl.sBlockCtrl.ui32CurrentBlock : PDUMP_BLOCKNUM_INVALID;
 }
 
 static PVRSRV_ERROR PDumpCtrlForcedStop(void)
@@ -533,6 +559,12 @@ static INLINE IMG_BOOL PDumpCtrlCaptureOn(void)
                        CHECK_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE)) ? IMG_TRUE : IMG_FALSE;
 }
 
+static INLINE IMG_BOOL PDumpCtrlCaptureInInterval(void)
+{
+       return ((g_PDumpCtrl.eServiceState == PDUMP_SM_READY_CLIENT_CONNECTED) &&
+                       CHECK_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL)) ? IMG_TRUE : IMG_FALSE;
+}
+
 static INLINE IMG_BOOL PDumpCtrlCaptureRangePast(void)
 {
        return (g_PDumpCtrl.ui32CurrentFrame > g_PDumpCtrl.sCaptureRange.ui32End);
@@ -610,12 +642,19 @@ static INLINE IMG_BOOL PDumpCtrlInPowerTransition(void)
 static PVRSRV_ERROR PDumpCtrlGetState(IMG_UINT64 *ui64State)
 {
        PDUMP_SM eState;
+
        *ui64State = 0;
+
        if (PDumpCtrlCaptureOn())
        {
                *ui64State |= PDUMP_STATE_CAPTURE_FRAME;
        }
 
+       if (PDumpCtrlCaptureInInterval())
+       {
+               *ui64State |= PDUMP_STATE_CAPTURE_IN_INTERVAL;
+       }
+
        eState = PDumpCtrlGetModuleState();
 
        if (eState == PDUMP_SM_READY_CLIENT_CONNECTED)
@@ -648,46 +687,35 @@ static INLINE void PDumpModuleTransitionState(PDUMP_SM eNewState)
        PDumpCtrlLockAcquire();
        g_PDumpCtrl.eServiceState = eNewState;
        PDumpCtrlLockRelease();
-       return;
-}
-
-void PDumpPowerTransitionStart(void)
-{
-       PDumpCtrlLockAcquire();
-       PDumpCtrlPowerTransitionStart();
-       PDumpCtrlLockRelease();
 }
 
-void PDumpPowerTransitionEnd(void)
+void PDumpPowerTransitionStart(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       PDumpCtrlLockAcquire();
-       PDumpCtrlPowerTransitionEnd();
-       PDumpCtrlLockRelease();
+       if (PDumpIsDevicePermitted(psDeviceNode))
+       {
+               PDumpCtrlLockAcquire();
+               PDumpCtrlPowerTransitionStart();
+               PDumpCtrlLockRelease();
+       }
 }
 
-IMG_BOOL PDumpInPowerTransition(void)
+void PDumpPowerTransitionEnd(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       IMG_BOOL bPDumpInPowerTransition = IMG_FALSE;
-
-       PDumpCtrlLockAcquire();
-       if (PDumpCtrlInPowerTransitionPID())
+       if (PDumpIsDevicePermitted(psDeviceNode))
        {
-               bPDumpInPowerTransition = IMG_TRUE;
+               PDumpCtrlLockAcquire();
+               PDumpCtrlPowerTransitionEnd();
+               PDumpCtrlLockRelease();
        }
-       PDumpCtrlLockRelease();
-
-       return bPDumpInPowerTransition;
 }
 
-IMG_BOOL PDumpIsContCaptureOn(void)
+static PVRSRV_ERROR PDumpGetCurrentBlockKM(IMG_UINT32 *pui32BlockNum)
 {
-       IMG_BOOL bPDumpIsCatpureOn;
-
        PDumpCtrlLockAcquire();
-       bPDumpIsCatpureOn = !PDumpCtrlInitPhaseComplete() || (PDumpCtrlGetModuleState() == PDUMP_SM_READY_CLIENT_CONNECTED);
+       *pui32BlockNum = PDumpCtrlGetBlock();
        PDumpCtrlLockRelease();
 
-       return bPDumpIsCatpureOn;
+       return PVRSRV_OK;
 }
 
 static IMG_BOOL PDumpIsClientConnected(void)
@@ -701,6 +729,16 @@ static IMG_BOOL PDumpIsClientConnected(void)
        return bPDumpClientConnected;
 }
 
+/* Prototype write allowed for exposure in PDumpCheckFlagsWrite */
+static IMG_BOOL PDumpWriteAllowed(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_UINT32 ui32Flags, IMG_UINT32* ui32ExitHere);
+
+IMG_BOOL PDumpCheckFlagsWrite(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              IMG_UINT32 ui32Flags)
+{
+       return PDumpWriteAllowed(psDeviceNode, ui32Flags, NULL);
+}
+
 /*****************************************************************************/
 /* PDump Common Write Layer just above common Transport Layer                */
 /*****************************************************************************/
@@ -726,6 +764,35 @@ static IMG_BOOL _PDumpSetSplitMarker(IMG_HANDLE hStream, IMG_BOOL bRemoveOld)
        return IMG_TRUE;
 }
 
+IMG_BOOL PDumpIsDevicePermitted(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+
+       if ((void*)psDeviceNode == (void*)PDUMP_MAGIC_COOKIE)
+       {
+               /* Always permit PDumping if passed 'magic' cookie */
+               return IMG_TRUE;
+       }
+
+       if (psDeviceNode)
+       {
+               if ((psDeviceNode->sDevId.ui32InternalID > PVRSRV_MAX_DEVICES) ||
+                   ((psPVRSRVData->ui32PDumpBoundDevice < PVRSRV_MAX_DEVICES) &&
+                    (psDeviceNode->sDevId.ui32InternalID != psPVRSRVData->ui32PDumpBoundDevice)))
+               {
+                       return IMG_FALSE;
+               }
+       }
+       else
+       {
+               /* Assert if provided with a NULL psDeviceNode */
+               OSDumpStack();
+               PVR_ASSERT(psDeviceNode);
+               return IMG_FALSE;
+       }
+       return IMG_TRUE;
+}
+
 /*
        Checks in this method were seeded from the original PDumpWriteILock()
        and DBGDrivWriteCM() and have grown since to ensure PDump output
@@ -733,12 +800,23 @@ static IMG_BOOL _PDumpSetSplitMarker(IMG_HANDLE hStream, IMG_BOOL bRemoveOld)
        Note: the order of the checks in this method is important as some
        writes have multiple pdump flags set!
  */
-static IMG_BOOL PDumpWriteAllowed(IMG_UINT32 ui32Flags, IMG_UINT32* ui32ExitHere)
+static IMG_BOOL PDumpWriteAllowed(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_UINT32 ui32Flags, IMG_UINT32* ui32ExitHere)
 {
        PDUMP_HERE_VAR;
 
+       /* No writes if for a different device than the PDump-bound device
+        *  NB. psDeviceNode may be NULL if called during initialisation
+        */
+       if (!PDumpIsDevicePermitted(psDeviceNode))
+       {
+               PDUMP_HERE(5);
+               goto returnFalse;
+       }
+
        /* PDUMP_FLAGS_CONTINUOUS and PDUMP_FLAGS_PERSISTENT can't come together. */
-       PVR_ASSERT(IMG_FALSE == ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) && (ui32Flags & PDUMP_FLAGS_PERSISTENT)));
+       PVR_ASSERT(IMG_FALSE == ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) &&
+                                    (ui32Flags & PDUMP_FLAGS_PERSISTENT)));
 
        /* Lock down the PDUMP_CTRL_STATE struct before calling the following
           PDumpCtrl*** functions. This is to avoid updates to the Control data
@@ -810,6 +888,17 @@ static IMG_BOOL PDumpWriteAllowed(IMG_UINT32 ui32Flags, IMG_UINT32* ui32ExitHere
                goto unlockAndReturnTrue;
        }
 
+       /* If in a capture interval but a write is still required.
+        * Force write out if FLAGS_INTERVAL has been set and we are in
+        * a capture interval */
+       if (ui32Flags & PDUMP_FLAGS_INTERVAL)
+       {
+               if (PDumpCtrlCaptureInInterval()){
+                       PDUMP_HERE(21);
+                       goto unlockAndReturnTrue;
+               }
+       }
+
        /*
                If no flags are provided then it is FRAMED output and the frame
                range must be checked matching expected behaviour.
@@ -830,6 +919,7 @@ unlockAndReturnTrue:
 
 unlockAndReturnFalse:
        PDumpCtrlLockRelease();
+returnFalse:
        if (ui32ExitHere != NULL)
        {
                *ui32ExitHere = here;
@@ -844,6 +934,7 @@ unlockAndReturnFalse:
                 to handle any buffer full conditions to ensure all the data
                 requested to be written, is.
 
+ @Input                        psDeviceNode The device the PDump pertains to
  @Input                        psStream        The address of the PDump stream buffer to write to
  @Input                        pui8Data    Pointer to the data to be written
  @Input                        ui32BCount      Number of bytes to write
@@ -853,8 +944,11 @@ unlockAndReturnFalse:
                             ui32BCount when buffer full condition could not
                             be avoided.
 */ /**************************************************************************/
-static IMG_UINT32 PDumpWriteToBuffer(PDUMP_STREAM* psStream, IMG_UINT8 *pui8Data,
-               IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
+static IMG_UINT32 PDumpWriteToBuffer(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     PDUMP_STREAM* psStream,
+                                     IMG_UINT8 *pui8Data,
+                                     IMG_UINT32 ui32BCount,
+                                     IMG_UINT32 ui32Flags)
 {
        IMG_UINT32      ui32BytesToBeWritten;
        IMG_UINT32      ui32Off = 0;
@@ -971,7 +1065,7 @@ static IMG_UINT32 PDumpWriteToBuffer(PDUMP_STREAM* psStream, IMG_UINT8 *pui8Data
                   (which is detected via PDumpWriteAllowed())
                */
 
-               if (!PDumpWriteAllowed(ui32Flags, NULL))
+               if (!PDumpWriteAllowed(psDeviceNode, ui32Flags, NULL))
                {
                        psStream->ui32BufferFullAborts++;
                        break;
@@ -986,6 +1080,7 @@ static IMG_UINT32 PDumpWriteToBuffer(PDUMP_STREAM* psStream, IMG_UINT8 *pui8Data
  @Description   Write the supplied data to the PDump channel specified obeying
                 flags to write to the necessary channel buffers.
 
+ @Input         psDeviceNode The device the PDump pertains to
  @Input         psChannel   Address of the script or parameter channel object
  @Input/Output  psWOff      Address of the channel write offsets object to
                             update on successful writing
@@ -1006,8 +1101,12 @@ static IMG_UINT32 PDumpWriteToBuffer(PDUMP_STREAM* psStream, IMG_UINT8 *pui8Data
                             the init buffer.
  @Return        IMG_BOOL    True when the data has been consumed, false otherwise
 */ /**************************************************************************/
-static IMG_BOOL PDumpWriteToChannel(PDUMP_CHANNEL* psChannel, PDUMP_CHANNEL_WOFFSETS* psWOff,
-               IMG_UINT8* pui8Data, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
+static IMG_BOOL PDumpWriteToChannel(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    PDUMP_CHANNEL* psChannel,
+                                    PDUMP_CHANNEL_WOFFSETS* psWOff,
+                                    IMG_UINT8* pui8Data,
+                                    IMG_UINT32 ui32Size,
+                                    IMG_UINT32 ui32Flags)
 {
        IMG_UINT32 ui32BytesWritten = 0;
        PDUMP_HERE_VAR;
@@ -1031,7 +1130,9 @@ static IMG_BOOL PDumpWriteToChannel(PDUMP_CHANNEL* psChannel, PDUMP_CHANNEL_WOFF
        if (ui32Flags & PDUMP_FLAGS_DEINIT)
        {
                PDUMP_HERE(211);
-               ui32BytesWritten = PDumpWriteToBuffer(&psChannel->sDeinitStream, pui8Data, ui32Size, ui32Flags);
+               ui32BytesWritten = PDumpWriteToBuffer(psDeviceNode,
+                                                     &psChannel->sDeinitStream,
+                                                     pui8Data, ui32Size, ui32Flags);
                if (ui32BytesWritten != ui32Size)
                {
                        PVR_DPF((PVR_DBG_ERROR, "PDumpWriteToChannel: DEINIT Written length (%d) does not match data length (%d), PDump incomplete!", ui32BytesWritten, ui32Size));
@@ -1057,7 +1158,9 @@ static IMG_BOOL PDumpWriteToChannel(PDUMP_CHANNEL* psChannel, PDUMP_CHANNEL_WOFF
                if (ui32Flags & PDUMP_FLAGS_PERSISTENT)
                {
                        PDUMP_HERE(213);
-                       ui32BytesWritten = PDumpWriteToBuffer(&psChannel->sInitStream, pui8Data, ui32Size, ui32Flags);
+                       ui32BytesWritten = PDumpWriteToBuffer(psDeviceNode,
+                                                             &psChannel->sInitStream,
+                                                             pui8Data, ui32Size, ui32Flags);
                        if (ui32BytesWritten != ui32Size)
                        {
                                PVR_DPF((PVR_DBG_ERROR, "PDumpWriteToChannel: PERSIST Written length (%d) does not match data length (%d), PDump incomplete!", ui32BytesWritten, ui32Size));
@@ -1111,7 +1214,9 @@ static IMG_BOOL PDumpWriteToChannel(PDUMP_CHANNEL* psChannel, PDUMP_CHANNEL_WOFF
                        if (ui32Flags & PDUMP_FLAGS_BLKDATA)
                        {
                                PDUMP_HERE(217);
-                               ui32BytesWritten = PDumpWriteToBuffer(&psChannel->sBlockStream, pui8Data, ui32Size, ui32Flags);
+                               ui32BytesWritten = PDumpWriteToBuffer(psDeviceNode,
+                                                                     &psChannel->sBlockStream,
+                                                                     pui8Data, ui32Size, ui32Flags);
                                if (ui32BytesWritten != ui32Size)
                                {
                                        PVR_DPF((PVR_DBG_ERROR, "PDumpWriteToChannel: BLOCK Written length (%d) does not match data length (%d), PDump incomplete!", ui32BytesWritten, ui32Size));
@@ -1122,7 +1227,9 @@ static IMG_BOOL PDumpWriteToChannel(PDUMP_CHANNEL* psChannel, PDUMP_CHANNEL_WOFF
                }
 
                /* Write the data to the stream */
-               ui32BytesWritten = PDumpWriteToBuffer(psStream, pui8Data, ui32Size, ui32Flags);
+               ui32BytesWritten = PDumpWriteToBuffer(psDeviceNode,
+                                                     psStream, pui8Data,
+                                                     ui32Size, ui32Flags);
                if (ui32BytesWritten != ui32Size)
                {
                        PVR_DPF((PVR_DBG_ERROR, "PDumpWriteToChannel: MAIN Written length (%d) does not match data length (%d), PDump incomplete!", ui32BytesWritten, ui32Size));
@@ -1167,8 +1274,12 @@ static IMG_UINT32 _GenerateChecksum(void *pvData, size_t uiSize)
 
 #endif
 
-PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags,
-               IMG_UINT32* pui32FileOffset, IMG_CHAR* aszFilenameStr)
+PVRSRV_ERROR PDumpWriteParameter(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 IMG_UINT8 *pui8Data,
+                                 IMG_UINT32 ui32Size,
+                                 IMG_UINT32 ui32Flags,
+                                 IMG_UINT32* pui32FileOffset,
+                                 IMG_CHAR* aszFilenameStr)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_BOOL bPDumpCtrlInitPhaseComplete = IMG_FALSE;
@@ -1183,7 +1294,7 @@ PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_U
        PDUMP_HERE(1);
 
        /* Check if write can proceed? */
-       if (!PDumpWriteAllowed(ui32Flags, &here))
+       if (!PDumpWriteAllowed(psDeviceNode, ui32Flags, &here))
        {
                /* Abort write for the above reason but indicate what happened to
                 * caller to avoid disrupting the driver, caller should treat it as OK
@@ -1239,7 +1350,9 @@ PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_U
 
        /* Write the parameter data to the parameter channel */
        eError = PVRSRV_ERROR_PDUMP_BUFFER_FULL;
-       if (!PDumpWriteToChannel(&g_PDumpParameters.sCh, &g_PDumpParameters.sWOff, pui8Data, ui32Size, ui32Flags))
+       if (!PDumpWriteToChannel(psDeviceNode, &g_PDumpParameters.sCh,
+                                &g_PDumpParameters.sWOff, pui8Data,
+                                ui32Size, ui32Flags))
        {
                PDUMP_HERE(7);
                PVR_LOG_GOTO_IF_ERROR(eError, "PDumpWrite", errExit);
@@ -1260,7 +1373,7 @@ PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *pui8Data, IMG_UINT32 ui32Size, IMG_U
                                                                        aszFilenameStr);
                PVR_GOTO_IF_ERROR(eError, errExit);
 
-               PDumpWriteScript(hScript, ui32Flags);
+               PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
                PDUMP_RELEASE_SCRIPT_STRING();
        }
 #endif
@@ -1272,7 +1385,8 @@ errExit:
 }
 
 
-IMG_BOOL PDumpWriteScript(IMG_HANDLE hString, IMG_UINT32 ui32Flags)
+IMG_BOOL PDumpWriteScript(PVRSRV_DEVICE_NODE *psDeviceNode,
+                          IMG_HANDLE hString, IMG_UINT32 ui32Flags)
 {
        PDUMP_HERE_VAR;
 
@@ -1296,7 +1410,7 @@ IMG_BOOL PDumpWriteScript(IMG_HANDLE hString, IMG_UINT32 ui32Flags)
        }
 #endif
 
-       if (!PDumpWriteAllowed(ui32Flags, NULL))
+       if (!PDumpWriteAllowed(psDeviceNode, ui32Flags, NULL))
        {
                /* Abort write for the above reasons but indicated it was OK to
                 * caller to avoid disrupting the driver */
@@ -1335,7 +1449,10 @@ IMG_BOOL PDumpWriteScript(IMG_HANDLE hString, IMG_UINT32 ui32Flags)
                }
        }
 
-       return PDumpWriteToChannel(&g_PDumpScript.sCh, NULL, (IMG_UINT8*) hString, (IMG_UINT32) OSStringLength((IMG_CHAR*) hString), ui32Flags);
+       return PDumpWriteToChannel(psDeviceNode, &g_PDumpScript.sCh, NULL,
+                                 (IMG_UINT8*) hString,
+                                 (IMG_UINT32) OSStringLength((IMG_CHAR*) hString),
+                                 ui32Flags);
 }
 
 
@@ -1527,12 +1644,12 @@ static void PDumpDeInitStreams(PDUMP_CHANNEL* psParam, PDUMP_CHANNEL* psScript)
 
 /******************************************************************************
  * Function Name  : PDumpParameterChannelZeroedPageBlock
- * Inputs         : None
+ * Inputs         : psDeviceNode
  * Outputs        : None
  * Returns        : PVRSRV_ERROR
  * Description    : Set up the zero page block in the parameter stream
 ******************************************************************************/
-static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(void)
+static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        IMG_UINT8 aui8Zero[32] = { 0 };
        size_t uiBytesToWrite;
@@ -1542,7 +1659,7 @@ static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(void)
        IMG_UINT32 ui32GeneralNon4KHeapPageSize;
 
        OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintUINT32(pvAppHintState, GeneralNon4KHeapPageSize,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, GeneralNon4KHeapPageSize,
                        &ui32AppHintDefault, &ui32GeneralNon4KHeapPageSize);
        OSFreeKMAppHintState(pvAppHintState);
 
@@ -1557,7 +1674,7 @@ static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(void)
         * contiguous in the stream
         */
        PDUMP_LOCK(0);
-       eError = PDumpWriteParameter(aui8Zero,
+       eError = PDumpWriteParameter(psDeviceNode, aui8Zero,
                                                        sizeof(aui8Zero),
                                                        0,
                                                        &g_PDumpParameters.uiZeroPageOffset,
@@ -1575,9 +1692,11 @@ static PVRSRV_ERROR PDumpParameterChannelZeroedPageBlock(void)
        {
                IMG_BOOL bOK;
 
-               bOK = PDumpWriteToChannel(&g_PDumpParameters.sCh, &g_PDumpParameters.sWOff,
-                                                                       aui8Zero,
-                                                                       sizeof(aui8Zero), 0);
+               bOK = PDumpWriteToChannel(psDeviceNode,
+                                                                 &g_PDumpParameters.sCh,
+                                                                 &g_PDumpParameters.sWOff,
+                                                                 aui8Zero,
+                                                                 sizeof(aui8Zero), 0);
 
                if (!bOK)
                {
@@ -1617,6 +1736,7 @@ void PDumpGetParameterZeroPageInfo(PDUMP_FILEOFFSET_T *puiZeroPageOffset,
                *ppszZeroPageFilename = g_PDumpParameters.szZeroPageFilename;
 }
 
+
 PVRSRV_ERROR PDumpInitCommon(void)
 {
        PVRSRV_ERROR eError;
@@ -1649,13 +1769,18 @@ PVRSRV_ERROR PDumpInitCommon(void)
        PDUMP_HEREA(2011);
 
        /* Test PDump initialised and ready by logging driver details */
-       eError = PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Driver Product Version: %s - %s (%s)", PVRVERSION_STRING, PVR_BUILD_DIR, PVR_BUILD_TYPE);
+       eError = PDumpCommentWithFlags((PVRSRV_DEVICE_NODE*)PDUMP_MAGIC_COOKIE,
+                                      PDUMP_FLAGS_CONTINUOUS,
+                                      "Driver Product Version: %s - %s (%s)",
+                                      PVRVERSION_STRING, PVR_BUILD_DIR, PVR_BUILD_TYPE);
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpCommentWithFlags", errRetState);
 
-       eError = PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Start of Init Phase");
+       eError = PDumpCommentWithFlags((PVRSRV_DEVICE_NODE*)PDUMP_MAGIC_COOKIE,
+                                      PDUMP_FLAGS_CONTINUOUS,
+                                      "Start of Init Phase");
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpCommentWithFlags", errRetState);
 
-       eError = PDumpParameterChannelZeroedPageBlock();
+       eError = PDumpParameterChannelZeroedPageBlock((PVRSRV_DEVICE_NODE*)PDUMP_MAGIC_COOKIE);
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpParameterChannelZeroedPageBlock", errRetState);
 
        PDUMP_HEREA(2012);
@@ -1693,14 +1818,20 @@ void PDumpDeInitCommon(void)
        OSLockDestroy(g_hPDumpWriteLock);
 }
 
-void PDumpStopInitPhase(void)
+void PDumpStopInitPhase(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       /* output this comment to indicate init phase ending OSs */
-       PDUMPCOMMENT("Stop Init Phase");
+       IMG_UINT32 ui32PDumpBoundDevice = PVRSRVGetPVRSRVData()->ui32PDumpBoundDevice;
 
-       PDumpCtrlLockAcquire();
-       PDumpCtrlSetInitPhaseComplete(IMG_TRUE);
-       PDumpCtrlLockRelease();
+       /* Stop the init phase for the PDump-bound device only */
+       if (psDeviceNode->sDevId.ui32InternalID == ui32PDumpBoundDevice)
+       {
+               /* output this comment to indicate init phase ending OSs */
+               PDUMPCOMMENT(psDeviceNode, "Stop Init Phase");
+
+               PDumpCtrlLockAcquire();
+               PDumpCtrlSetInitPhaseComplete(IMG_TRUE);
+               PDumpCtrlLockRelease();
+       }
 }
 
 PVRSRV_ERROR PDumpIsLastCaptureFrameKM(IMG_BOOL *pbIsLastCaptureFrame)
@@ -1800,12 +1931,13 @@ void PDumpUnregisterTransitionCallbackFenceSync(void *pvHandle)
        OSFreeMem(psData);
 }
 
-static PVRSRV_ERROR _PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, PDUMP_TRANSITION_EVENT eEvent, IMG_UINT32 ui32PDumpFlags)
+static PVRSRV_ERROR _PDumpTransition(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+                                        PDUMP_TRANSITION_EVENT eEvent,
+                                        IMG_UINT32 ui32PDumpFlags)
 {
        DLLIST_NODE *psNode, *psNext;
        PVRSRV_ERROR eError;
-       PVRSRV_DEVICE_NODE *psThis;
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
 
        /* Only call the callbacks if we've really got new event */
        if ((eEvent != psPDumpConnectionData->eLastEvent) && (eEvent != PDUMP_TRANSITION_EVENT_NONE))
@@ -1839,17 +1971,12 @@ static PVRSRV_ERROR _PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionDat
                 * At playback time, script-thread and sim-FW threads needs to be
                 * synchronised before re-loading sync-blocks.
                 * */
-               psPDumpConnectionData->pfnPDumpSyncBlocks(psPDumpConnectionData->hSyncPrivData, eEvent);
+               psPDumpConnectionData->pfnPDumpSyncBlocks(psDeviceNode, psPDumpConnectionData->hSyncPrivData, eEvent);
 
-               psThis = psPVRSRVData->psDeviceNodeList;
-               while (psThis)
+               if (psDeviceNode->hTransition)
                {
-                       if (psThis->hTransition)
-                       {
-                               PDUMP_Transition_DATA_FENCE_SYNC *psData = (PDUMP_Transition_DATA_FENCE_SYNC*)psThis->hTransition;
-                               psData->pfnCallback(psData->hPrivData, eEvent);
-                       }
-                       psThis = psThis->psNext;
+                       PDUMP_Transition_DATA_FENCE_SYNC *psData = (PDUMP_Transition_DATA_FENCE_SYNC*)psDeviceNode->hTransition;
+                       psData->pfnCallback(psData->hPrivData, eEvent);
                }
 
                psPDumpConnectionData->eLastEvent = eEvent;
@@ -1858,7 +1985,10 @@ static PVRSRV_ERROR _PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionDat
        return PVRSRV_OK;
 }
 
-static PVRSRV_ERROR _PDumpBlockTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, PDUMP_TRANSITION_EVENT eEvent, IMG_UINT32 ui32PDumpFlags)
+static PVRSRV_ERROR _PDumpBlockTransition(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                          PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+                                          PDUMP_TRANSITION_EVENT eEvent,
+                                          IMG_UINT32 ui32PDumpFlags)
 {
 
        /* Need to follow following sequence for Block transition:
@@ -1878,38 +2008,51 @@ static PVRSRV_ERROR _PDumpBlockTransition(PDUMP_CONNECTION_DATA *psPDumpConnecti
        if (eEvent == PDUMP_TRANSITION_EVENT_BLOCK_FINISHED)
        {
                /* (1) Current block has finished */
-               eError = _PDumpTransition(psPDumpConnectionData, PDUMP_TRANSITION_EVENT_BLOCK_FINISHED, ui32PDumpFlags);
+               eError = _PDumpTransition(psDeviceNode,
+                                             psPDumpConnectionData,
+                                             PDUMP_TRANSITION_EVENT_BLOCK_FINISHED,
+                                             ui32PDumpFlags);
                PVR_RETURN_IF_ERROR(eError);
 
-               (void) PDumpCommentWithFlags(ui32Flags, "}PDUMP_BLOCK_END_0x%08X", ui32CurrentBlock - 1); /* Add pdump-block end marker */
+               (void) PDumpCommentWithFlags(psDeviceNode, ui32Flags,
+                                            "}PDUMP_BLOCK_END_0x%08X",
+                                            ui32CurrentBlock - 1); /* Add pdump-block end marker */
 
                /* (2) Split MAIN and BLOCK script out files on current pdump-block end */
                ui32Flags |= PDUMP_FLAGS_FORCESPLIT;
 
-               (void) PDumpCommentWithFlags(ui32Flags, "PDUMP_BLOCK_START_0x%08X{", ui32CurrentBlock); /* Add pdump-block start marker */
+               (void) PDumpCommentWithFlags(psDeviceNode, ui32Flags,
+                                            "PDUMP_BLOCK_START_0x%08X{",
+                                            ui32CurrentBlock); /* Add pdump-block start marker */
        }
 
        /* (3) New block has started */
-       return _PDumpTransition(psPDumpConnectionData, PDUMP_TRANSITION_EVENT_BLOCK_STARTED, ui32PDumpFlags);
+       return _PDumpTransition(psDeviceNode,
+                                   psPDumpConnectionData,
+                                   PDUMP_TRANSITION_EVENT_BLOCK_STARTED,
+                                   ui32PDumpFlags);
 }
 
 
-PVRSRV_ERROR PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData, PDUMP_TRANSITION_EVENT eEvent, IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpTransition(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+                             PDUMP_TRANSITION_EVENT eEvent,
+                             IMG_UINT32 ui32PDumpFlags)
 {
        if ((eEvent == PDUMP_TRANSITION_EVENT_BLOCK_FINISHED) || (eEvent == PDUMP_TRANSITION_EVENT_BLOCK_STARTED))
        {
                /* Block mode transition events */
                PVR_ASSERT(PDumpCtrlCapModIsBlocked());
-               return _PDumpBlockTransition(psPDumpConnectionData, eEvent, ui32PDumpFlags);
+               return _PDumpBlockTransition(psDeviceNode, psPDumpConnectionData, eEvent, ui32PDumpFlags);
        }
        else
        {
                /* Non-block mode transition events */
-               return _PDumpTransition(psPDumpConnectionData, eEvent, ui32PDumpFlags);
+               return _PDumpTransition(psDeviceNode, psPDumpConnectionData, eEvent, ui32PDumpFlags);
        }
 }
 
-PVRSRV_ERROR PDumpIsCaptureFrameKM(IMG_BOOL *bInCaptureRange)
+static PVRSRV_ERROR PDumpIsCaptureFrame(IMG_BOOL *bInCaptureRange)
 {
        IMG_UINT64 ui64State = 0;
        PVRSRV_ERROR eError;
@@ -1932,15 +2075,6 @@ PVRSRV_ERROR PDumpGetStateKM(IMG_UINT64 *ui64State)
        return eError;
 }
 
-PVRSRV_ERROR PDumpGetCurrentBlockKM(IMG_UINT32 *pui32BlockNum)
-{
-       PDumpCtrlLockAcquire();
-       *pui32BlockNum = PDumpCtrlGetBlock();
-       PDumpCtrlLockRelease();
-
-       return PVRSRV_OK;
-}
-
 /******************************************************************************
  * Function Name  : PDumpUpdateBlockCtrlStatus
  * Inputs         : ui32Frame - frame number
@@ -2015,17 +2149,31 @@ static INLINE IMG_BOOL PDumpUpdateBlockCtrlStatus(IMG_UINT32 ui32Frame)
        return IMG_FALSE; /* No transition */
 }
 
-PVRSRV_ERROR PDumpForceCaptureStopKM(void)
+PVRSRV_ERROR PDumpForceCaptureStopKM(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        PVRSRV_ERROR eError;
 
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       /* If call is not for the pdump-bound device, return immediately
+        * taking no action.
+        */
+       if (!PDumpIsDevicePermitted(psDeviceNode))
+       {
+               return PVRSRV_OK;
+       }
+
        if (!PDumpCtrlCapModIsBlocked())
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: This call is valid only in Block mode of PDump i.e. pdump -b<block-len>", __func__));
                return PVRSRV_ERROR_PDUMP_NOT_ALLOWED;
        }
 
-       (void) PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_BLKDATA, "PDdump forced STOP capture request received at frame %u", g_PDumpCtrl.ui32CurrentFrame);
+       (void) PDumpCommentWithFlags(psDeviceNode,
+                                    PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_BLKDATA,
+                                    "PDdump forced STOP capture request received at frame %u",
+                                    g_PDumpCtrl.ui32CurrentFrame);
 
        PDumpCtrlLockAcquire();
        eError = PDumpCtrlForcedStop();
@@ -2035,6 +2183,7 @@ PVRSRV_ERROR PDumpForceCaptureStopKM(void)
 }
 
 static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDeviceNode,
                                      IMG_UINT32 ui32Frame)
 {
        PDUMP_CONNECTION_DATA *psPDumpConnectionData = psConnection->psPDumpConnectionData;
@@ -2053,7 +2202,8 @@ static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection,
        */
        if (psPDumpConnectionData->ui32LastSetFrameNumber != ui32Frame)
        {
-               (void) PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, "Set pdump frame %u", ui32Frame);
+               (void) PDumpCommentWithFlags(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                            "Set pdump frame %u", ui32Frame);
 
                /*
                        The boolean values below decide if the PDump transition
@@ -2064,9 +2214,9 @@ static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection,
                */
                PDumpCtrlLockAcquire();
 
-               PDumpIsCaptureFrameKM(&bWasInCaptureRange);
+               PDumpIsCaptureFrame(&bWasInCaptureRange);
                PDumpCtrlSetCurrentFrame(ui32Frame);
-               PDumpIsCaptureFrameKM(&bIsInCaptureRange);
+               PDumpIsCaptureFrame(&bIsInCaptureRange);
 
                PDumpCtrlLockRelease();
 
@@ -2110,9 +2260,9 @@ static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection,
 
        if (eTransitionEvent != PDUMP_TRANSITION_EVENT_NONE)
        {
-               DEBUG_OUTFILES_COMMENT("PDump transition event(%u)-begin frame %u (post)", eTransitionEvent, ui32Frame);
-               eError = PDumpTransition(psPDumpConnectionData, eTransitionEvent, PDUMP_FLAGS_NONE);
-               DEBUG_OUTFILES_COMMENT("PDump transition event(%u)-complete frame %u (post)", eTransitionEvent, ui32Frame);
+               DEBUG_OUTFILES_COMMENT(psDeviceNode, "PDump transition event(%u)-begin frame %u (post)", eTransitionEvent, ui32Frame);
+               eError = PDumpTransition(psDeviceNode, psPDumpConnectionData, eTransitionEvent, PDUMP_FLAGS_NONE);
+               DEBUG_OUTFILES_COMMENT(psDeviceNode, "PDump transition event(%u)-complete frame %u (post)", eTransitionEvent, ui32Frame);
                PVR_RETURN_IF_ERROR(eError);
        }
 
@@ -2120,26 +2270,32 @@ static PVRSRV_ERROR _PDumpSetFrameKM(CONNECTION_DATA *psConnection,
 }
 
 PVRSRV_ERROR PDumpSetFrameKM(CONNECTION_DATA *psConnection,
-                             PVRSRV_DEVICE_NODE * psDeviceNode,
+                             PVRSRV_DEVICE_NODE *psDeviceNode,
                              IMG_UINT32 ui32Frame)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
 
-       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       /* If call is not for the pdump-bound device, return immediately
+        * taking no action.
+        */
+       if (!PDumpIsDevicePermitted(psDeviceNode))
+       {
+               return PVRSRV_OK;
+       }
 
 #if defined(PDUMP_TRACE_STATE)
        PVR_DPF((PVR_DBG_WARNING, "PDumpSetFrameKM: ui32Frame( %d )", ui32Frame));
 #endif
 
-       DEBUG_OUTFILES_COMMENT("(pre) Set pdump frame %u", ui32Frame);
+       DEBUG_OUTFILES_COMMENT(psDeviceNode, "(pre) Set pdump frame %u", ui32Frame);
 
-       eError = _PDumpSetFrameKM(psConnection, ui32Frame);
+       eError = _PDumpSetFrameKM(psConnection, psDeviceNode, ui32Frame);
        if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
        {
                PVR_LOG_ERROR(eError, "_PDumpSetFrameKM");
        }
 
-       DEBUG_OUTFILES_COMMENT("(post) Set pdump frame %u", ui32Frame);
+       DEBUG_OUTFILES_COMMENT(psDeviceNode, "(post) Set pdump frame %u", ui32Frame);
 
        return eError;
 }
@@ -2167,14 +2323,24 @@ PVRSRV_ERROR PDumpGetFrameKM(CONNECTION_DATA *psConnection,
        return eError;
 }
 
-PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
-                                           IMG_UINT32 ui32Start,
-                                           IMG_UINT32 ui32End,
-                                           IMG_UINT32 ui32Interval,
-                                           IMG_UINT32 ui32MaxParamFileSize)
+PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(CONNECTION_DATA *psConnection,
+                                            PVRSRV_DEVICE_NODE *psDeviceNode,
+                                            IMG_UINT32 ui32Mode,
+                                            IMG_UINT32 ui32Start,
+                                            IMG_UINT32 ui32End,
+                                            IMG_UINT32 ui32Interval,
+                                            IMG_UINT32 ui32MaxParamFileSize)
 {
        PVRSRV_ERROR eError;
 
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       /* NB. We choose not to check that the device is the pdump-bound
+        * device here, as this particular bridge call is made only from the pdump
+        * tool itself (which may only connect to the bound device).
+        */
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
        eError = PDumpReady();
        PVR_LOG_RETURN_IF_ERROR(eError, "PDumpReady");
 
@@ -2231,7 +2397,8 @@ PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
  * Returns        : PVRSRV_ERROR
  * Description    : Create a PDUMP string, which represents a register write
 ******************************************************************************/
-PVRSRV_ERROR PDumpReg32(IMG_CHAR       *pszPDumpRegName,
+PVRSRV_ERROR PDumpReg32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_CHAR        *pszPDumpRegName,
                                                IMG_UINT32      ui32Reg,
                                                IMG_UINT32      ui32Data,
                                                IMG_UINT32      ui32Flags)
@@ -2248,7 +2415,7 @@ PVRSRV_ERROR PDumpReg32(IMG_CHAR  *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2262,7 +2429,8 @@ PVRSRV_ERROR PDumpReg32(IMG_CHAR  *pszPDumpRegName,
  * Returns        : PVRSRV_ERROR
  * Description    : Create a PDUMP string, which represents a register write
 ******************************************************************************/
-PVRSRV_ERROR PDumpReg64(IMG_CHAR       *pszPDumpRegName,
+PVRSRV_ERROR PDumpReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_CHAR        *pszPDumpRegName,
                                                IMG_UINT32      ui32Reg,
                                                IMG_UINT64      ui64Data,
                                                IMG_UINT32      ui32Flags)
@@ -2286,7 +2454,7 @@ PVRSRV_ERROR PDumpReg64(IMG_CHAR  *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        eErr = PDumpSNPrintf(hScript, ui32MaxLen, "WRW :%s:0x%08X 0x%08X",
                                        pszPDumpRegName, ui32Reg + 4, ui32UpperValue);
@@ -2297,7 +2465,7 @@ PVRSRV_ERROR PDumpReg64(IMG_CHAR  *pszPDumpRegName,
                PDUMP_UNLOCK(ui32Flags);
                return eErr;
        }
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #else
        eErr = PDumpSNPrintf(hScript, ui32MaxLen, "WRW64 :%s:0x%08X 0x%010" IMG_UINT64_FMTSPECX, pszPDumpRegName, ui32Reg, ui64Data);
@@ -2309,7 +2477,7 @@ PVRSRV_ERROR PDumpReg64(IMG_CHAR  *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #endif
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2322,7 +2490,8 @@ PVRSRV_ERROR PDumpReg64(IMG_CHAR  *pszPDumpRegName,
  * Description    : Create a PDUMP string, which represents a register write
  *                  from a register label
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegLabelToReg64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegLabelToReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_CHAR *pszPDumpRegName,
                                   IMG_UINT32 ui32RegDst,
                                   IMG_UINT32 ui32RegSrc,
                                   IMG_UINT32 ui32Flags)
@@ -2339,7 +2508,7 @@ PVRSRV_ERROR PDumpRegLabelToReg64(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2364,9 +2533,12 @@ PVRSRV_ERROR PDumpRegLabelToMem32(IMG_CHAR *pszPDumpRegName,
        IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMR);
+
        eErr = PMR_PDumpSymbolicAddr(psPMR,
                                     uiLogicalOffset,
                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
@@ -2393,7 +2565,7 @@ PVRSRV_ERROR PDumpRegLabelToMem32(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2417,17 +2589,20 @@ PVRSRV_ERROR PDumpRegLabelToMem64(IMG_CHAR *pszPDumpRegName,
        IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMR);
+
        eErr = PMR_PDumpSymbolicAddr(psPMR,
-                                                                        uiLogicalOffset,
-                                                                        PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
-                                                                        aszMemspaceName,
-                                                                        PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
-                                                                        aszSymbolicName,
-                                                                        &uiPDumpSymbolicOffset,
-                                                                        &uiNextSymName);
+                                    uiLogicalOffset,
+                                    PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
+                                    aszMemspaceName,
+                                    PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
+                                    aszSymbolicName,
+                                    &uiPDumpSymbolicOffset,
+                                    &uiNextSymName);
 
        if (eErr != PVRSRV_OK)
        {
@@ -2444,7 +2619,7 @@ PVRSRV_ERROR PDumpRegLabelToMem64(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2458,7 +2633,8 @@ PVRSRV_ERROR PDumpRegLabelToMem64(IMG_CHAR *pszPDumpRegName,
  * Description    : Create a PDUMP string, which represents an internal var
                     write using a PDump pages handle
 ******************************************************************************/
-PVRSRV_ERROR PDumpPhysHandleToInternalVar64(IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpPhysHandleToInternalVar64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                            IMG_CHAR *pszInternalVar,
                                             IMG_HANDLE hPdumpPages,
                                             IMG_UINT32 ui32Flags)
 {
@@ -2488,7 +2664,7 @@ PVRSRV_ERROR PDumpPhysHandleToInternalVar64(IMG_CHAR *pszInternalVar,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
@@ -2510,7 +2686,7 @@ PVRSRV_ERROR PDumpPhysHandleToInternalVar64(IMG_CHAR *pszInternalVar,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #endif
        PDUMP_UNLOCK(ui32Flags);
@@ -2536,12 +2712,15 @@ PVRSRV_ERROR PDumpMemLabelToInternalVar64(IMG_CHAR *pszInternalVar,
        IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        IMG_CHAR *pszPDumpVarName;
 #endif
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMR);
+
        eErr = PMR_PDumpSymbolicAddr(psPMR,
                                     uiLogicalOffset,
                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
@@ -2569,7 +2748,7 @@ PVRSRV_ERROR PDumpMemLabelToInternalVar64(IMG_CHAR *pszInternalVar,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
@@ -2580,7 +2759,17 @@ PVRSRV_ERROR PDumpMemLabelToInternalVar64(IMG_CHAR *pszInternalVar,
                return PVRSRV_ERROR_OUT_OF_MEMORY;
        }
 
-       eErr = PDumpSNPrintf(hScript, ui32MaxLen, "WRW %s 0x%X", pszPDumpVarName, 0);
+       eErr = PDumpSNPrintf(hScript, ui32MaxLen, "WRW %s :%s:%s:0x%"IMG_UINT64_FMTSPECX, pszPDumpVarName,
+                                                       aszMemspaceName, aszSymbolicName, uiPDumpSymbolicOffset);
+       if (eErr != PVRSRV_OK)
+       {
+               PDUMP_RELEASE_SCRIPT_STRING()
+               PDUMP_UNLOCK(ui32Flags);
+               return eErr;
+       }
+
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
+       eErr = PDumpSNPrintf(hScript, ui32MaxLen, "SHR %s %s 0x20", pszPDumpVarName, pszPDumpVarName);
 
        PDumpFreeIncVarNameStr(pszPDumpVarName);
 
@@ -2591,7 +2780,7 @@ PVRSRV_ERROR PDumpMemLabelToInternalVar64(IMG_CHAR *pszInternalVar,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #endif
        PDUMP_UNLOCK(ui32Flags);
@@ -2616,12 +2805,15 @@ PVRSRV_ERROR PDumpInternalVarToMemLabel(PMR *psPMR,
        IMG_CHAR aszSymbolicName[PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH];
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        IMG_CHAR *pszPDumpVarName;
 #endif
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMR);
+
        eErr = PMR_PDumpSymbolicAddr(psPMR,
                                     uiLogicalOffset,
                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
@@ -2649,7 +2841,7 @@ PVRSRV_ERROR PDumpInternalVarToMemLabel(PMR *psPMR,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
@@ -2671,7 +2863,7 @@ PVRSRV_ERROR PDumpInternalVarToMemLabel(PMR *psPMR,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #endif
        PDUMP_UNLOCK(ui32Flags);
@@ -2693,7 +2885,8 @@ PVRSRV_ERROR PDumpInternalVarToMemLabel(PMR *psPMR,
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpWriteVarORValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarORValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    const IMG_CHAR *pszInternalVariable,
                                     const IMG_UINT64 ui64Value,
                                     const IMG_UINT32 ui32PDumpFlags)
 {
@@ -2729,7 +2922,7 @@ PVRSRV_ERROR PDumpWriteVarORValueOp(const IMG_CHAR *pszInternalVariable,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVariable);
@@ -2756,7 +2949,7 @@ PVRSRV_ERROR PDumpWriteVarORValueOp(const IMG_CHAR *pszInternalVariable,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 #endif
 
        PDUMP_UNLOCK(ui32PDumpFlags);
@@ -2778,7 +2971,8 @@ PVRSRV_ERROR PDumpWriteVarORValueOp(const IMG_CHAR *pszInternalVariable,
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpWriteVarORVarOp(const IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpWriteVarORVarOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  const IMG_CHAR *pszInternalVar,
                                   const IMG_CHAR *pszInternalVar2,
                                   const IMG_UINT32 ui32PDumpFlags)
 {
@@ -2800,7 +2994,7 @@ PVRSRV_ERROR PDumpWriteVarORVarOp(const IMG_CHAR *pszInternalVar,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        PDUMP_UNLOCK(ui32PDumpFlags);
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2820,7 +3014,8 @@ PVRSRV_ERROR PDumpWriteVarORVarOp(const IMG_CHAR *pszInternalVar,
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpWriteVarANDVarOp(const IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpWriteVarANDVarOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const IMG_CHAR *pszInternalVar,
                                    const IMG_CHAR *pszInternalVar2,
                                    const IMG_UINT32 ui32PDumpFlags)
 {
@@ -2842,7 +3037,7 @@ PVRSRV_ERROR PDumpWriteVarANDVarOp(const IMG_CHAR *pszInternalVar,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        PDUMP_UNLOCK(ui32PDumpFlags);
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2857,7 +3052,8 @@ PVRSRV_ERROR PDumpWriteVarANDVarOp(const IMG_CHAR *pszInternalVar,
  * Description    : Create a PDUMP string, which writes a register label into
  *                  an internal variable
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegLabelToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegLabelToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        IMG_CHAR *pszPDumpRegName,
                                         IMG_UINT32 ui32Reg,
                                         IMG_CHAR *pszInternalVar,
                                         IMG_UINT32 ui32Flags)
@@ -2877,7 +3073,7 @@ PVRSRV_ERROR PDumpRegLabelToInternalVar(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
@@ -2899,7 +3095,7 @@ PVRSRV_ERROR PDumpRegLabelToInternalVar(IMG_CHAR *pszPDumpRegName,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 #endif
 
        PDUMP_UNLOCK(ui32Flags);
@@ -2915,7 +3111,8 @@ PVRSRV_ERROR PDumpRegLabelToInternalVar(IMG_CHAR *pszPDumpRegName,
  * Description    : Create a PDUMP string, which represents a register write
  *                  from an internal variable
 ******************************************************************************/
-PVRSRV_ERROR PDumpInternalVarToReg32(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpInternalVarToReg32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_CHAR *pszPDumpRegName,
                                      IMG_UINT32 ui32Reg,
                                      IMG_CHAR *pszInternalVar,
                                      IMG_UINT32 ui32Flags)
@@ -2932,7 +3129,7 @@ PVRSRV_ERROR PDumpInternalVarToReg32(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -2946,7 +3143,8 @@ PVRSRV_ERROR PDumpInternalVarToReg32(IMG_CHAR *pszPDumpRegName,
  * Description    : Create a PDUMP string, which represents a register write
  *                  from an internal variable
 ******************************************************************************/
-PVRSRV_ERROR PDumpInternalVarToReg64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpInternalVarToReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_CHAR *pszPDumpRegName,
                                      IMG_UINT32 ui32Reg,
                                      IMG_CHAR *pszInternalVar,
                                      IMG_UINT32 ui32Flags)
@@ -2966,7 +3164,7 @@ PVRSRV_ERROR PDumpInternalVarToReg64(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
        if (pszPDumpVarName == NULL)
@@ -2987,7 +3185,7 @@ PVRSRV_ERROR PDumpInternalVarToReg64(IMG_CHAR *pszPDumpRegName,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
 #else
@@ -3000,7 +3198,7 @@ PVRSRV_ERROR PDumpInternalVarToReg64(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #endif
 
@@ -3032,10 +3230,13 @@ PVRSRV_ERROR PDumpMemLabelToMem32(PMR *psPMRSource,
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
        IMG_DEVMEM_OFFSET_T uiNextSymNameSource;
        IMG_DEVMEM_OFFSET_T uiNextSymNameDest;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMRSource);
+
        eErr = PMR_PDumpSymbolicAddr(psPMRSource,
                                     uiLogicalOffsetSource,
                                     PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
@@ -3081,7 +3282,7 @@ PVRSRV_ERROR PDumpMemLabelToMem32(PMR *psPMRSource,
 
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -3110,18 +3311,21 @@ PVRSRV_ERROR PDumpMemLabelToMem64(PMR *psPMRSource,
        IMG_DEVMEM_OFFSET_T uiPDumpSymbolicOffsetDest;
        IMG_DEVMEM_OFFSET_T uiNextSymNameSource;
        IMG_DEVMEM_OFFSET_T uiNextSymNameDest;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 
 
        PDUMP_GET_SCRIPT_STRING()
 
+       psDeviceNode = PMR_DeviceNode(psPMRSource);
+
        eErr = PMR_PDumpSymbolicAddr(psPMRSource,
-                                                                        uiLogicalOffsetSource,
-                                                                        PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
-                                                                        aszMemspaceNameSource,
-                                                                        PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
-                                                                        aszSymbolicNameSource,
-                                                                        &uiPDumpSymbolicOffsetSource,
-                                                                        &uiNextSymNameSource);
+                                    uiLogicalOffsetSource,
+                                    PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
+                                    aszMemspaceNameSource,
+                                    PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
+                                    aszSymbolicNameSource,
+                                    &uiPDumpSymbolicOffsetSource,
+                                    &uiNextSymNameSource);
 
        if (eErr != PVRSRV_OK)
        {
@@ -3130,13 +3334,13 @@ PVRSRV_ERROR PDumpMemLabelToMem64(PMR *psPMRSource,
        }
 
        eErr = PMR_PDumpSymbolicAddr(psPMRDest,
-                                                                        uiLogicalOffsetDest,
-                                                                        PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
-                                                                        aszMemspaceNameDest,
-                                                                        PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
-                                                                        aszSymbolicNameDest,
-                                                                        &uiPDumpSymbolicOffsetDest,
-                                                                        &uiNextSymNameDest);
+                                    uiLogicalOffsetDest,
+                                    PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH,
+                                    aszMemspaceNameDest,
+                                    PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH,
+                                    aszSymbolicNameDest,
+                                    &uiPDumpSymbolicOffsetDest,
+                                    &uiNextSymNameDest);
 
 
        if (eErr != PVRSRV_OK)
@@ -3158,7 +3362,7 @@ PVRSRV_ERROR PDumpMemLabelToMem64(PMR *psPMRSource,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -3180,7 +3384,8 @@ PVRSRV_ERROR PDumpMemLabelToMem64(PMR *psPMRSource,
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpWriteVarSHRValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarSHRValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     const IMG_CHAR *pszInternalVariable,
                                      const IMG_UINT64 ui64Value,
                                      const IMG_UINT32 ui32PDumpFlags)
 {
@@ -3216,7 +3421,7 @@ PVRSRV_ERROR PDumpWriteVarSHRValueOp(const IMG_CHAR *pszInternalVariable,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVariable);
@@ -3243,7 +3448,7 @@ PVRSRV_ERROR PDumpWriteVarSHRValueOp(const IMG_CHAR *pszInternalVariable,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 #endif
 
        PDUMP_UNLOCK(ui32PDumpFlags);
@@ -3266,7 +3471,8 @@ PVRSRV_ERROR PDumpWriteVarSHRValueOp(const IMG_CHAR *pszInternalVariable,
  @Return   PVRSRV_ERROR
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpWriteVarANDValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarANDValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     const IMG_CHAR *pszInternalVariable,
                                      const IMG_UINT64 ui64Value,
                                      const IMG_UINT32 ui32PDumpFlags)
 {
@@ -3302,7 +3508,7 @@ PVRSRV_ERROR PDumpWriteVarANDValueOp(const IMG_CHAR *pszInternalVariable,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
 #if defined(PDUMP_SPLIT_64BIT_REGISTER_ACCESS)
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVariable);
@@ -3329,7 +3535,7 @@ PVRSRV_ERROR PDumpWriteVarANDValueOp(const IMG_CHAR *pszInternalVariable,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 #endif
 
        PDUMP_UNLOCK(ui32PDumpFlags);
@@ -3352,12 +3558,13 @@ PVRSRV_ERROR PDumpWriteVarANDValueOp(const IMG_CHAR *pszInternalVariable,
  * Description    : Dumps the contents of a register bank into a file
  *                  NB: ui32NumSaveBytes must be divisible by 4
 ******************************************************************************/
-PVRSRV_ERROR PDumpSAW(IMG_CHAR      *pszDevSpaceName,
-                      IMG_UINT32    ui32HPOffsetBytes,
-                      IMG_UINT32    ui32NumSaveBytes,
-                      IMG_CHAR      *pszOutfileName,
-                      IMG_UINT32    ui32OutfileOffsetByte,
-                      PDUMP_FLAGS_T uiPDumpFlags)
+PVRSRV_ERROR PDumpSAW(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_CHAR           *pszDevSpaceName,
+                      IMG_UINT32         ui32HPOffsetBytes,
+                      IMG_UINT32         ui32NumSaveBytes,
+                      IMG_CHAR           *pszOutfileName,
+                      IMG_UINT32         ui32OutfileOffsetByte,
+                      PDUMP_FLAGS_T      uiPDumpFlags)
 {
        PVRSRV_ERROR eError;
 
@@ -3382,7 +3589,7 @@ PVRSRV_ERROR PDumpSAW(IMG_CHAR      *pszDevSpaceName,
        }
 
        PDUMP_LOCK(uiPDumpFlags);
-       if (! PDumpWriteScript(hScript, uiPDumpFlags))
+       if (! PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags))
        {
                PVR_DPF((PVR_DBG_ERROR, "PDumpSAW PDumpWriteScript failed!"));
        }
@@ -3406,7 +3613,8 @@ PVRSRV_ERROR PDumpSAW(IMG_CHAR      *pszDevSpaceName,
  * Description    : Create a PDUMP string which represents a register read
  *                                     with the expected value
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR                            *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegPolKM(PVRSRV_DEVICE_NODE  *psDeviceNode,
+                                                  IMG_CHAR                             *pszPDumpRegName,
                                                   IMG_UINT32                   ui32RegAddr,
                                                   IMG_UINT32                   ui32RegValue,
                                                   IMG_UINT32                   ui32Mask,
@@ -3436,7 +3644,7 @@ PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR                               *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING()
@@ -3468,7 +3676,9 @@ static void _PDumpVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSize
  * Use PDumpCommentWithFlags() from within the server.
  * Clients call this via the bridge and PDumpCommentKM().
  */
-static PVRSRV_ERROR _PDumpWriteComment(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+static PVRSRV_ERROR _PDumpWriteComment(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       IMG_CHAR *pszComment,
+                                       IMG_UINT32 ui32Flags)
 {
        PVRSRV_ERROR eErr;
 #if defined(PDUMP_DEBUG_OUTFILES)
@@ -3519,7 +3729,7 @@ static PVRSRV_ERROR _PDumpWriteComment(IMG_CHAR *pszComment, IMG_UINT32 ui32Flag
                PVR_LOG_GOTO_IF_ERROR(eErr, "PDumpSNPrintf", ErrUnlock);
        }
 
-       if (!PDumpWriteScript(hScript, ui32Flags))
+       if (!PDumpWriteScript(psDeviceNode, hScript, ui32Flags))
        {
                if (PDUMP_IS_CONTINUOUS(ui32Flags))
                {
@@ -3540,70 +3750,82 @@ ErrUnlock:
 
 /******************************************************************************
  * Function Name  : PDumpCommentKM
- * Inputs         : pszComment, ui32Flags
+ * Inputs         : ui32CommentSize, pszComment, ui32Flags
  * Outputs        : None
  * Returns        : None
  * Description    : Dumps a pre-formatted comment, primarily called from the
  *                : bridge.
 ******************************************************************************/
-PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+PVRSRV_ERROR PDumpCommentKM(CONNECTION_DATA *psConnection,
+                            PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_UINT32 ui32CommentSize,
+                            IMG_CHAR *pszComment,
+                            IMG_UINT32 ui32Flags)
 {
        PVRSRV_ERROR eErr = PVRSRV_OK;
 
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVR_UNREFERENCED_PARAMETER(ui32CommentSize); /* Generated bridge code appends null char to pszComment. */
+
        PDUMP_LOCK(ui32Flags);
 
-       eErr = _PDumpWriteComment(pszComment, ui32Flags);
+       eErr = _PDumpWriteComment(psDeviceNode, pszComment, ui32Flags);
 
        PDUMP_UNLOCK(ui32Flags);
        return eErr;
 }
 
 /******************************************************************************
- * Function Name  : PDumpCommentWithFlagsNoLock
+ * Function Name  : PDumpCommentWithFlagsNoLockVA
  * Inputs         : ui32Flags - PDump flags
  *                               : pszFormat - format string for comment
- *                               : ... - args for format string
+ *                               : args      - pre-started va_list args for format string
  * Outputs        : None
  * Returns        : None
  * Description    : PDumps a comment, caller need to acquire pdump lock
- *                  explicitly before calling this function.
+ *                  explicitly before calling this function
 ******************************************************************************/
-PVRSRV_ERROR PDumpCommentWithFlagsNoLock(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+static PVRSRV_ERROR PDumpCommentWithFlagsNoLockVA(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           IMG_UINT32 ui32Flags,
+                                           const IMG_CHAR * pszFormat, va_list args)
 {
+       IMG_INT32 iCount;
        PVRSRV_ERROR eErr = PVRSRV_OK;
-       va_list args;
+       PDUMP_GET_MSG_STRING();
 
-       va_start(args, pszFormat);
-       PDumpCommentWithFlagsNoLockVA(ui32Flags, pszFormat, args);
-       va_end(args);
+       /* Construct the string */
+       iCount = OSVSNPrintf(pszMsg, ui32MaxLen, pszFormat, args);
+       PVR_LOG_GOTO_IF_FALSE(((iCount != -1) && (iCount < ui32MaxLen)), "OSVSNPrintf", exit);
 
+       eErr = _PDumpWriteComment(psDeviceNode, pszMsg, ui32Flags);
+
+exit:
+       PDUMP_RELEASE_MSG_STRING();
        return eErr;
 }
 
 /******************************************************************************
- * Function Name  : PDumpCommentWithFlagsNoLockVA
+ * Function Name  : PDumpCommentWithFlagsNoLock
  * Inputs         : ui32Flags - PDump flags
  *                               : pszFormat - format string for comment
- *                               : args      - pre-started va_list args for format string
+ *                               : ... - args for format string
  * Outputs        : None
  * Returns        : None
  * Description    : PDumps a comment, caller need to acquire pdump lock
- *                  explicitly before calling this function
+ *                  explicitly before calling this function.
 ******************************************************************************/
-PVRSRV_ERROR PDumpCommentWithFlagsNoLockVA(IMG_UINT32 ui32Flags, const IMG_CHAR * pszFormat, va_list args)
+__printf(3, 4)
+static PVRSRV_ERROR PDumpCommentWithFlagsNoLock(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                         IMG_UINT32 ui32Flags,
+                                         IMG_CHAR *pszFormat, ...)
 {
-       IMG_INT32 iCount;
        PVRSRV_ERROR eErr = PVRSRV_OK;
-       PDUMP_GET_MSG_STRING();
-
-       /* Construct the string */
-       iCount = OSVSNPrintf(pszMsg, ui32MaxLen, pszFormat, args);
-       PVR_LOG_GOTO_IF_FALSE(((iCount != -1) && (iCount < ui32MaxLen)), "OSVSNPrintf", exit);
+       va_list args;
 
-       eErr = _PDumpWriteComment(pszMsg, ui32Flags);
+       va_start(args, pszFormat);
+       PDumpCommentWithFlagsNoLockVA(psDeviceNode, ui32Flags, pszFormat, args);
+       va_end(args);
 
-exit:
-       PDUMP_RELEASE_MSG_STRING();
        return eErr;
 }
 
@@ -3616,13 +3838,15 @@ exit:
  * Returns        : None
  * Description    : PDumps a comments
 ******************************************************************************/
-PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
+PVRSRV_ERROR PDumpCommentWithFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   IMG_UINT32 ui32Flags,
+                                   IMG_CHAR * pszFormat, ...)
 {
        PVRSRV_ERROR eErr = PVRSRV_OK;
        va_list args;
 
        va_start(args, pszFormat);
-       PDumpCommentWithFlagsVA(ui32Flags, pszFormat, args);
+       PDumpCommentWithFlagsVA(psDeviceNode, ui32Flags, pszFormat, args);
        va_end(args);
 
        return eErr;
@@ -3637,7 +3861,9 @@ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, .
  * Returns        : None
  * Description    : PDumps a comments
 ******************************************************************************/
-PVRSRV_ERROR PDumpCommentWithFlagsVA(IMG_UINT32 ui32Flags, const IMG_CHAR * pszFormat, va_list args)
+PVRSRV_ERROR PDumpCommentWithFlagsVA(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_UINT32 ui32Flags,
+                                     const IMG_CHAR * pszFormat, va_list args)
 {
        IMG_INT32 iCount;
        PVRSRV_ERROR eErr = PVRSRV_OK;
@@ -3648,7 +3874,7 @@ PVRSRV_ERROR PDumpCommentWithFlagsVA(IMG_UINT32 ui32Flags, const IMG_CHAR * pszF
        PVR_LOG_GOTO_IF_FALSE(((iCount != -1) && (iCount < ui32MaxLen)), "OSVSNPrintf", exit);
 
        PDUMP_LOCK(ui32Flags);
-       eErr = _PDumpWriteComment(pszMsg, ui32Flags);
+       eErr = _PDumpWriteComment(psDeviceNode, pszMsg, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
 exit:
@@ -3664,7 +3890,9 @@ exit:
  * Returns        : PVRSRV_ERROR
  * Description    : PDumps a COM command
 ******************************************************************************/
-PVRSRV_ERROR PDumpCOMCommand(IMG_UINT32 ui32PDumpFlags, const IMG_CHAR * pszPdumpStr)
+PVRSRV_ERROR PDumpCOMCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             IMG_UINT32 ui32PDumpFlags,
+                             const IMG_CHAR * pszPdumpStr)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -3678,7 +3906,7 @@ PVRSRV_ERROR PDumpCOMCommand(IMG_UINT32 ui32PDumpFlags, const IMG_CHAR * pszPdum
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -3697,7 +3925,8 @@ PVRSRV_ERROR PDumpCOMCommand(IMG_UINT32 ui32PDumpFlags, const IMG_CHAR * pszPdum
  *                : detects a condition that will lead to an invalid PDump
  *                : script that cannot be played back off-line.
  */ /*************************************************************************/
-PVRSRV_ERROR PDumpPanic(IMG_UINT32      ui32PanicNo,
+PVRSRV_ERROR PDumpPanic(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                               IMG_UINT32      ui32PanicNo,
                                                IMG_CHAR*       pszPanicMsg,
                                                const IMG_CHAR* pszPPFunc,
                                                IMG_UINT32      ui32PPline)
@@ -3722,26 +3951,26 @@ PVRSRV_ERROR PDumpPanic(IMG_UINT32      ui32PanicNo,
        /* Write -- Panic start (Function:line) */
        eError = PDumpSNPrintf(hScript, ui32MaxLen, "-- Panic start (%s:%d)", pszPPFunc, ui32PPline);
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpSNPrintf", e1);
-       (void)PDumpWriteScript(hScript, uiPDumpFlags);
+       (void)PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
        /* Write COM messages */
-       eError = PDumpCOMCommand(uiPDumpFlags,
+       eError = PDumpCOMCommand(psDeviceNode, uiPDumpFlags,
                                  "**** Script invalid and not compatible with off-line playback. ****");
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpCOMCommand", e1);
 
-       eError = PDumpCOMCommand(uiPDumpFlags,
+       eError = PDumpCOMCommand(psDeviceNode, uiPDumpFlags,
                                  "**** Check test parameters and driver configuration, stop imminent. ****");
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpCOMCommand", e1);
 
        /* Write PANIC no msg command */
        eError = PDumpSNPrintf(hScript, ui32MaxLen, "PANIC %08x %s", ui32PanicNo, pszPanicMsg);
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpSNPrintf", e1);
-       (void)PDumpWriteScript(hScript, uiPDumpFlags);
+       (void)PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
        /* Write -- Panic end */
        eError = PDumpSNPrintf(hScript, ui32MaxLen, "-- Panic end");
        PVR_LOG_GOTO_IF_ERROR(eError, "PDumpSNPrintf", e1);
-       (void)PDumpWriteScript(hScript, uiPDumpFlags);
+       (void)PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
 e1:
        PDUMP_BLKEND(uiPDumpFlags);
@@ -3762,10 +3991,11 @@ e1:
  *                : play back to inform user of a fatal issue that occurred
  *                : during PDump capture.
  */ /*************************************************************************/
-PVRSRV_ERROR PDumpCaptureError(PVRSRV_ERROR    ui32ErrorNo,
-                       IMG_CHAR*       pszErrorMsg,
-                       const IMG_CHAR* pszPPFunc,
-                       IMG_UINT32      ui32PPline)
+PVRSRV_ERROR PDumpCaptureError(PVRSRV_DEVICE_NODE *psDeviceNode,
+                               PVRSRV_ERROR       ui32ErrorNo,
+                               IMG_CHAR*          pszErrorMsg,
+                               const IMG_CHAR     *pszPPFunc,
+                               IMG_UINT32         ui32PPline)
 {
        IMG_CHAR*       pszFormatStr = "DRIVER_ERROR: %3d: %s";
        PDUMP_FLAGS_T   uiPDumpFlags = PDUMP_FLAGS_CONTINUOUS;
@@ -3782,7 +4012,7 @@ PVRSRV_ERROR PDumpCaptureError(PVRSRV_ERROR    ui32ErrorNo,
        /* Obtain lock to keep the multi-line
         * panic statement together in a single atomic write */
        PDUMP_LOCK(uiPDumpFlags);
-       (void) PDumpWriteScript(hScript, uiPDumpFlags);
+       (void) PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        PDUMP_UNLOCK(uiPDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -3792,282 +4022,6 @@ PVRSRV_ERROR PDumpCaptureError(PVRSRV_ERROR    ui32ErrorNo,
 /*!
 *******************************************************************************
 
- @Function     PDumpBitmapKM
-
- @Description
-
- Dumps a bitmap from device memory to a file
-
- @Input    psDevId
- @Input    pszFileName
- @Input    ui32FileOffset
- @Input    ui32Width
- @Input    ui32Height
- @Input    ui32StrideInBytes
- @Input    sDevBaseAddr
- @Input    ui32Size
- @Input    ePixelFormat
- @Input    eMemFormat
- @Input    ui32PDumpFlags
-
- @Return   PVRSRV_ERROR                        :
-
-******************************************************************************/
-PVRSRV_ERROR PDumpBitmapKM(    PVRSRV_DEVICE_NODE *psDeviceNode,
-                                                       IMG_CHAR *pszFileName,
-                                                       IMG_UINT32 ui32FileOffset,
-                                                       IMG_UINT32 ui32Width,
-                                                       IMG_UINT32 ui32Height,
-                                                       IMG_UINT32 ui32StrideInBytes,
-                                                       IMG_DEV_VIRTADDR sDevBaseAddr,
-                                                       IMG_UINT32 ui32MMUContextID,
-                                                       IMG_UINT32 ui32Size,
-                                                       PDUMP_PIXEL_FORMAT ePixelFormat,
-                                                       IMG_UINT32 ui32AddrMode,
-                                                       IMG_UINT32 ui32PDumpFlags)
-{
-       PVRSRV_DEVICE_IDENTIFIER *psDevId = &psDeviceNode->sDevId;
-       PVRSRV_ERROR eErr = PVRSRV_OK;
-       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       IMG_BOOL bIsFBC31 = psDevInfo->psRGXFWIfFwSysData->
-                               ui32ConfigFlags & RGXFWIF_INICFG_FBCDC_V3_1_EN;
-       PDUMP_GET_SCRIPT_STRING();
-
-       PDUMP_LOCK(ui32PDumpFlags);
-
-       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "Dump bitmap of render.");
-
-       /* Overwrite incoming addrmode compat field if FBC v3.1 is enabled. */
-       if (bIsFBC31 &&
-               (ui32AddrMode & PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_MASK) == PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_RESOURCE)
-       {
-               ui32AddrMode &= ~PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_MASK;
-               ui32AddrMode |= PVRSRV_PDUMP_ADDRMODE_FBCCOMPAT_V3_1_RESOURCE;
-       }
-
-       switch (ePixelFormat)
-       {
-               case PVRSRV_PDUMP_PIXEL_FORMAT_YUV8:
-               {
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YUV data. Switching from SII to SAB. Width=0x%08X Height=0x%08X Stride=0x%08X",
-                                                                                                       ui32Width, ui32Height, ui32StrideInBytes);
-                       eErr = PDumpSNPrintf(hScript,
-                                                                       ui32MaxLen,
-                                                                       "SAB :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X %s.bin\n",
-                                                                       psDevId->pszPDumpDevName,
-                                                                       ui32MMUContextID,
-                                                                       sDevBaseAddr.uiAddr,
-                                                                       ui32Size,
-                                                                       ui32FileOffset,
-                                                                       pszFileName);
-
-                       PVR_GOTO_IF_ERROR(eErr, error);
-
-                       PDumpWriteScript(hScript, ui32PDumpFlags);
-                       break;
-               }
-               case PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8: // YUV420 2 planes
-               {
-                       const IMG_UINT32 ui32Plane0Size = ui32StrideInBytes*ui32Height;
-                       const IMG_UINT32 ui32Plane1Size = ui32Plane0Size>>1; // YUV420
-                       const IMG_UINT32 ui32Plane1FileOffset = ui32FileOffset + ui32Plane0Size;
-                       const IMG_UINT32 ui32Plane1MemOffset = ui32Plane0Size;
-
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YUV420 2-plane. Width=0x%08X Height=0x%08X Stride=0x%08X",
-                                                                                                       ui32Width, ui32Height, ui32StrideInBytes);
-                       eErr = PDumpSNPrintf(hScript,
-                                               ui32MaxLen,
-                                               "SII %s %s.bin :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X",
-                                               pszFileName,
-                                               pszFileName,
-
-                                               // Plane 0 (Y)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // Context id
-                                               sDevBaseAddr.uiAddr,            // virtaddr
-                                               ui32Plane0Size,                         // size
-                                               ui32FileOffset,                         // fileoffset
-
-                                               // Plane 1 (UV)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // Context id
-                                               sDevBaseAddr.uiAddr+ui32Plane1MemOffset,        // virtaddr
-                                               ui32Plane1Size,                         // size
-                                               ui32Plane1FileOffset,           // fileoffset
-
-                                               ePixelFormat,
-                                               ui32Width,
-                                               ui32Height,
-                                               ui32StrideInBytes,
-                                               ui32AddrMode);
-
-                       PVR_GOTO_IF_ERROR(eErr, error);
-
-                       PDumpWriteScript(hScript, ui32PDumpFlags);
-                       break;
-               }
-
-               case PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12: // YUV420 3 planes
-               {
-                       const IMG_UINT32 ui32Plane0Size = ui32StrideInBytes*ui32Height;
-                       const IMG_UINT32 ui32Plane1Size = ui32Plane0Size>>2; // YUV420
-                       const IMG_UINT32 ui32Plane2Size = ui32Plane1Size;
-                       const IMG_UINT32 ui32Plane1FileOffset = ui32FileOffset + ui32Plane0Size;
-                       const IMG_UINT32 ui32Plane2FileOffset = ui32Plane1FileOffset + ui32Plane1Size;
-                       const IMG_UINT32 ui32Plane1MemOffset = ui32Plane0Size;
-                       const IMG_UINT32 ui32Plane2MemOffset = ui32Plane0Size+ui32Plane1Size;
-
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YUV420 3-plane. Width=0x%08X Height=0x%08X Stride=0x%08X",
-                                                                                                       ui32Width, ui32Height, ui32StrideInBytes);
-                       eErr = PDumpSNPrintf(hScript,
-                                               ui32MaxLen,
-                                               "SII %s %s.bin :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X",
-                                               pszFileName,
-                                               pszFileName,
-
-                                               // Plane 0 (Y)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr,            // virtaddr
-                                               ui32Plane0Size,                         // size
-                                               ui32FileOffset,                         // fileoffset
-
-                                               // Plane 1 (U)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane1MemOffset,        // virtaddr
-                                               ui32Plane1Size,                         // size
-                                               ui32Plane1FileOffset,           // fileoffset
-
-                                               // Plane 2 (V)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane2MemOffset,        // virtaddr
-                                               ui32Plane2Size,                         // size
-                                               ui32Plane2FileOffset,           // fileoffset
-
-                                               ePixelFormat,
-                                               ui32Width,
-                                               ui32Height,
-                                               ui32StrideInBytes,
-                                               ui32AddrMode);
-
-                       PVR_GOTO_IF_ERROR(eErr, error);
-
-                       PDumpWriteScript(hScript, ui32PDumpFlags);
-                       break;
-               }
-
-               case PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV32: // YV32 - 4 contiguous planes in the order VUYA, stride can be > width.
-               {
-                       const IMG_UINT32 ui32PlaneSize = ui32StrideInBytes*ui32Height; // All 4 planes are the same size
-                       const IMG_UINT32 ui32Plane0FileOffset = ui32FileOffset + (ui32PlaneSize<<1);            // SII plane 0 is Y, which is YV32 plane 2
-                       const IMG_UINT32 ui32Plane1FileOffset = ui32FileOffset + ui32PlaneSize;                         // SII plane 1 is U, which is YV32 plane 1
-                       const IMG_UINT32 ui32Plane2FileOffset = ui32FileOffset;                                                         // SII plane 2 is V, which is YV32 plane 0
-                       const IMG_UINT32 ui32Plane3FileOffset = ui32Plane0FileOffset + ui32PlaneSize;           // SII plane 3 is A, which is YV32 plane 3
-                       const IMG_UINT32 ui32Plane0MemOffset = ui32PlaneSize<<1;
-                       const IMG_UINT32 ui32Plane1MemOffset = ui32PlaneSize;
-                       const IMG_UINT32 ui32Plane2MemOffset = 0;
-                       const IMG_UINT32 ui32Plane3MemOffset = ui32Plane0MemOffset + ui32PlaneSize;
-
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 4 planes. Width=0x%08X Height=0x%08X Stride=0x%08X",
-                                                                                                       ui32Width, ui32Height, ui32StrideInBytes);
-
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 plane size is 0x%08X", ui32PlaneSize);
-
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 Plane 0 Mem Offset=0x%08X", ui32Plane0MemOffset);
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 Plane 1 Mem Offset=0x%08X", ui32Plane1MemOffset);
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 Plane 2 Mem Offset=0x%08X", ui32Plane2MemOffset);
-                       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YV32 Plane 3 Mem Offset=0x%08X", ui32Plane3MemOffset);
-
-                       /*
-                               SII <imageset> <filename>       :<memsp1>:v<id1>:<virtaddr1> <size1> <fileoffset1>              Y
-                                                                                       :<memsp2>:v<id2>:<virtaddr2> <size2> <fileoffset2>              U
-                                                                                       :<memsp3>:v<id3>:<virtaddr3> <size3> <fileoffset3>              V
-                                                                                       :<memsp4>:v<id4>:<virtaddr4> <size4> <fileoffset4>              A
-                                                                                       <pixfmt> <width> <height> <stride> <addrmode>
-                       */
-                       eErr = PDumpSNPrintf(hScript,
-                                               ui32MaxLen,
-                                               "SII %s %s.bin :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X",
-                                               pszFileName,
-                                               pszFileName,
-
-                                               // Plane 0 (V)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane0MemOffset,        // virtaddr
-                                               ui32PlaneSize,                          // size
-                                               ui32Plane0FileOffset,           // fileoffset
-
-                                               // Plane 1 (U)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane1MemOffset,        // virtaddr
-                                               ui32PlaneSize,                          // size
-                                               ui32Plane1FileOffset,           // fileoffset
-
-                                               // Plane 2 (Y)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane2MemOffset,        // virtaddr
-                                               ui32PlaneSize,                          // size
-                                               ui32Plane2FileOffset,           // fileoffset
-
-                                               // Plane 3 (A)
-                                               psDevId->pszPDumpDevName,       // memsp
-                                               ui32MMUContextID,                       // MMU context id
-                                               sDevBaseAddr.uiAddr+ui32Plane3MemOffset,        // virtaddr
-                                               ui32PlaneSize,                          // size
-                                               ui32Plane3FileOffset,           // fileoffset
-
-                                               ePixelFormat,
-                                               ui32Width,
-                                               ui32Height,
-                                               ui32StrideInBytes,
-                                               ui32AddrMode);
-
-                       PVR_GOTO_IF_ERROR(eErr, error);
-
-                       PDumpWriteScript(hScript, ui32PDumpFlags);
-                       break;
-               }
-
-               default: // Single plane formats
-               {
-                       eErr = PDumpSNPrintf(hScript,
-                                               ui32MaxLen,
-                                               "SII %s %s.bin :%s:v%x:0x%010"IMG_UINT64_FMTSPECX" 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X",
-                                               pszFileName,
-                                               pszFileName,
-                                               psDevId->pszPDumpDevName,
-                                               ui32MMUContextID,
-                                               sDevBaseAddr.uiAddr,
-                                               ui32Size,
-                                               ui32FileOffset,
-                                               ePixelFormat,
-                                               ui32Width,
-                                               ui32Height,
-                                               ui32StrideInBytes,
-                                               ui32AddrMode);
-
-                       PVR_GOTO_IF_ERROR(eErr, error);
-
-                       PDumpWriteScript(hScript, ui32PDumpFlags);
-                       break;
-               }
-       }
-
-error:
-       PDUMP_UNLOCK(ui32PDumpFlags);
-
-       PDUMP_RELEASE_SCRIPT_STRING()
-       return eErr;
-}
-
-/*!
-*******************************************************************************
-
  @Function     PDumpImageDescriptor
 
  @Description
@@ -4141,7 +4095,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        /* Prepare OutputImage descriptor header */
-       eErr = RGXPDumpPrepareOutputImageDescriptorHdr( psDeviceNode,
+       eErr = RGXPDumpPrepareOutputImageDescriptorHdr(psDeviceNode,
                                                                        ui32HeaderSize,
                                                                        ui32DataSize,
                                                                        ui32LogicalWidth,
@@ -4158,7 +4112,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        PDUMP_LOCK(ui32PDumpFlags);
 
-       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "Dump Image descriptor");
+       PDumpCommentWithFlagsNoLock(psDeviceNode, ui32PDumpFlags, "Dump Image descriptor");
 
        bRawImageData =
                 (ePixFmt == PVRSRV_PDUMP_PIXEL_FORMAT_YUV8
@@ -4189,8 +4143,9 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                IMG_UINT32 ui32ElementType;
                IMG_UINT32 ui32ElementCount;
 
-               PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "YUV data. Switching from OutputImage to SAB. Width=0x%08X Height=0x%08X",
-                                                         ui32LogicalWidth, ui32LogicalHeight);
+               PDumpCommentWithFlagsNoLock(psDeviceNode, ui32PDumpFlags,
+                                           "YUV data. Switching from OutputImage to SAB. Width=0x%08X Height=0x%08X",
+                                           ui32LogicalWidth, ui32LogicalHeight);
 
                PDUMP_UNLOCK(ui32PDumpFlags);
 
@@ -4212,7 +4167,8 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        /* Write OutputImage descriptor header to parameter file */
-       eErr = PDumpWriteParameter(abyPDumpDesc,
+       eErr = PDumpWriteParameter(psDeviceNode,
+                                                          abyPDumpDesc,
                                                           IMAGE_HEADER_SIZE,
                                                           ui32PDumpFlags,
                                                           &ui32ParamOutPos,
@@ -4221,7 +4177,8 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
        {
                if (eErr != PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
                {
-                       PDUMP_ERROR(eErr, "Failed to write device allocation to parameter file");
+                       PDUMP_ERROR(psDeviceNode, eErr,
+                                   "Failed to write device allocation to parameter file");
                        PVR_LOG_ERROR(eErr, "PDumpWriteParameter");
                }
                else
@@ -4242,7 +4199,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        IMAGE_HEADER_SIZE,
                                                        IMAGE_HEADER_SIZE);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
@@ -4252,7 +4209,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        ui32ParamOutPos,
                                                        pszFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
@@ -4261,7 +4218,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        IMAGE_HEADER_SIZE,
                                                        pszSABFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        ui32SABOffset += IMAGE_HEADER_SIZE;
 
@@ -4280,7 +4237,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                                ui32SABOffset,
                                                                pszSABFileName);
                PVR_GOTO_IF_ERROR(eErr, error);
-               PDumpWriteScript(hScript, ui32PDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
                ui32SABOffset += ui32HeaderSize;
        }
@@ -4299,7 +4256,7 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        pszSABFileName);
 
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        /*
         * The OutputImage command is required to trigger processing of the output
@@ -4310,14 +4267,14 @@ PVRSRV_ERROR PDumpImageDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        "CMD:OutputImage %s.bin\n",
                                                        pszSABFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
                                                        "FREE :%s:BINHEADER\n",
                                                        pszPDumpDevName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
 error:
        PDUMP_UNLOCK(ui32PDumpFlags);
@@ -4401,7 +4358,7 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        /* Prepare OutputData descriptor header */
-       eErr = RGXPDumpPrepareOutputDataDescriptorHdr(  psDeviceNode,
+       eErr = RGXPDumpPrepareOutputDataDescriptorHdr(psDeviceNode,
                                                                        ui32HeaderType,
                                                                        ui32DataSize,
                                                                        ui32ElementType,
@@ -4411,10 +4368,11 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        PDUMP_LOCK(ui32PDumpFlags);
 
-       PDumpCommentWithFlagsNoLock(ui32PDumpFlags, "Dump Data descriptor");
+       PDumpCommentWithFlagsNoLock(psDeviceNode, ui32PDumpFlags, "Dump Data descriptor");
 
        /* Write OutputImage command header to parameter file */
-       eErr = PDumpWriteParameter(abyPDumpDesc,
+       eErr = PDumpWriteParameter(psDeviceNode,
+                                                          abyPDumpDesc,
                                                           ui32HeaderSize,
                                                           ui32PDumpFlags,
                                                           &ui32ParamOutPos,
@@ -4423,7 +4381,8 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
        {
                if (eErr != PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
                {
-                       PDUMP_ERROR(eErr, "Failed to write device allocation to parameter file");
+                       PDUMP_ERROR(psDeviceNode, eErr,
+                                   "Failed to write device allocation to parameter file");
                        PVR_LOG_ERROR(eErr, "PDumpWriteParameter");
                }
                else
@@ -4444,7 +4403,7 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        ui32HeaderSize,
                                                        ui32HeaderSize);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
@@ -4454,7 +4413,7 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        ui32ParamOutPos,
                                                        pszFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
@@ -4463,7 +4422,7 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        ui32HeaderSize,
                                                        pszSABFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        ui32SABOffset += ui32HeaderSize;
 
@@ -4481,7 +4440,7 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        pszSABFileName);
 
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        /*
         * The OutputData command is required to trigger processing of the output
@@ -4492,14 +4451,14 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                        "CMD:OutputData %s.bin\n",
                                                        pszSABFileName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
        eErr = PDumpSNPrintf(hScript,
                                                        ui32MaxLenScript,
                                                        "FREE :%s:BINHEADER\n",
                                                        pszPDumpDevName);
        PVR_GOTO_IF_ERROR(eErr, error);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
 
 error:
        PDUMP_UNLOCK(ui32PDumpFlags);
@@ -4528,12 +4487,13 @@ error_release_script:
  @Return   PVRSRV_ERROR                        :
 
 ******************************************************************************/
-PVRSRV_ERROR PDumpReadRegKM            (       IMG_CHAR *pszPDumpRegName,
-                                                                       IMG_CHAR *pszFileName,
-                                                                       IMG_UINT32 ui32FileOffset,
-                                                                       IMG_UINT32 ui32Address,
-                                                                       IMG_UINT32 ui32Size,
-                                                                       IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpReadRegKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_CHAR *pszPDumpRegName,
+                            IMG_CHAR *pszFileName,
+                            IMG_UINT32 ui32FileOffset,
+                            IMG_UINT32 ui32Address,
+                            IMG_UINT32 ui32Size,
+                            IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING();
@@ -4554,7 +4514,7 @@ PVRSRV_ERROR PDumpReadRegKM               (       IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -4568,7 +4528,8 @@ PVRSRV_ERROR PDumpReadRegKM               (       IMG_CHAR *pszPDumpRegName,
  * Description    : Create a PDUMP string, which reads register into an
  *                  internal variable
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegRead32ToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead32ToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_CHAR *pszPDumpRegName,
                                                        IMG_UINT32 ui32Reg,
                                                        IMG_CHAR *pszInternalVar,
                                                        IMG_UINT32 ui32Flags)
@@ -4591,7 +4552,7 @@ PVRSRV_ERROR PDumpRegRead32ToInternalVar(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -4606,7 +4567,8 @@ PVRSRV_ERROR PDumpRegRead32ToInternalVar(IMG_CHAR *pszPDumpRegName,
  @param                ui32Flags - pdump flags
  @return       Error
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_CHAR *pszPDumpRegName,
                                                        const IMG_UINT32 ui32RegOffset,
                                                        IMG_UINT32 ui32Flags)
 {
@@ -4623,7 +4585,7 @@ PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -4638,7 +4600,8 @@ PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
  @param     ui32Flags - pdump flags
  @return    Error
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead64ToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_CHAR *pszPDumpRegName,
                             IMG_CHAR *pszInternalVar,
                             const IMG_UINT32 ui32RegOffset,
                             IMG_UINT32 ui32Flags)
@@ -4661,7 +4624,7 @@ PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        pszPDumpVarName = PDumpCreateIncVarNameStr(pszInternalVar);
        if (pszPDumpVarName == NULL)
@@ -4685,7 +4648,7 @@ PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
                return eErr;
        }
 
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
 #else
@@ -4700,7 +4663,7 @@ PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #endif
 
@@ -4717,7 +4680,8 @@ PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
  @param                ui32Flags - pdump flags
  @return       Error
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_CHAR *pszPDumpRegName,
                                                        const IMG_UINT32 ui32RegOffset,
                                                        IMG_UINT32 ui32Flags)
 {
@@ -4733,7 +4697,7 @@ PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
                return eErr;
        }
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
 
        eErr = PDumpSNPrintf(hScript, ui32MaxLen, "RDW :%s:0x%X",
                                                        pszPDumpRegName, ui32RegOffset + 4);
@@ -4743,7 +4707,7 @@ PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
                PDUMP_UNLOCK(ui32Flags);
                return eErr;
        }
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #else
        eErr = PDumpSNPrintf(hScript, ui32MaxLen, "RDW64 :%s:0x%X",
@@ -4756,7 +4720,7 @@ PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 #endif
 
@@ -4780,7 +4744,8 @@ PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
  RETURNS       : None
 ******************************************************************************/
 PVRSRV_ERROR
-PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
+PDumpWriteShiftedMaskedValue(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             const IMG_CHAR *pszDestRegspaceName,
                              const IMG_CHAR *pszDestSymbolicName,
                              IMG_DEVMEM_OFFSET_T uiDestOffset,
                              const IMG_CHAR *pszRefRegspaceName,
@@ -4829,7 +4794,7 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
                       uiRefOffset);
        PVR_GOTO_IF_ERROR(eError, ErrUnlock);
 
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
        if (uiSHRAmount > 0)
        {
@@ -4845,7 +4810,7 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
                               /* src B */
                               uiSHRAmount);
                PVR_GOTO_IF_ERROR(eError, ErrUnlock);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        }
 
        if (uiSHLAmount > 0)
@@ -4862,7 +4827,7 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
                               /* src B */
                               uiSHLAmount);
                PVR_GOTO_IF_ERROR(eError, ErrUnlock);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        }
 
        if (uiMask != (1ULL << (8*uiWordSize))-1)
@@ -4879,7 +4844,7 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
                               /* src B */
                               uiMask);
                PVR_GOTO_IF_ERROR(eError, ErrUnlock);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        }
 
        eError = PDumpSNPrintf(hScript,
@@ -4894,7 +4859,7 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
                       pszPDumpIntRegSpace,
                       uiPDumpIntRegNum);
        PVR_GOTO_IF_ERROR(eError, ErrUnlock);
-       PDumpWriteScript(hScript, uiPDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
 ErrUnlock:
        PDUMP_UNLOCK(uiPDumpFlags);
@@ -4905,7 +4870,8 @@ ErrUnlock:
 
 
 PVRSRV_ERROR
-PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
+PDumpWriteSymbAddress(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      const IMG_CHAR *pszDestSpaceName,
                       IMG_DEVMEM_OFFSET_T uiDestOffset,
                       const IMG_CHAR *pszRefSymbolicName,
                       IMG_DEVMEM_OFFSET_T uiRefOffset,
@@ -4940,7 +4906,7 @@ PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
                                       pszRefSymbolicName,
                                       uiRefOffset);
                PVR_GOTO_IF_ERROR(eError, symbAddress_error);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
                /* apply address alignment */
                eError = PDumpSNPrintf(hScript,
@@ -4953,7 +4919,7 @@ PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
                                       /* src B */
                                       ui32AlignShift);
                PVR_GOTO_IF_ERROR(eError, symbAddress_error);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
                /* apply address shift */
                eError = PDumpSNPrintf(hScript,
@@ -4966,7 +4932,7 @@ PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
                                       /* src B */
                                       ui32Shift);
                PVR_GOTO_IF_ERROR(eError, symbAddress_error);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
 
 
                /* write result to register */
@@ -4978,7 +4944,7 @@ PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
                                       (IMG_UINT32)uiDestOffset,
                                       pszPDumpDevName);
                PVR_GOTO_IF_ERROR(eError, symbAddress_error);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        }
        else
        {
@@ -4993,7 +4959,7 @@ PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
                                       pszRefSymbolicName,
                                       uiRefOffset);
                PVR_GOTO_IF_ERROR(eError, symbAddress_error);
-               PDumpWriteScript(hScript, uiPDumpFlags);
+               PDumpWriteScript(psDeviceNode, hScript, uiPDumpFlags);
        }
 
 symbAddress_error:
@@ -5010,7 +4976,8 @@ symbAddress_error:
  * Returns        : Error
  * Description    : Dump IDL command to script
 ******************************************************************************/
-PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
+PVRSRV_ERROR PDumpIDLWithFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
+                               IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING();
@@ -5023,7 +4990,7 @@ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5038,9 +5005,10 @@ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
  * Returns        : Error
  * Description    : Dump IDL command to script
 ******************************************************************************/
-PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
+PVRSRV_ERROR PDumpIDL(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_UINT32 ui32Clocks)
 {
-       return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+       return PDumpIDLWithFlags(psDeviceNode, ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
 }
 
 /******************************************************************************
@@ -5051,7 +5019,8 @@ PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
  * Returns        : Error
  * Description    : Dump CBP command to script
 ******************************************************************************/
-PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR         *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegBasedCBP(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                         IMG_CHAR              *pszPDumpRegName,
                                                          IMG_UINT32    ui32RegOffset,
                                                          IMG_UINT32    ui32WPosVal,
                                                          IMG_UINT32    ui32PacketSize,
@@ -5076,14 +5045,15 @@ PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR          *pszPDumpRegName,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
+PVRSRV_ERROR PDumpTRG(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_CHAR *pszMemSpace,
                       IMG_UINT32 ui32MMUCtxID,
                       IMG_UINT32 ui32RegionID,
                       IMG_BOOL bEnable,
@@ -5116,7 +5086,7 @@ PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
        }
 
        PDUMP_LOCK(ui32Flags);
-       PDumpWriteScript(hScript, ui32Flags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32Flags);
        PDUMP_UNLOCK(ui32Flags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5129,10 +5099,8 @@ PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
  * Description    : Called by the srvcore to tell PDump core that the
  *                  PDump capture and control client has connected
 ******************************************************************************/
-void PDumpConnectionNotify(void)
+void PDumpConnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       PVRSRV_DATA                     *psPVRSRVData = PVRSRVGetPVRSRVData();
-       PVRSRV_DEVICE_NODE      *psThis;
 #if defined(TL_BUFFER_STATS)
        PVRSRV_ERROR            eErr;
 #endif
@@ -5169,16 +5137,10 @@ void PDumpConnectionNotify(void)
        PVR_LOG_IF_ERROR(eErr, "TLStreamResetByteCount Script Main");
 #endif
 
-       /* Loop over all known devices */
-       psThis = psPVRSRVData->psDeviceNodeList;
-       while (psThis)
+       if (psDeviceNode->pfnPDumpInitDevice)
        {
-               if (psThis->pfnPDumpInitDevice)
-               {
-                       /* Reset pdump according to connected device */
-                       psThis->pfnPDumpInitDevice(psThis);
-               }
-               psThis = psThis->psNext;
+               /* Reset pdump according to connected device */
+               psDeviceNode->pfnPDumpInitDevice(psDeviceNode);
        }
 }
 
@@ -5187,7 +5149,7 @@ void PDumpConnectionNotify(void)
  * Description    : Called by the connection_server to tell PDump core that
  *                  the PDump capture and control client has disconnected
 ******************************************************************************/
-void PDumpDisconnectionNotify(void)
+void PDumpDisconnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        PVRSRV_ERROR eErr;
 
@@ -5199,7 +5161,7 @@ void PDumpDisconnectionNotify(void)
                 * not get a chance to reset the capture parameters.
                 * Will set module state back to READY.
                 */
-               eErr = PDumpSetDefaultCaptureParamsKM(PDUMP_CAPMODE_UNSET,
+               eErr = PDumpSetDefaultCaptureParamsKM(NULL, psDeviceNode, PDUMP_CAPMODE_UNSET,
                                                      PDUMP_FRAME_UNSET, PDUMP_FRAME_UNSET, 0, 0);
                PVR_LOG_IF_ERROR(eErr, "PDumpSetDefaultCaptureParamsKM");
        }
@@ -5291,7 +5253,8 @@ PVRSRV_ERROR PDumpInternalValCondStr(IMG_CHAR            **ppszPDumpCond,
  * Description    : Create a PDUMP string which represents IF command
                                        with condition.
 ******************************************************************************/
-PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpIfKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -5305,7 +5268,7 @@ PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5320,7 +5283,8 @@ PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
  * Description    : Create a PDUMP string which represents ELSE command
                                        with condition.
 ******************************************************************************/
-PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpElseKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                         IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -5334,7 +5298,7 @@ PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5350,7 +5314,8 @@ PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
  * Description    : Create a PDUMP string which represents FI command
                                        with condition.
 ******************************************************************************/
-PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpFiKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -5364,7 +5329,7 @@ PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5380,7 +5345,8 @@ PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags)
  * Description    : Create a PDUMP string which represents SDO command
                                        with condition.
 ******************************************************************************/
-PVRSRV_ERROR PDumpStartDoLoopKM(IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpStartDoLoopKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -5394,7 +5360,7 @@ PVRSRV_ERROR PDumpStartDoLoopKM(IMG_UINT32 ui32PDumpFlags)
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5410,7 +5376,9 @@ PVRSRV_ERROR PDumpStartDoLoopKM(IMG_UINT32 ui32PDumpFlags)
  * Description    : Create a PDUMP string which represents DOW command
                                        with condition.
 ******************************************************************************/
-PVRSRV_ERROR PDumpEndDoWhileLoopKM(IMG_CHAR *pszPDumpWhileCond, IMG_UINT32 ui32PDumpFlags)
+PVRSRV_ERROR PDumpEndDoWhileLoopKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   IMG_CHAR *pszPDumpWhileCond,
+                                   IMG_UINT32 ui32PDumpFlags)
 {
        PVRSRV_ERROR eErr;
        PDUMP_GET_SCRIPT_STRING()
@@ -5424,7 +5392,7 @@ PVRSRV_ERROR PDumpEndDoWhileLoopKM(IMG_CHAR *pszPDumpWhileCond, IMG_UINT32 ui32P
        }
 
        PDUMP_LOCK(ui32PDumpFlags);
-       PDumpWriteScript(hScript, ui32PDumpFlags);
+       PDumpWriteScript(psDeviceNode, hScript, ui32PDumpFlags);
        PDUMP_UNLOCK(ui32PDumpFlags);
 
        PDUMP_RELEASE_SCRIPT_STRING();
@@ -5447,6 +5415,7 @@ static void PDumpAssertWriteLockHeld(void)
        PVR_ASSERT(OSLockIsLocked(g_hPDumpWriteLock));
 }
 
+#if defined(PDUMP_TRACE_STATE) || defined(PVR_TESTING_UTILS)
 void PDumpCommonDumpState(void)
 {
        PVR_LOG(("--- PDUMP COMMON: g_PDumpScript.sCh.*.hTL (In, Mn, De, Bk) ( %p, %p, %p, %p )",
@@ -5500,11 +5469,14 @@ void PDumpCommonDumpState(void)
                        g_PDumpCtrl.ui32DefaultCapMode, g_PDumpCtrl.ui32CurrentFrame));
        PVR_LOG(("--- PDUMP COMMON: sCaptureRange.ui32Start( %x ) sCaptureRange.ui32End( %x ) sCaptureRange.ui32Interval( %u )",
                        g_PDumpCtrl.sCaptureRange.ui32Start, g_PDumpCtrl.sCaptureRange.ui32End, g_PDumpCtrl.sCaptureRange.ui32Interval));
-       PVR_LOG(("--- PDUMP COMMON: IsInCaptureRange( %s ) InPowerTransition( %d )",
-                       CHECK_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE) ? "yes" : "no", PDumpCtrlInPowerTransition()));
+       PVR_LOG(("--- PDUMP COMMON: IsInCaptureRange( %s ) IsInCaptureInterval( %s ) InPowerTransition( %d )",
+                       CHECK_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_RANGE) ? "yes" : "no",
+                       CHECK_PDUMP_CONTROL_FLAG(FLAG_IS_IN_CAPTURE_INTERVAL) ? "yes" : "no",
+                       PDumpCtrlInPowerTransition()));
        PVR_LOG(("--- PDUMP COMMON: sBlockCtrl.ui32BlockLength( %d ), sBlockCtrl.ui32CurrentBlock( %d )",
                        g_PDumpCtrl.sBlockCtrl.ui32BlockLength, g_PDumpCtrl.sBlockCtrl.ui32CurrentBlock));
 }
+#endif /* defined(PDUMP_TRACE_STATE) || defined(PVR_TESTING_UTILS) */
 
 
 PVRSRV_ERROR PDumpRegisterConnection(void *hSyncPrivData,
index 8297a56..2155bcb 100644 (file)
@@ -106,14 +106,18 @@ typedef struct PHYS_HEAP_PROPERTIES_TAG
        IMG_BOOL bUserModeAlloc;
 } PHYS_HEAP_PROPERTIES;
 
+/* NOTE: Table entries and order must match enum PVRSRV_PHYS_HEAP to ensure
+ * correct operation of PhysHeapCreatePMR().
+ */
 static PHYS_HEAP_PROPERTIES gasHeapProperties[PVRSRV_PHYS_HEAP_LAST] =
 {
        /* eFallbackHeap,               bPVRLayerAcquire, bUserModeAlloc */
-    {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_TRUE  }, /* GPU_LOCAL */
-    {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_TRUE  }, /* CPU_LOCAL */
+    {  PVRSRV_PHYS_HEAP_DEFAULT,    IMG_TRUE,         IMG_TRUE  }, /* DEFAULT */
+    {  PVRSRV_PHYS_HEAP_DEFAULT,    IMG_TRUE,         IMG_TRUE  }, /* GPU_LOCAL */
+    {  PVRSRV_PHYS_HEAP_DEFAULT,    IMG_TRUE,         IMG_TRUE  }, /* CPU_LOCAL */
+    {  PVRSRV_PHYS_HEAP_DEFAULT,    IMG_TRUE,         IMG_TRUE  }, /* GPU_PRIVATE */
     {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_FALSE,        IMG_FALSE }, /* FW_MAIN */
     {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_FALSE }, /* EXTERNAL */
-    {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_FALSE }, /* GPU_PRIVATE */
     {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_FALSE }, /* GPU_COHERENT */
     {  PVRSRV_PHYS_HEAP_GPU_LOCAL,  IMG_TRUE,         IMG_TRUE  }, /* GPU_SECURE */
     {  PVRSRV_PHYS_HEAP_FW_MAIN,    IMG_FALSE,        IMG_FALSE }, /* FW_CONFIG */
@@ -129,12 +133,150 @@ static PHYS_HEAP_PROPERTIES gasHeapProperties[PVRSRV_PHYS_HEAP_LAST] =
     {  PVRSRV_PHYS_HEAP_FW_PREMAP7, IMG_FALSE,        IMG_FALSE }, /* FW_PREMAP7 */
 };
 
+static_assert((ARRAY_SIZE(gasHeapProperties) == PVRSRV_PHYS_HEAP_LAST),
+       "Size or order of gasHeapProperties entries incorrect for PVRSRV_PHYS_HEAP enum");
+
+void PVRSRVGetDevicePhysHeapCount(PVRSRV_DEVICE_NODE *psDevNode,
+                                                                 IMG_UINT32 *pui32PhysHeapCount)
+{
+       *pui32PhysHeapCount = psDevNode->ui32UserAllocHeapCount;
+}
+
+static IMG_UINT32 PhysHeapOSGetPageShift(void)
+{
+       return (IMG_UINT32)OSGetPageShift();
+}
+
 static PHEAP_IMPL_FUNCS _sPHEAPImplFuncs =
 {
        .pfnDestroyData = NULL,
+       .pfnGetPMRFactoryMemStats = PhysmemGetOSRamMemStats,
        .pfnCreatePMR = PhysmemNewOSRamBackedPMR,
+       .pfnPagesAlloc = &OSPhyContigPagesAlloc,
+       .pfnPagesFree = &OSPhyContigPagesFree,
+       .pfnPagesMap = &OSPhyContigPagesMap,
+       .pfnPagesUnMap = &OSPhyContigPagesUnmap,
+       .pfnPagesClean = &OSPhyContigPagesClean,
+       .pfnGetPageShift = &PhysHeapOSGetPageShift,
 };
 
+/*************************************************************************/ /*!
+@Function       _PhysHeapDebugRequest
+@Description    This function is used to output debug information for a given
+                device's PhysHeaps.
+@Input          pfnDbgRequestHandle Data required by this function that is
+                                    passed through the RegisterDeviceDbgRequestNotify
+                                    function.
+@Input          ui32VerbLevel       The maximum verbosity of the debug request.
+@Input          pfnDumpDebugPrintf  The specified print function that should be
+                                    used to dump any debug information
+                                    (see PVRSRVDebugRequest).
+@Input          pvDumpDebugFile     Optional file identifier to be passed to
+                                    the print function if required.
+@Return         void
+*/ /**************************************************************************/
+static void _PhysHeapDebugRequest(PVRSRV_DBGREQ_HANDLE pfnDbgRequestHandle,
+                                  IMG_UINT32 ui32VerbLevel,
+                                  DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                  void *pvDumpDebugFile)
+{
+       static const IMG_CHAR *const pszTypeStrings[] = {
+               "UNKNOWN",
+               "UMA",
+               "LMA",
+               "DMA",
+#if defined(SUPPORT_WRAP_EXTMEMOBJECT)
+               "WRAP"
+#endif
+       };
+
+       PPVRSRV_DEVICE_NODE psDeviceNode = (PPVRSRV_DEVICE_NODE)pfnDbgRequestHandle;
+       PHYS_HEAP *psPhysHeap = NULL;
+       IMG_UINT64 ui64TotalSize;
+       IMG_UINT64 ui64FreeSize;
+       IMG_UINT32 i;
+
+       PVR_LOG_RETURN_VOID_IF_FALSE(psDeviceNode != NULL,
+                                    "Phys Heap debug request failed. psDeviceNode was NULL");
+
+       PVR_DUMPDEBUG_LOG("------[ Device ID: %d - Phys Heaps ]------",
+                         psDeviceNode->sDevId.i32OsDeviceID);
+
+       for (i = 0; i < psDeviceNode->ui32RegisteredPhysHeaps; i++)
+       {
+               psPhysHeap = psDeviceNode->papsRegisteredPhysHeaps[i];
+
+               if (psPhysHeap->eType >= ARRAY_SIZE(pszTypeStrings))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "PhysHeap at address %p eType is not a PHYS_HEAP_TYPE",
+                                psPhysHeap));
+                       break;
+               }
+
+               psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats(psPhysHeap->pvImplData,
+                                                                 &ui64TotalSize,
+                                                                 &ui64FreeSize);
+
+               if (psPhysHeap->eType == PHYS_HEAP_TYPE_LMA)
+               {
+                       IMG_CPU_PHYADDR sCPUPAddr;
+                       IMG_DEV_PHYADDR sGPUPAddr;
+                       PVRSRV_ERROR eError;
+
+                       PVR_ASSERT(psPhysHeap->psImplFuncs->pfnGetCPUPAddr != NULL);
+                       PVR_ASSERT(psPhysHeap->psImplFuncs->pfnGetDevPAddr != NULL);
+
+                       eError = psPhysHeap->psImplFuncs->pfnGetCPUPAddr(psPhysHeap->pvImplData,
+                                                                        &sCPUPAddr);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_LOG_ERROR(eError, "pfnGetCPUPAddr");
+                               sCPUPAddr.uiAddr = IMG_CAST_TO_CPUPHYADDR_UINT(IMG_UINT64_MAX);
+                       }
+
+                       eError = psPhysHeap->psImplFuncs->pfnGetDevPAddr(psPhysHeap->pvImplData,
+                                                                        &sGPUPAddr);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_LOG_ERROR(eError, "pfnGetDevPAddr");
+                               sGPUPAddr.uiAddr = IMG_UINT64_MAX;
+                       }
+
+                       PVR_DUMPDEBUG_LOG("0x%p -> Name: %s, Type: %s, "
+
+                                         "CPU PA Base: " CPUPHYADDR_UINT_FMTSPEC", "
+                                         "GPU PA Base: 0x%08"IMG_UINT64_FMTSPECx", "
+                                         "Usage Flags: 0x%08x, Refs: %d, "
+                                         "Free Size: %"IMG_UINT64_FMTSPEC", "
+                                         "Total Size: %"IMG_UINT64_FMTSPEC,
+                                         psPhysHeap,
+                                         psPhysHeap->pszPDumpMemspaceName,
+                                         pszTypeStrings[psPhysHeap->eType],
+                                         CPUPHYADDR_FMTARG(sCPUPAddr.uiAddr),
+                                         sGPUPAddr.uiAddr,
+                                         psPhysHeap->ui32UsageFlags,
+                                         psPhysHeap->ui32RefCount,
+                                         ui64FreeSize,
+                                         ui64TotalSize);
+               }
+               else
+               {
+                       PVR_DUMPDEBUG_LOG("0x%p -> Name: %s, Type: %s, "
+                                         "Usage Flags: 0x%08x, Refs: %d, "
+                                         "Free Size: %"IMG_UINT64_FMTSPEC", "
+                                         "Total Size: %"IMG_UINT64_FMTSPEC,
+                                         psPhysHeap,
+                                         psPhysHeap->pszPDumpMemspaceName,
+                                         pszTypeStrings[psPhysHeap->eType],
+                                         psPhysHeap->ui32UsageFlags,
+                                         psPhysHeap->ui32RefCount,
+                                         ui64FreeSize,
+                                         ui64TotalSize);
+               }
+       }
+}
+
 PVRSRV_ERROR
 PhysHeapCreateHeapFromConfig(PVRSRV_DEVICE_NODE *psDevNode,
                                                         PHYS_HEAP_CONFIG *psConfig,
@@ -167,27 +309,44 @@ PhysHeapCreateHeapFromConfig(PVRSRV_DEVICE_NODE *psDevNode,
 }
 
 PVRSRV_ERROR
-PhysHeapCreateHeapsFromConfigs(PPVRSRV_DEVICE_NODE psDevNode,
-                                       PHYS_HEAP_CONFIG *pasConfigs,
-                                       IMG_UINT32 ui32NumConfigs,
-                                       PHYS_HEAP **papsPhysHeaps,
-                                       IMG_UINT32 *pui32NumHeaps)
+PhysHeapCreateDeviceHeapsFromConfigs(PPVRSRV_DEVICE_NODE psDevNode,
+                                     PHYS_HEAP_CONFIG *pasConfigs,
+                                     IMG_UINT32 ui32NumConfigs)
 {
        IMG_UINT32 i;
        PVRSRV_ERROR eError;
 
-       *pui32NumHeaps = 0;
+       /* Register the physical memory heaps */
+       psDevNode->papsRegisteredPhysHeaps =
+               OSAllocZMem(sizeof(*psDevNode->papsRegisteredPhysHeaps) * ui32NumConfigs);
+       PVR_LOG_RETURN_IF_NOMEM(psDevNode->papsRegisteredPhysHeaps, "OSAllocZMem");
+
+       psDevNode->ui32RegisteredPhysHeaps = 0;
 
        for (i = 0; i < ui32NumConfigs; i++)
        {
                eError = PhysHeapCreateHeapFromConfig(psDevNode,
                                                                                          pasConfigs + i,
-                                                                                         papsPhysHeaps + i);
+                                                                                         psDevNode->papsRegisteredPhysHeaps + i);
                PVR_LOG_RETURN_IF_ERROR(eError, "PhysmemCreateHeap");
 
-               (*pui32NumHeaps)++;
+               psDevNode->ui32RegisteredPhysHeaps++;
        }
 
+#if defined(SUPPORT_PHYSMEM_TEST)
+       /* For a temporary device node there will never be a debug dump
+        * request targeting it */
+       if (psDevNode->hDebugTable != NULL)
+#endif
+       {
+               eError = PVRSRVRegisterDeviceDbgRequestNotify(&psDevNode->hPhysHeapDbgReqNotify,
+                                                             psDevNode,
+                                                             _PhysHeapDebugRequest,
+                                                             DEBUG_REQUEST_SYS,
+                                                             psDevNode);
+
+               PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVRegisterDeviceDbgRequestNotify");
+       }
        return PVRSRV_OK;
 }
 
@@ -232,6 +391,24 @@ PVRSRV_ERROR PhysHeapCreate(PPVRSRV_DEVICE_NODE psDevNode,
        PVR_DPF_RETURN_RC1(PVRSRV_OK, *ppsPhysHeap);
 }
 
+void PhysHeapDestroyDeviceHeaps(PPVRSRV_DEVICE_NODE psDevNode)
+{
+       IMG_UINT32 i;
+
+       if (psDevNode->hPhysHeapDbgReqNotify)
+       {
+               PVRSRVUnregisterDeviceDbgRequestNotify(psDevNode->hPhysHeapDbgReqNotify);
+       }
+
+       /* Unregister heaps */
+       for (i = 0; i < psDevNode->ui32RegisteredPhysHeaps; i++)
+       {
+               PhysHeapDestroy(psDevNode->papsRegisteredPhysHeaps[i]);
+       }
+
+       OSFreeMem(psDevNode->papsRegisteredPhysHeaps);
+}
+
 void PhysHeapDestroy(PHYS_HEAP *psPhysHeap)
 {
        PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
@@ -280,17 +457,26 @@ PVRSRV_ERROR PhysHeapAcquire(PHYS_HEAP *psPhysHeap)
 }
 
 PVRSRV_ERROR PhysHeapAcquireByUsage(PHYS_HEAP_USAGE_FLAGS ui32UsageFlag,
+                                                                       PPVRSRV_DEVICE_NODE psDevNode,
                                                                        PHYS_HEAP **ppsPhysHeap)
 {
        PHYS_HEAP *psNode = g_psPhysHeapList;
        PVRSRV_ERROR eError = PVRSRV_OK;
 
+       PVR_LOG_RETURN_IF_INVALID_PARAM(ui32UsageFlag != 0, "ui32UsageFlag");
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psDevNode != NULL, "psDevNode");
+
        PVR_DPF_ENTERED1(ui32UsageFlag);
 
        OSLockAcquire(g_hPhysHeapLock);
 
        while (psNode)
        {
+               if (psNode->psDevNode != psDevNode)
+               {
+                       psNode = psNode->psNext;
+                       continue;
+               }
                if (BITMASK_ANY(psNode->ui32UsageFlags, ui32UsageFlag))
                {
                        break;
@@ -321,6 +507,11 @@ static PHYS_HEAP * _PhysHeapFindHeap(PVRSRV_PHYS_HEAP ePhysHeap,
        PHYS_HEAP *psPhysHeapNode = g_psPhysHeapList;
        PVRSRV_PHYS_HEAP eFallback;
 
+       if (ePhysHeap == PVRSRV_PHYS_HEAP_DEFAULT)
+       {
+               ePhysHeap = psDevNode->psDevConfig->eDefaultHeap;
+       }
+
        while (psPhysHeapNode)
        {
                if ((psPhysHeapNode->psDevNode == psDevNode) &&
@@ -351,6 +542,7 @@ PVRSRV_ERROR PhysHeapAcquireByDevPhysHeap(PVRSRV_PHYS_HEAP eDevPhysHeap,
        PHYS_HEAP *psPhysHeap;
        PVRSRV_ERROR eError = PVRSRV_OK;
 
+       PVR_LOG_RETURN_IF_INVALID_PARAM(eDevPhysHeap != PVRSRV_PHYS_HEAP_DEFAULT, "eDevPhysHeap");
        PVR_LOG_RETURN_IF_INVALID_PARAM(eDevPhysHeap < PVRSRV_PHYS_HEAP_LAST, "eDevPhysHeap");
        PVR_LOG_RETURN_IF_INVALID_PARAM(psDevNode != NULL, "psDevNode");
 
@@ -406,6 +598,24 @@ PHYS_HEAP_USAGE_FLAGS PhysHeapGetFlags(PHYS_HEAP *psPhysHeap)
        return psPhysHeap->ui32UsageFlags;
 }
 
+IMG_BOOL PhysHeapValidateDefaultHeapExists(PPVRSRV_DEVICE_NODE psDevNode)
+{
+       PHYS_HEAP *psDefaultHeap;
+       IMG_BOOL bDefaultHeapFound;
+       PhysHeapAcquireByUsage(1<<(psDevNode->psDevConfig->eDefaultHeap), psDevNode, &psDefaultHeap);
+       if (psDefaultHeap == NULL)
+       {
+               bDefaultHeapFound = IMG_FALSE;
+       }
+       else
+       {
+               PhysHeapRelease(psDefaultHeap);
+               bDefaultHeapFound = IMG_TRUE;
+       }
+       return bDefaultHeapFound;
+}
+
+
 /*
  * This function will set the psDevPAddr to whatever the system layer
  * has set it for the referenced region.
@@ -461,6 +671,120 @@ PVRSRV_ERROR PhysHeapGetSize(PHYS_HEAP *psPhysHeap,
        return eResult;
 }
 
+PVRSRV_ERROR
+PhysHeapGetMemInfo(PVRSRV_DEVICE_NODE *psDevNode,
+              IMG_UINT32 ui32PhysHeapCount,
+                         PVRSRV_PHYS_HEAP *paePhysHeapID,
+                         PHYS_HEAP_MEM_STATS_PTR paPhysHeapMemStats)
+{
+       IMG_UINT32 i = 0;
+       PHYS_HEAP *psPhysHeap;
+
+       PVR_ASSERT(ui32PhysHeapCount <= PVRSRV_PHYS_HEAP_LAST);
+
+       for (i = 0; i < ui32PhysHeapCount; i++)
+       {
+               if (paePhysHeapID[i] >= PVRSRV_PHYS_HEAP_LAST)
+               {
+                       return PVRSRV_ERROR_PHYSHEAP_ID_INVALID;
+               }
+
+               if (paePhysHeapID[i] == PVRSRV_PHYS_HEAP_DEFAULT)
+               {
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+
+               psPhysHeap = _PhysHeapFindHeap(paePhysHeapID[i], psDevNode);
+
+               paPhysHeapMemStats[i].ui32PhysHeapFlags = 0;
+
+               if (psPhysHeap && PhysHeapUserModeAlloc(paePhysHeapID[i])
+                               && psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats)
+               {
+                       psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats(psPhysHeap->pvImplData,
+                                       &paPhysHeapMemStats[i].ui64TotalSize,
+                                       &paPhysHeapMemStats[i].ui64FreeSize);
+                       paPhysHeapMemStats[i].ui32PhysHeapFlags |= PhysHeapGetType(psPhysHeap);
+
+                       if (paePhysHeapID[i] == psDevNode->psDevConfig->eDefaultHeap)
+                       {
+                               paPhysHeapMemStats[i].ui32PhysHeapFlags |= PVRSRV_PHYS_HEAP_FLAGS_IS_DEFAULT;
+                       }
+               }
+               else
+               {
+                       paPhysHeapMemStats[i].ui64TotalSize = 0;
+                       paPhysHeapMemStats[i].ui64FreeSize = 0;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PhysHeapGetMemInfoPkd(PVRSRV_DEVICE_NODE *psDevNode,
+              IMG_UINT32 ui32PhysHeapCount,
+                         PVRSRV_PHYS_HEAP *paePhysHeapID,
+                         PHYS_HEAP_MEM_STATS_PKD_PTR paPhysHeapMemStats)
+{
+       IMG_UINT32 i = 0;
+       PHYS_HEAP *psPhysHeap;
+
+       PVR_ASSERT(ui32PhysHeapCount <= PVRSRV_PHYS_HEAP_LAST);
+
+       for (i = 0; i < ui32PhysHeapCount; i++)
+       {
+               if (paePhysHeapID[i] >= PVRSRV_PHYS_HEAP_LAST)
+               {
+                       return PVRSRV_ERROR_PHYSHEAP_ID_INVALID;
+               }
+
+               if (paePhysHeapID[i] == PVRSRV_PHYS_HEAP_DEFAULT)
+               {
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+
+               psPhysHeap = _PhysHeapFindHeap(paePhysHeapID[i], psDevNode);
+
+               paPhysHeapMemStats[i].ui32PhysHeapFlags = 0;
+
+               if (psPhysHeap && PhysHeapUserModeAlloc(paePhysHeapID[i])
+                               && psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats)
+               {
+                       psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats(psPhysHeap->pvImplData,
+                                       &paPhysHeapMemStats[i].ui64TotalSize,
+                                       &paPhysHeapMemStats[i].ui64FreeSize);
+                       paPhysHeapMemStats[i].ui32PhysHeapFlags |= PhysHeapGetType(psPhysHeap);
+
+                       if (paePhysHeapID[i] == psDevNode->psDevConfig->eDefaultHeap)
+                       {
+                               paPhysHeapMemStats[i].ui32PhysHeapFlags |= PVRSRV_PHYS_HEAP_FLAGS_IS_DEFAULT;
+                       }
+               }
+               else
+               {
+                       paPhysHeapMemStats[i].ui64TotalSize = 0;
+                       paPhysHeapMemStats[i].ui64FreeSize = 0;
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+void PhysheapGetPhysMemUsage(PHYS_HEAP *psPhysHeap, IMG_UINT64 *pui64TotalSize, IMG_UINT64 *pui64FreeSize)
+{
+       if (psPhysHeap && psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats)
+       {
+               psPhysHeap->psImplFuncs->pfnGetPMRFactoryMemStats(psPhysHeap->pvImplData,
+                               pui64TotalSize,
+                               pui64FreeSize);
+       }
+       else
+       {
+               *pui64TotalSize = *pui64FreeSize = 0;
+       }
+}
+
 void PhysHeapCpuPAddrToDevPAddr(PHYS_HEAP *psPhysHeap,
                                                                IMG_UINT32 ui32NumOfAddr,
                                                                IMG_DEV_PHYADDR *psDevPAddr,
@@ -531,13 +855,11 @@ PVRSRV_ERROR PhysHeapInit(void)
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR PhysHeapDeinit(void)
+void PhysHeapDeinit(void)
 {
        PVR_ASSERT(g_psPhysHeapList == NULL);
 
        OSLockDestroy(g_hPhysHeapLock);
-
-       return PVRSRV_OK;
 }
 
 PPVRSRV_DEVICE_NODE PhysHeapDeviceNode(PHYS_HEAP *psPhysHeap)
@@ -560,3 +882,303 @@ IMG_BOOL PhysHeapUserModeAlloc(PVRSRV_PHYS_HEAP ePhysHeap)
 
        return gasHeapProperties[ePhysHeap].bUserModeAlloc;
 }
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+/*************************************************************************/ /*!
+@Function       CreateGpuVirtValArenas
+@Description    Create virtualization validation arenas
+@Input          psDeviceNode The device node
+@Return         PVRSRV_ERROR PVRSRV_OK on success
+*/ /**************************************************************************/
+static PVRSRV_ERROR CreateGpuVirtValArenas(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       /* aui64OSidMin and aui64OSidMax are what we program into HW registers.
+          The values are different from base/size of arenas. */
+       IMG_UINT64 aui64OSidMin[GPUVIRT_VALIDATION_NUM_REGIONS][GPUVIRT_VALIDATION_NUM_OS];
+       IMG_UINT64 aui64OSidMax[GPUVIRT_VALIDATION_NUM_REGIONS][GPUVIRT_VALIDATION_NUM_OS];
+       PHYS_HEAP_CONFIG *psGPULocalHeap = FindPhysHeapConfig(psDeviceNode->psDevConfig, PHYS_HEAP_USAGE_GPU_LOCAL);
+       PHYS_HEAP_CONFIG *psDisplayHeap = FindPhysHeapConfig(psDeviceNode->psDevConfig, PHYS_HEAP_USAGE_DISPLAY);
+       IMG_UINT64 uBase;
+       IMG_UINT64 uSize;
+       IMG_UINT64 uBaseShared;
+       IMG_UINT64 uSizeShared;
+       IMG_UINT64 uSizeSharedReg;
+       IMG_UINT32 i;
+
+       /* Shared region is fixed size, the remaining space is divided amongst OSes */
+       uSizeShared = PVR_ALIGN(GPUVIRT_SIZEOF_SHARED, (IMG_DEVMEM_SIZE_T)OSGetPageSize());
+       uSize = psGPULocalHeap->uiSize - uSizeShared;
+       uSize /= GPUVIRT_VALIDATION_NUM_OS;
+       uSize = uSize & ~((IMG_UINT64)OSGetPageSize() - 1ULL); /* Align, round down */
+
+       uBase = psGPULocalHeap->sCardBase.uiAddr;
+       uBaseShared = uBase + uSize * GPUVIRT_VALIDATION_NUM_OS;
+       uSizeShared = psGPULocalHeap->uiSize - (uBaseShared - uBase);
+
+       PVR_LOG(("GPUVIRT_VALIDATION split GPU_LOCAL base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".",
+                        psGPULocalHeap->sCardBase.uiAddr,
+                        psGPULocalHeap->uiSize));
+
+       /* If a display heap config exists, include the display heap in the non-secure regions */
+       if (psDisplayHeap)
+       {
+               /* Only works when DISPLAY heap follows GPU_LOCAL heap. */
+               PVR_LOG(("GPUVIRT_VALIDATION include DISPLAY in shared, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".",
+                                psDisplayHeap->sCardBase.uiAddr,
+                                psDisplayHeap->uiSize));
+
+               uSizeSharedReg = uSizeShared + psDisplayHeap->uiSize;
+       }
+       else
+       {
+               uSizeSharedReg = uSizeShared;
+       }
+
+       PVR_ASSERT(uSize >= GPUVIRT_MIN_SIZE);
+       PVR_ASSERT(uSizeSharedReg >= GPUVIRT_SIZEOF_SHARED);
+
+       for (i = 0; i < GPUVIRT_VALIDATION_NUM_OS; i++)
+       {
+               IMG_CHAR aszOSRAName[RA_MAX_NAME_LENGTH];
+
+               PVR_LOG(("GPUVIRT_VALIDATION create arena OS: %d, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".", i, uBase, uSize));
+
+               OSSNPrintf(aszOSRAName, RA_MAX_NAME_LENGTH, "GPUVIRT_OS%d", i);
+
+               psDeviceNode->psOSidSubArena[i] = RA_Create_With_Span(aszOSRAName,
+                                                                     OSGetPageShift(),
+                                                                     0,
+                                                                     uBase,
+                                                                     uSize);
+               PVR_LOG_RETURN_IF_NOMEM(psDeviceNode->psOSidSubArena[i], "RA_Create_With_Span");
+
+               aui64OSidMin[GPUVIRT_VAL_REGION_SECURE][i] = uBase;
+
+               if (i == 0)
+               {
+                       /* OSid0 has access to all regions */
+                       aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i] = psGPULocalHeap->uiSize - 1ULL;
+               }
+               else
+               {
+                       aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i] = uBase + uSize - 1ULL;
+               }
+
+               /* uSizeSharedReg includes display heap */
+               aui64OSidMin[GPUVIRT_VAL_REGION_SHARED][i] = uBaseShared;
+               aui64OSidMax[GPUVIRT_VAL_REGION_SHARED][i] = uBaseShared + uSizeSharedReg - 1ULL;
+
+               PVR_LOG(("GPUVIRT_VALIDATION HW reg regions %d: min[0]: 0x%" IMG_UINT64_FMTSPECX ", max[0]: 0x%" IMG_UINT64_FMTSPECX ", min[1]: 0x%" IMG_UINT64_FMTSPECX ", max[1]: 0x%" IMG_UINT64_FMTSPECX ",",
+                                i,
+                                aui64OSidMin[GPUVIRT_VAL_REGION_SECURE][i],
+                                aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i],
+                                aui64OSidMin[GPUVIRT_VAL_REGION_SHARED][i],
+                                aui64OSidMax[GPUVIRT_VAL_REGION_SHARED][i]));
+               uBase += uSize;
+       }
+
+       PVR_LOG(("GPUVIRT_VALIDATION create arena Shared, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".", uBaseShared, uSizeShared));
+
+       PVR_ASSERT(uSizeShared >= GPUVIRT_SIZEOF_SHARED);
+
+       /* uSizeShared does not include  display heap */
+       psDeviceNode->psOSSharedArena = RA_Create_With_Span("GPUVIRT_SHARED",
+                                                           OSGetPageShift(),
+                                                           0,
+                                                           uBaseShared,
+                                                           uSizeShared);
+       PVR_LOG_RETURN_IF_NOMEM(psDeviceNode->psOSSharedArena, "RA_Create_With_Span");
+
+       if (psDeviceNode->psDevConfig->pfnSysDevVirtInit != NULL)
+       {
+               psDeviceNode->psDevConfig->pfnSysDevVirtInit(aui64OSidMin, aui64OSidMax);
+       }
+
+       return PVRSRV_OK;
+}
+
+/*
+ * Counter-part to CreateGpuVirtValArenas.
+ */
+static void DestroyGpuVirtValArenas(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       IMG_UINT32      uiCounter = 0;
+
+       /*
+        * NOTE: We overload psOSidSubArena[0] into the psLocalMemArena so we must
+        * not free it here as it gets cleared later.
+        */
+       for (uiCounter = 1; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
+       {
+               if (psDeviceNode->psOSidSubArena[uiCounter] == NULL)
+               {
+                       continue;
+               }
+               RA_Delete(psDeviceNode->psOSidSubArena[uiCounter]);
+       }
+
+       if (psDeviceNode->psOSSharedArena != NULL)
+       {
+               RA_Delete(psDeviceNode->psOSSharedArena);
+       }
+}
+#endif
+
+PVRSRV_ERROR PhysHeapMMUPxSetup(PPVRSRV_DEVICE_NODE psDeviceNode)
+{
+       PHYS_HEAP_TYPE eHeapType;
+       PVRSRV_ERROR eError;
+
+       eError = PhysHeapAcquireByDevPhysHeap(psDeviceNode->psDevConfig->eDefaultHeap,
+                                             psDeviceNode, &psDeviceNode->psMMUPhysHeap);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquireByDevPhysHeap", ErrorDeinit);
+
+       eHeapType = PhysHeapGetType(psDeviceNode->psMMUPhysHeap);
+
+       if (eHeapType == PHYS_HEAP_TYPE_UMA)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: GPU physical heap uses OS System memory (UMA)", __func__));
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+               PVR_DPF((PVR_DBG_ERROR, "%s: Virtualisation Validation builds are currently only"
+                                                                " supported on systems with local memory (LMA).", __func__));
+               eError = PVRSRV_ERROR_NOT_SUPPORTED;
+               goto ErrorDeinit;
+#endif
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: GPU physical heap uses local memory managed by the driver (LMA)", __func__));
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+               eError = CreateGpuVirtValArenas(psDeviceNode);
+               PVR_LOG_GOTO_IF_ERROR(eError, "CreateGpuVirtValArenas", ErrorDeinit);
+#endif
+       }
+
+       return PVRSRV_OK;
+ErrorDeinit:
+       return eError;
+}
+
+void PhysHeapMMUPxDeInit(PPVRSRV_DEVICE_NODE psDeviceNode)
+{
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       /* Remove local LMA subarenas */
+       DestroyGpuVirtValArenas(psDeviceNode);
+#endif /* defined(SUPPORT_GPUVIRT_VALIDATION) */
+
+       if (psDeviceNode->psMMUPhysHeap != NULL)
+       {
+               PhysHeapRelease(psDeviceNode->psMMUPhysHeap);
+               psDeviceNode->psMMUPhysHeap = NULL;
+       }
+}
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+PVRSRV_ERROR PhysHeapPagesAllocGPV(PHYS_HEAP *psPhysHeap, size_t uiSize,
+                                   PG_HANDLE *psMemHandle,
+                                   IMG_DEV_PHYADDR *psDevPAddr,
+                                   IMG_UINT32 ui32OSid, IMG_PID uiPid)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+       PVRSRV_ERROR eResult = PVRSRV_ERROR_NOT_IMPLEMENTED;
+
+       if (psImplFuncs->pfnPagesAllocGPV != NULL)
+       {
+               eResult = psImplFuncs->pfnPagesAllocGPV(psPhysHeap,
+                                                       uiSize, psMemHandle, psDevPAddr, ui32OSid, uiPid);
+       }
+
+       return eResult;
+}
+#endif
+
+PVRSRV_ERROR PhysHeapPagesAlloc(PHYS_HEAP *psPhysHeap, size_t uiSize,
+                                                               PG_HANDLE *psMemHandle,
+                                                               IMG_DEV_PHYADDR *psDevPAddr,
+                                                               IMG_PID uiPid)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+       PVRSRV_ERROR eResult = PVRSRV_ERROR_NOT_IMPLEMENTED;
+
+       if (psImplFuncs->pfnPagesAlloc != NULL)
+       {
+               eResult = psImplFuncs->pfnPagesAlloc(psPhysHeap,
+                                                      uiSize, psMemHandle, psDevPAddr, uiPid);
+       }
+
+       return eResult;
+}
+
+void PhysHeapPagesFree(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+
+       PVR_ASSERT(psImplFuncs->pfnPagesFree != NULL);
+
+       if (psImplFuncs->pfnPagesFree != NULL)
+       {
+               psImplFuncs->pfnPagesFree(psPhysHeap,
+                                         psMemHandle);
+       }
+}
+
+PVRSRV_ERROR PhysHeapPagesMap(PHYS_HEAP *psPhysHeap, PG_HANDLE *pshMemHandle, size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+                                                         void **pvPtr)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+       PVRSRV_ERROR eResult = PVRSRV_ERROR_NOT_IMPLEMENTED;
+
+       if (psImplFuncs->pfnPagesMap != NULL)
+       {
+               eResult = psImplFuncs->pfnPagesMap(psPhysHeap,
+                                                  pshMemHandle, uiSize, psDevPAddr, pvPtr);
+       }
+
+       return eResult;
+}
+
+void PhysHeapPagesUnMap(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle, void *pvPtr)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+
+       PVR_ASSERT(psImplFuncs->pfnPagesUnMap != NULL);
+
+       if (psImplFuncs->pfnPagesUnMap != NULL)
+       {
+               psImplFuncs->pfnPagesUnMap(psPhysHeap,
+                                          psMemHandle, pvPtr);
+       }
+}
+
+PVRSRV_ERROR PhysHeapPagesClean(PHYS_HEAP *psPhysHeap, PG_HANDLE *pshMemHandle,
+                                                         IMG_UINT32 uiOffset,
+                                                         IMG_UINT32 uiLength)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+       PVRSRV_ERROR eResult = PVRSRV_ERROR_NOT_IMPLEMENTED;
+
+       if (psImplFuncs->pfnPagesClean != NULL)
+       {
+               eResult = psImplFuncs->pfnPagesClean(psPhysHeap,
+                                                    pshMemHandle, uiOffset, uiLength);
+       }
+
+       return eResult;
+}
+
+IMG_UINT32 PhysHeapGetPageShift(PHYS_HEAP *psPhysHeap)
+{
+       PHEAP_IMPL_FUNCS *psImplFuncs = psPhysHeap->psImplFuncs;
+       IMG_UINT32 ui32PageShift = 0;
+
+       PVR_ASSERT(psImplFuncs->pfnGetPageShift != NULL);
+
+       if (psImplFuncs->pfnGetPageShift != NULL)
+       {
+               ui32PageShift = psImplFuncs->pfnGetPageShift();
+       }
+
+       return ui32PageShift;
+}
index 277f804..34c174d 100644 (file)
@@ -94,6 +94,7 @@ PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE       *psDevNode,
        PDUMP_FILEOFFSET_T uiOffsetOut;
        IMG_UINT32 ui32PageSize;
        IMG_UINT32 ui32PDumpMemSize = ui32MemSize;
+       PVRSRV_ERROR ePDumpError;
 #endif
        PG_HANDLE *psMemHandle;
        IMG_UINT64 uiMask;
@@ -108,11 +109,11 @@ PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE   *psDevNode,
 #endif
 
        /* Allocate the pages */
-       eError = psDevNode->sDevMMUPxSetup.pfnDevPxAlloc(psDevNode,
-                                                        TRUNCATE_64BITS_TO_SIZE_T(ui32MemSize),
-                                                        psMemHandle,
-                                                        &sDevPhysAddr_int,
-                                                        uiPid);
+       eError = PhysHeapPagesAlloc(psDevNode->psMMUPhysHeap,
+                                   TRUNCATE_64BITS_TO_SIZE_T(ui32MemSize),
+                                   psMemHandle,
+                                   &sDevPhysAddr_int,
+                                   uiPid);
        PVR_LOG_RETURN_IF_ERROR(eError, "pfnDevPxAlloc:1");
 
        /* Check to see if the page allocator returned pages with our desired
@@ -122,14 +123,14 @@ PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE   *psDevNode,
        if (ui32Log2Align && (sDevPhysAddr_int.uiAddr & uiMask))
        {
                /* use over allocation instead */
-               psDevNode->sDevMMUPxSetup.pfnDevPxFree(psDevNode, psMemHandle);
+               PhysHeapPagesFree(psDevNode->psMMUPhysHeap, psMemHandle);
 
                ui32MemSize += (IMG_UINT32) uiMask;
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxAlloc(psDevNode,
-                                                                TRUNCATE_64BITS_TO_SIZE_T(ui32MemSize),
-                                                                psMemHandle,
-                                                                &sDevPhysAddr_int,
-                                                                uiPid);
+               eError = PhysHeapPagesAlloc(psDevNode->psMMUPhysHeap,
+                                           TRUNCATE_64BITS_TO_SIZE_T(ui32MemSize),
+                                           psMemHandle,
+                                           &sDevPhysAddr_int,
+                                           uiPid);
                PVR_LOG_RETURN_IF_ERROR(eError, "pfnDevPxAlloc:2");
 
                sDevPhysAddr_int.uiAddr += uiMask;
@@ -139,33 +140,35 @@ PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE   *psDevNode,
 
 #if defined(PDUMP)
        ui32PageSize = ui32Log2Align? (1 << ui32Log2Align) : OSGetPageSize();
-       eError = PDumpMalloc(pszDevSpace,
-                                                               pszSymbolicAddress,
-                                                               ui32PDumpMemSize,
-                                                               ui32PageSize,
-                                                               IMG_FALSE,
-                                                               0,
-                                                               phHandlePtr,
-                                                               PDUMP_NONE);
+       eError = PDumpMalloc(psDevNode,
+                            pszDevSpace,
+                            pszSymbolicAddress,
+                            ui32PDumpMemSize,
+                            ui32PageSize,
+                            IMG_FALSE,
+                            0,
+                            phHandlePtr,
+                            PDUMP_NONE);
        if (PVRSRV_OK != eError)
        {
-               PDUMPCOMMENT("Allocating pages failed");
+               PDUMPCOMMENT(psDevNode, "Allocating pages failed");
                *phHandlePtr = NULL;
        }
+       ePDumpError = eError;
 #endif
 
        if (bInitPage)
        {
                /*Map the page to the CPU VA space */
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxMap(psDevNode,
-                                                              psMemHandle,
-                                                              ui32MemSize,
-                                                              &sDevPhysAddr_int,
-                                                              &pvCpuVAddr);
+               eError = PhysHeapPagesMap(psDevNode->psMMUPhysHeap,
+                                         psMemHandle,
+                                         ui32MemSize,
+                                         &sDevPhysAddr_int,
+                                         &pvCpuVAddr);
                if (PVRSRV_OK != eError)
                {
                        PVR_LOG_ERROR(eError, "DevPxMap");
-                       psDevNode->sDevMMUPxSetup.pfnDevPxFree(psDevNode, psMemHandle);
+                       PhysHeapPagesFree(psDevNode->psMMUPhysHeap, psMemHandle);
                        return eError;
                }
 
@@ -173,73 +176,78 @@ PVRSRV_ERROR DevPhysMemAlloc(PVRSRV_DEVICE_NODE   *psDevNode,
                OSDeviceMemSet(pvCpuVAddr, u8Value, ui32MemSize);
 
                /*Map the page to the CPU VA space */
-               eError = psDevNode->sDevMMUPxSetup.pfnDevPxClean(psDevNode,
-                                                                psMemHandle,
-                                                                0,
-                                                                ui32MemSize);
+               eError = PhysHeapPagesClean(psDevNode->psMMUPhysHeap,
+                                           psMemHandle,
+                                           0,
+                                           ui32MemSize);
                if (PVRSRV_OK != eError)
                {
                        PVR_LOG_ERROR(eError, "DevPxClean");
-                       psDevNode->sDevMMUPxSetup.pfnDevPxUnMap(psDevNode, psMemHandle, pvCpuVAddr);
-                       psDevNode->sDevMMUPxSetup.pfnDevPxFree(psDevNode, psMemHandle);
+                       PhysHeapPagesUnMap(psDevNode->psMMUPhysHeap, psMemHandle, pvCpuVAddr);
+                       PhysHeapPagesFree(psDevNode->psMMUPhysHeap, psMemHandle);
                        return eError;
                }
 
 #if defined(PDUMP)
-               /* PDumping of the page contents can be done in two ways
-                * 1. Store the single byte init value to the .prm file
-                *    and load the same value to the entire dummy page buffer
-                *    This method requires lot of LDB's inserted into the out2.txt
-                *
-                * 2. Store the entire contents of the buffer to the .prm file
-                *    and load them back.
-                *    This only needs a single LDB instruction in the .prm file
-                *    and chosen this method
-                *    size of .prm file might go up but that's not huge at least
-                *    for this allocation
-                */
-               /* Write the buffer contents to the prm file */
-               eError = PDumpWriteParameterBlob(pvCpuVAddr,
-                                         ui32PDumpMemSize,
-                                         PDUMP_FLAGS_CONTINUOUS,
-                                         szFilenameOut,
-                                         sizeof(szFilenameOut),
-                                         &uiOffsetOut);
-               if (PVRSRV_OK == eError)
+               if (ePDumpError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
                {
-                       /* Load the buffer back to the allocated memory when playing the pdump */
-                       eError = PDumpPMRLDB(pszDevSpace,
-                                            pszSymbolicAddress,
-                                            0,
-                                            ui32PDumpMemSize,
-                                            szFilenameOut,
-                                            uiOffsetOut,
-                                            PDUMP_FLAGS_CONTINUOUS);
-                       if (PVRSRV_OK != eError)
+                       /* PDumping of the page contents can be done in two ways
+                        * 1. Store the single byte init value to the .prm file
+                        *    and load the same value to the entire dummy page buffer
+                        *    This method requires lot of LDB's inserted into the out2.txt
+                        *
+                        * 2. Store the entire contents of the buffer to the .prm file
+                        *    and load them back.
+                        *    This only needs a single LDB instruction in the .prm file
+                        *    and chosen this method
+                        *    size of .prm file might go up but that's not huge at least
+                        *    for this allocation
+                        */
+                       /* Write the buffer contents to the prm file */
+                       eError = PDumpWriteParameterBlob(psDevNode,
+                                                                                        pvCpuVAddr,
+                                                                                        ui32PDumpMemSize,
+                                                                                        PDUMP_FLAGS_CONTINUOUS,
+                                                                                        szFilenameOut,
+                                                                                        sizeof(szFilenameOut),
+                                                                                        &uiOffsetOut);
+                       if (PVRSRV_OK == eError)
                        {
-                               PDUMP_ERROR(eError, "Failed to write LDB statement to script file");
-                               PVR_LOG_ERROR(eError, "PDumpPMRLDB");
+                               /* Load the buffer back to the allocated memory when playing the pdump */
+                               eError = PDumpPMRLDB(psDevNode,
+                                                                        pszDevSpace,
+                                                                        pszSymbolicAddress,
+                                                                        0,
+                                                                        ui32PDumpMemSize,
+                                                                        szFilenameOut,
+                                                                        uiOffsetOut,
+                                                                        PDUMP_FLAGS_CONTINUOUS);
+                               if (PVRSRV_OK != eError)
+                               {
+                                       PDUMP_ERROR(psDevNode, eError, "Failed to write LDB statement to script file");
+                                       PVR_LOG_ERROR(eError, "PDumpPMRLDB");
+                               }
+                       }
+                       else if (eError != PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
+                       {
+                               PDUMP_ERROR(psDevNode, eError, "Failed to write device allocation to parameter file");
+                               PVR_LOG_ERROR(eError, "PDumpWriteParameterBlob");
+                       }
+                       else
+                       {
+                               /* Else write to parameter file prevented under the flags and
+                                * current state of the driver so skip write to script and error IF.
+                                * This is expected e.g., if not in the capture range.
+                                */
+                               eError = PVRSRV_OK;
                        }
-               }
-               else if (eError != PVRSRV_ERROR_PDUMP_NOT_ALLOWED)
-               {
-                       PDUMP_ERROR(eError, "Failed to write device allocation to parameter file");
-                       PVR_LOG_ERROR(eError, "PDumpWriteParameterBlob");
-               }
-               else
-               {
-                       /* Else write to parameter file prevented under the flags and
-                        * current state of the driver so skip write to script and error IF.
-                        * This is expected e.g., if not in the capture range.
-                        */
-                       eError = PVRSRV_OK;
                }
 #endif
 
                /* Unmap the page */
-               psDevNode->sDevMMUPxSetup.pfnDevPxUnMap(psDevNode,
-                                                       psMemHandle,
-                                                       pvCpuVAddr);
+               PhysHeapPagesUnMap(psDevNode->psMMUPhysHeap,
+                                  psMemHandle,
+                                  pvCpuVAddr);
        }
 
        return PVRSRV_OK;
@@ -254,11 +262,11 @@ void DevPhysMemFree(PVRSRV_DEVICE_NODE *psDevNode,
        PG_HANDLE *psMemHandle;
 
        psMemHandle = hMemHandle;
-       psDevNode->sDevMMUPxSetup.pfnDevPxFree(psDevNode, psMemHandle);
+       PhysHeapPagesFree(psDevNode->psMMUPhysHeap, psMemHandle);
 #if defined(PDUMP)
        if (NULL != hPDUMPMemHandle)
        {
-               PDumpFree(hPDUMPMemHandle);
+               PDumpFree(psDevNode, hPDUMPMemHandle);
        }
 #endif
 
@@ -462,10 +470,12 @@ PhysmemNewRamBackedPMR_direct(CONNECTION_DATA *psConnection,
                        const IMG_CHAR *pszAnnotation,
                        IMG_PID uiPid,
                        PMR **ppsPMRPtr,
-                       IMG_UINT32 ui32PDumpFlags)
+                       IMG_UINT32 ui32PDumpFlags,
+                       PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags)
 {
        PVRSRV_ERROR eError;
        PVRSRV_PHYS_HEAP ePhysHeapIdx;
+       PVRSRV_MEMALLOCFLAGS_T uiPMRFlags = uiFlags;
        PFN_SYS_DEV_CHECK_MEM_ALLOC_SIZE pfnCheckMemAllocSize =
                psDevNode->psDevConfig->pfnCheckMemAllocSize;
 
@@ -482,16 +492,37 @@ PhysmemNewRamBackedPMR_direct(CONNECTION_DATA *psConnection,
        eError = _DevPhysHeapFromFlags(uiFlags, &ePhysHeapIdx);
        PVR_RETURN_IF_ERROR(eError);
 
+       if (ePhysHeapIdx == PVRSRV_PHYS_HEAP_DEFAULT)
+       {
+               ePhysHeapIdx = psDevNode->psDevConfig->eDefaultHeap;
+               PVRSRV_CHANGE_PHYS_HEAP_HINT(ePhysHeapIdx, uiPMRFlags);
+       }
+
        if (ePhysHeapIdx == PVRSRV_PHYS_HEAP_GPU_LOCAL)
        {
                if ((uiFlags & PVRSRV_MEMALLOCFLAGS_CPU_MAPPABLE_MASK) == 0)
                {
                        ePhysHeapIdx = PVRSRV_PHYS_HEAP_GPU_PRIVATE;
+                       PVRSRV_SET_PHYS_HEAP_HINT(GPU_PRIVATE, uiPMRFlags);
+                       PVR_DPF((PVR_DBG_VERBOSE, "%s: Consider explicit use of GPU_PRIVATE for PMR %s."
+                               " Implicit conversion to GPU PRIVATE performed",
+                               __func__, pszAnnotation));
                }
                else if (PVRSRV_CHECK_GPU_CACHE_COHERENT(uiFlags) &&
                                 PVRSRVSystemSnoopingOfCPUCache(psDevNode->psDevConfig))
                {
                        ePhysHeapIdx = PVRSRV_PHYS_HEAP_GPU_COHERENT;
+                       PVRSRV_SET_PHYS_HEAP_HINT(GPU_COHERENT, uiPMRFlags);
+               }
+       }
+       else if (ePhysHeapIdx == PVRSRV_PHYS_HEAP_GPU_PRIVATE)
+       {
+               if (uiFlags & PVRSRV_MEMALLOCFLAGS_CPU_MAPPABLE_MASK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Invalid flags for PMR %s!"
+                               " Client requested GPU_PRIVATE physical heap with CPU access flags.",
+                               __func__, pszAnnotation));
+                       return PVRSRV_ERROR_INVALID_HEAP;
                }
        }
 
@@ -555,6 +586,11 @@ PhysmemNewRamBackedPMR_direct(CONNECTION_DATA *psConnection,
                                                           ppsPMRPtr,
                                                           ui32PDumpFlags);
 
+       if (puiPMRFlags != NULL)
+       {
+               *puiPMRFlags = uiPMRFlags;
+       }
+
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
        if (eError != PVRSRV_OK)
        {
@@ -580,13 +616,19 @@ PhysmemNewRamBackedPMR(CONNECTION_DATA *psConnection,
                        const IMG_CHAR *pszAnnotation,
                        IMG_PID uiPid,
                        PMR **ppsPMRPtr,
-                       IMG_UINT32 ui32PDumpFlags)
+                       IMG_UINT32 ui32PDumpFlags,
+                       PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags)
 {
        PVRSRV_PHYS_HEAP ePhysHeap = PVRSRV_GET_PHYS_HEAP_HINT(uiFlags);
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(uiAnnotationLength != 0, "uiAnnotationLength");
        PVR_LOG_RETURN_IF_INVALID_PARAM(pszAnnotation != NULL, "pszAnnotation");
 
+       if (ePhysHeap == PVRSRV_PHYS_HEAP_DEFAULT)
+       {
+               ePhysHeap = psDevNode->psDevConfig->eDefaultHeap;
+       }
+
        if (!PhysHeapUserModeAlloc(ePhysHeap))
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Invalid phys heap hint: %d.", __func__, ePhysHeap));
@@ -606,7 +648,8 @@ PhysmemNewRamBackedPMR(CONNECTION_DATA *psConnection,
                                                                                 pszAnnotation,
                                                                                 uiPid,
                                                                                 ppsPMRPtr,
-                                                                                ui32PDumpFlags);
+                                                                                ui32PDumpFlags,
+                                                                                puiPMRFlags);
 }
 
 PVRSRV_ERROR
@@ -623,7 +666,8 @@ PhysmemNewRamBackedLockedPMR(CONNECTION_DATA *psConnection,
                                                        const IMG_CHAR *pszAnnotation,
                                                        IMG_PID uiPid,
                                                        PMR **ppsPMRPtr,
-                                                       IMG_UINT32 ui32PDumpFlags)
+                                                       IMG_UINT32 ui32PDumpFlags,
+                                                       PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags)
 {
 
        PVRSRV_ERROR eError;
@@ -640,7 +684,8 @@ PhysmemNewRamBackedLockedPMR(CONNECTION_DATA *psConnection,
                                                                        pszAnnotation,
                                                                        uiPid,
                                                                        ppsPMRPtr,
-                                                                       ui32PDumpFlags);
+                                                                       ui32PDumpFlags,
+                                                                       puiPMRFlags);
 
        if (eError == PVRSRV_OK)
        {
@@ -651,53 +696,117 @@ PhysmemNewRamBackedLockedPMR(CONNECTION_DATA *psConnection,
 }
 
 PVRSRV_ERROR
-PVRSRVGetMaxDevMemSizeKM(CONNECTION_DATA *psConnection,
+PVRSRVGetMaxPhysHeapCountKM(CONNECTION_DATA *psConnection,
+                                 PVRSRV_DEVICE_NODE *psDevNode,
+                                 IMG_UINT32 *pui32PhysHeapCount)
+{
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVRSRVGetDevicePhysHeapCount(psDevNode, pui32PhysHeapCount);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVGetDefaultPhysicalHeapKM(CONNECTION_DATA *psConnection,
                          PVRSRV_DEVICE_NODE *psDevNode,
-                         IMG_DEVMEM_SIZE_T *puiLMASize,
-                         IMG_DEVMEM_SIZE_T *puiUMASize )
+                         PVRSRV_PHYS_HEAP *peHeap)
+{
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       *peHeap = psDevNode->psDevConfig->eDefaultHeap;
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVGetHeapPhysMemUsageKM(CONNECTION_DATA *psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         IMG_UINT32 ui32PhysHeapCount,
+                         PHYS_HEAP_MEM_STATS *apPhysHeapMemStats)
 {
-       IMG_DEVMEM_SIZE_T uiLMASize = 0;
-       IMG_DEVMEM_SIZE_T uiUMASize = 0;
        PHYS_HEAP *psPhysHeap;
-       IMG_UINT uiHeapIndex;
-       IMG_UINT64 uiRegionSize;
+       IMG_UINT uiHeapIndex, i = 0;
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
-       /*
-        * psDevNode->apsPhysHeap may contain duplicates so loop over all registered
-        * heaps instead.
-        */
-       for (uiHeapIndex = 0; uiHeapIndex < psDevNode->ui32RegisteredPhysHeaps; uiHeapIndex++)
+       if (ui32PhysHeapCount != psDevNode->ui32UserAllocHeapCount)
        {
-               psPhysHeap = psDevNode->papsRegisteredPhysHeaps[uiHeapIndex];
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
 
-               if (psPhysHeap != psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL] &&
-                       psPhysHeap != psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_CPU_LOCAL])
-               {
-                       continue;
-               }
+       for (uiHeapIndex = PVRSRV_PHYS_HEAP_DEFAULT+1; (uiHeapIndex < PVRSRV_PHYS_HEAP_LAST); uiHeapIndex++)
+       {
+               psPhysHeap = psDevNode->apsPhysHeap[uiHeapIndex];
 
-               if (PhysHeapGetType(psPhysHeap) == PHYS_HEAP_TYPE_LMA)
+               if (psPhysHeap && PhysHeapUserModeAlloc(uiHeapIndex))
                {
+                       PVR_ASSERT(i < ui32PhysHeapCount);
 
-                       uiRegionSize = 0;
-                       PhysHeapGetSize(psPhysHeap, &uiRegionSize);
-                       uiLMASize += uiRegionSize;
+                       PhysheapGetPhysMemUsage(psPhysHeap, &apPhysHeapMemStats[i].ui64TotalSize,
+                                       &apPhysHeapMemStats[i].ui64FreeSize);
+
+                       i++;
                }
-               else if (PhysHeapGetType(psPhysHeap) == PHYS_HEAP_TYPE_UMA)
+       }
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVGetHeapPhysMemUsagePkdKM(CONNECTION_DATA *psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         IMG_UINT32 ui32PhysHeapCount,
+                         PHYS_HEAP_MEM_STATS_PKD *apPhysHeapMemStats)
+{
+       PHYS_HEAP *psPhysHeap;
+       IMG_UINT uiHeapIndex, i = 0;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       if (ui32PhysHeapCount != psDevNode->ui32UserAllocHeapCount)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       for (uiHeapIndex = PVRSRV_PHYS_HEAP_DEFAULT+1; (uiHeapIndex < PVRSRV_PHYS_HEAP_LAST); uiHeapIndex++)
+       {
+               psPhysHeap = psDevNode->apsPhysHeap[uiHeapIndex];
+
+               if (psPhysHeap && PhysHeapUserModeAlloc(uiHeapIndex))
                {
-                       if (uiUMASize == 0)
-                       {
-                               uiUMASize = OSGetRAMSize();
-                       }
+                       PVR_ASSERT(i < ui32PhysHeapCount);
+
+                       PhysheapGetPhysMemUsage(psPhysHeap, &apPhysHeapMemStats[i].ui64TotalSize,
+                                       &apPhysHeapMemStats[i].ui64FreeSize);
+
+                       i++;
                }
        }
+       return PVRSRV_OK;
+}
 
-       *puiLMASize = uiLMASize;
-       *puiUMASize = uiUMASize;
+PVRSRV_ERROR
+PVRSRVPhysHeapGetMemInfoKM(CONNECTION_DATA *psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         IMG_UINT32 ui32PhysHeapCount,
+                         PVRSRV_PHYS_HEAP *paePhysHeapID,
+                         PHYS_HEAP_MEM_STATS *paPhysHeapMemStats)
+{
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       return PhysHeapGetMemInfo(psDevNode,
+                                 ui32PhysHeapCount,
+                                 paePhysHeapID,
+                                 paPhysHeapMemStats);
+}
 
-       return PVRSRV_OK;
+PVRSRV_ERROR
+PVRSRVPhysHeapGetMemInfoPkdKM(CONNECTION_DATA *psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         IMG_UINT32 ui32PhysHeapCount,
+                         PVRSRV_PHYS_HEAP *paePhysHeapID,
+                         PHYS_HEAP_MEM_STATS_PKD *paPhysHeapMemStats)
+{
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       return PhysHeapGetMemInfoPkd(psDevNode,
+                                 ui32PhysHeapCount,
+                                 paePhysHeapID,
+                                 paPhysHeapMemStats);
 }
 
 /* 'Wrapper' function to call PMRImportPMR(), which first checks the PMR is
index c09fa40..4fa61ac 100644 (file)
@@ -168,7 +168,26 @@ _GetSize(PHEAP_IMPL_DATA pvImplData,
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR
+static IMG_UINT32
+_GetPageShift(void)
+{
+       return PVRSRV_4K_PAGE_SIZE_ALIGNSHIFT;
+}
+
+static void PhysmemGetLocalRamMemStats(PHEAP_IMPL_DATA pvImplData,
+                IMG_UINT64 *pui64TotalSize,
+                IMG_UINT64 *pui64FreeSize)
+{
+       PHYSMEM_LMA_DATA *psLMAData = (PHYSMEM_LMA_DATA*)pvImplData;
+       RA_USAGE_STATS sRAUsageStats;
+
+       RA_Get_Usage_Stats(psLMAData->psRA, &sRAUsageStats);
+
+       *pui64TotalSize = sRAUsageStats.ui64TotalArenaSize;
+       *pui64FreeSize = sRAUsageStats.ui64FreeArenaSize;
+}
+
+static PVRSRV_ERROR
 PhysmemGetArenaLMA(PHYS_HEAP *psPhysHeap,
                                   RA_ARENA **ppsArena)
 {
@@ -219,13 +238,426 @@ _DestroyImplData(PHEAP_IMPL_DATA pvImplData)
        OSFreeMem(psLMAData);
 }
 
+struct _PHYS_HEAP_ITERATOR_ {
+       PHYS_HEAP *psPhysHeap;
+       RA_ARENA_ITERATOR *psRAIter;
+
+       IMG_UINT64 uiTotalSize;
+       IMG_UINT64 uiInUseSize;
+};
+
+PVRSRV_ERROR LMA_HeapIteratorCreate(PVRSRV_DEVICE_NODE *psDevNode,
+                                    PHYS_HEAP_USAGE_FLAGS ui32Flags,
+                                    PHYS_HEAP_ITERATOR **ppsIter)
+{
+       PVRSRV_ERROR eError;
+       PHYSMEM_LMA_DATA *psLMAData;
+       PHYS_HEAP_ITERATOR *psHeapIter;
+       PHYS_HEAP *psPhysHeap = NULL;
+       RA_USAGE_STATS sStats;
+
+       PVR_LOG_RETURN_IF_INVALID_PARAM(ppsIter != NULL, "ppsIter");
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psDevNode != NULL, "psDevNode");
+       PVR_LOG_RETURN_IF_INVALID_PARAM(ui32Flags != 0, "ui32Flags");
+
+       eError = PhysHeapAcquireByUsage(ui32Flags, psDevNode, &psPhysHeap);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PhysHeapAcquireByUsage");
+
+       PVR_LOG_GOTO_IF_FALSE(PhysHeapGetType(psPhysHeap) == PHYS_HEAP_TYPE_LMA,
+                             "PhysHeap must be of LMA type", release_heap);
+
+       psLMAData = (PHYSMEM_LMA_DATA *) PhysHeapGetImplData(psPhysHeap);
+
+       psHeapIter = OSAllocMem(sizeof(*psHeapIter));
+       PVR_LOG_GOTO_IF_NOMEM(psHeapIter, eError, release_heap);
+
+       psHeapIter->psPhysHeap = psPhysHeap;
+       psHeapIter->psRAIter = RA_IteratorAcquire(psLMAData->psRA, IMG_FALSE);
+       PVR_LOG_GOTO_IF_NOMEM(psHeapIter->psRAIter, eError, free_heap_iter);
+
+       /* get heap usage */
+       RA_Get_Usage_Stats(psLMAData->psRA, &sStats);
+
+       psHeapIter->uiTotalSize = sStats.ui64TotalArenaSize;
+       psHeapIter->uiInUseSize = sStats.ui64TotalArenaSize - sStats.ui64FreeArenaSize;
+
+       *ppsIter = psHeapIter;
+
+       return PVRSRV_OK;
+
+free_heap_iter:
+       OSFreeMem(psHeapIter);
+
+release_heap:
+       PhysHeapRelease(psPhysHeap);
+
+       return eError;
+}
+
+void LMA_HeapIteratorDestroy(PHYS_HEAP_ITERATOR *psIter)
+{
+       PHYS_HEAP_ITERATOR *psHeapIter = psIter;
+
+       PVR_LOG_RETURN_VOID_IF_FALSE(psHeapIter != NULL, "psHeapIter is NULL");
+
+       PhysHeapRelease(psHeapIter->psPhysHeap);
+       RA_IteratorRelease(psHeapIter->psRAIter);
+       OSFreeMem(psHeapIter);
+}
+
+PVRSRV_ERROR LMA_HeapIteratorReset(PHYS_HEAP_ITERATOR *psIter)
+{
+       PHYS_HEAP_ITERATOR *psHeapIter = psIter;
+
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psHeapIter != NULL, "ppsIter");
+
+       RA_IteratorReset(psHeapIter->psRAIter);
+
+       return PVRSRV_OK;
+}
+
+IMG_BOOL LMA_HeapIteratorNext(PHYS_HEAP_ITERATOR *psIter,
+                              IMG_DEV_PHYADDR *psDevPAddr,
+                              IMG_UINT64 *puiSize)
+{
+       PHYS_HEAP_ITERATOR *psHeapIter = psIter;
+       RA_ITERATOR_DATA sData = {0};
+
+       if (psHeapIter == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "psHeapIter in %s() is NULL", __func__));
+               return IMG_FALSE;
+       }
+
+       if (!RA_IteratorNext(psHeapIter->psRAIter, &sData))
+       {
+               return IMG_FALSE;
+       }
+
+       PVR_ASSERT(sData.uiSize != 0);
+
+       psDevPAddr->uiAddr = sData.uiAddr;
+       *puiSize = sData.uiSize;
+
+       return IMG_TRUE;
+}
+
+PVRSRV_ERROR LMA_HeapIteratorGetHeapStats(PHYS_HEAP_ITERATOR *psIter,
+                                          IMG_UINT64 *puiTotalSize,
+                                          IMG_UINT64 *puiInUseSize)
+{
+       PHYS_HEAP_ITERATOR *psHeapIter = psIter;
+
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psHeapIter != NULL, "psHeapIter");
+
+       *puiTotalSize = psHeapIter->uiTotalSize;
+       *puiInUseSize = psHeapIter->uiInUseSize;
+
+       return PVRSRV_OK;
+}
+
+
+static PVRSRV_ERROR
+_LMA_DoPhyContigPagesAlloc(RA_ARENA *pArena,
+                           size_t uiSize,
+                           PG_HANDLE *psMemHandle,
+                           IMG_DEV_PHYADDR *psDevPAddr,
+                           IMG_PID uiPid)
+{
+       RA_BASE_T uiCardAddr = 0;
+       RA_LENGTH_T uiActualSize;
+       PVRSRV_ERROR eError;
+#if defined(DEBUG)
+       static IMG_UINT32       ui32MaxLog2NumPages = 4;        /* 16 pages => 64KB */
+#endif /* defined(DEBUG) */
+
+       IMG_UINT32 ui32Log2NumPages = 0;
+
+       PVR_ASSERT(uiSize != 0);
+       ui32Log2NumPages = OSGetOrder(uiSize);
+       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
+
+       eError = RA_Alloc(pArena,
+                         uiSize,
+                         RA_NO_IMPORT_MULTIPLIER,
+                         0,                         /* No flags */
+                         uiSize,
+                         "LMA_PhyContigPagesAlloc",
+                         &uiCardAddr,
+                         &uiActualSize,
+                         NULL);                     /* No private handle */
+
+       PVR_ASSERT(uiSize == uiActualSize);
+
+       psMemHandle->u.ui64Handle = uiCardAddr;
+       psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
+
+       if (PVRSRV_OK == eError)
+       {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+               PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+                                                   uiSize,
+                                                   uiCardAddr,
+                                                   uiPid);
+#else
+               IMG_CPU_PHYADDR sCpuPAddr;
+               sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
+
+               PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+                                            NULL,
+                                            sCpuPAddr,
+                                            uiSize,
+                                            NULL,
+                                            uiPid
+                                            DEBUG_MEMSTATS_VALUES);
+#endif
+#endif
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+               PVR_DPF((PVR_DBG_MESSAGE,
+                       "%s: (GPU Virtualisation) Allocated 0x" IMG_SIZE_FMTSPECX " at 0x%" IMG_UINT64_FMTSPECX ", Arena ID %u",
+                       __func__, uiSize, psDevPAddr->uiAddr, psMemHandle->uiOSid));
+#endif
+
+#if defined(DEBUG)
+               PVR_ASSERT((ui32Log2NumPages <= ui32MaxLog2NumPages));
+               if (ui32Log2NumPages > ui32MaxLog2NumPages)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: ui32MaxLog2NumPages = %u, increasing to %u", __func__,
+                               ui32MaxLog2NumPages, ui32Log2NumPages ));
+                       ui32MaxLog2NumPages = ui32Log2NumPages;
+               }
+#endif /* defined(DEBUG) */
+               psMemHandle->uiOrder = ui32Log2NumPages;
+       }
+
+       return eError;
+}
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+static PVRSRV_ERROR
+LMA_PhyContigPagesAllocGPV(PHYS_HEAP *psPhysHeap,
+                           size_t uiSize,
+                           PG_HANDLE *psMemHandle,
+                           IMG_DEV_PHYADDR *psDevPAddr,
+                           IMG_UINT32 ui32OSid,
+                           IMG_PID uiPid)
+{
+       PVRSRV_DEVICE_NODE *psDevNode = PhysHeapDeviceNode(psPhysHeap);
+       RA_ARENA *pArena;
+       IMG_UINT32 ui32Log2NumPages = 0;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(uiSize != 0);
+       ui32Log2NumPages = OSGetOrder(uiSize);
+       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
+
+       PVR_ASSERT(ui32OSid < GPUVIRT_VALIDATION_NUM_OS);
+       if (ui32OSid >= GPUVIRT_VALIDATION_NUM_OS)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Arena index %u defaulting to 0",
+                       __func__, ui32OSid));
+               ui32OSid = 0;
+       }
+
+       pArena = psDevNode->psOSidSubArena[ui32OSid];
+
+       if (psMemHandle->uiOSid != ui32OSid)
+       {
+               PVR_LOG(("%s: Unexpected OSid value %u - expecting %u", __func__,
+                       psMemHandle->uiOSid, ui32OSid));
+       }
+
+       psMemHandle->uiOSid = ui32OSid;         /* For Free() use */
+
+       eError =  _LMA_DoPhyContigPagesAlloc(pArena, uiSize, psMemHandle,
+                                            psDevPAddr, uiPid);
+       PVR_LOG_IF_ERROR(eError, "_LMA_DoPhyContigPagesAlloc");
+
+       return eError;
+}
+#endif
+
+static PVRSRV_ERROR
+LMA_PhyContigPagesAlloc(PHYS_HEAP *psPhysHeap,
+                        size_t uiSize,
+                        PG_HANDLE *psMemHandle,
+                        IMG_DEV_PHYADDR *psDevPAddr,
+                        IMG_PID uiPid)
+{
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       IMG_UINT32 ui32OSid = 0;
+       return LMA_PhyContigPagesAllocGPV(psPhysHeap, uiSize, psMemHandle, psDevPAddr,
+                                                                         ui32OSid, uiPid);
+#else
+       PVRSRV_ERROR eError;
+
+       RA_ARENA *pArena;
+       IMG_UINT32 ui32Log2NumPages = 0;
+
+       eError = PhysmemGetArenaLMA(psPhysHeap, &pArena);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PhysmemGetArenaLMA");
+
+       PVR_ASSERT(uiSize != 0);
+       ui32Log2NumPages = OSGetOrder(uiSize);
+       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
+
+       eError = _LMA_DoPhyContigPagesAlloc(pArena, uiSize, psMemHandle,
+                                           psDevPAddr, uiPid);
+       PVR_LOG_IF_ERROR(eError, "_LMA_DoPhyContigPagesAlloc");
+
+       return eError;
+#endif
+}
+
+static void
+LMA_PhyContigPagesFree(PHYS_HEAP *psPhysHeap,
+                                          PG_HANDLE *psMemHandle)
+{
+       RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
+       RA_ARENA        *pArena;
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       PVRSRV_DEVICE_NODE *psDevNode = PhysHeapDeviceNode(psPhysHeap);
+       IMG_UINT32      ui32OSid = psMemHandle->uiOSid;
+
+       /*
+        * The Arena ID is set by the originating allocation, and maintained via
+        * the call stacks into this function. We have a limited range of IDs
+        * and if the passed value falls outside this we simply treat it as a
+        * 'global' arena ID of 0. This is where all default OS-specific allocations
+        * are created.
+        */
+       PVR_ASSERT(ui32OSid < GPUVIRT_VALIDATION_NUM_OS);
+       if (ui32OSid >= GPUVIRT_VALIDATION_NUM_OS)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Arena index %u PhysAddr 0x%"
+                        IMG_UINT64_FMTSPECx " Reverting to Arena 0", __func__,
+                        ui32OSid, uiCardAddr));
+               /*
+                * No way of determining what we're trying to free so default to the
+                * global default arena index 0.
+                */
+               ui32OSid = 0;
+       }
+
+       pArena = psDevNode->psOSidSubArena[ui32OSid];
+
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: (GPU Virtualisation) Freeing 0x%"
+               IMG_UINT64_FMTSPECx ", Arena %u", __func__,
+               uiCardAddr, ui32OSid));
+
+#else
+       PhysmemGetArenaLMA(psPhysHeap, &pArena);
+#endif
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+       PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+                                             (IMG_UINT64)uiCardAddr);
+#else
+       PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
+                                                                       (IMG_UINT64)uiCardAddr,
+                                                                       OSGetCurrentClientProcessIDKM());
+#endif
+#endif
+
+       RA_Free(pArena, uiCardAddr);
+       psMemHandle->uiOrder = 0;
+}
+
+static PVRSRV_ERROR
+LMA_PhyContigPagesMap(PHYS_HEAP *psPhysHeap,
+                      PG_HANDLE *psMemHandle,
+                      size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
+                      void **pvPtr)
+{
+       IMG_CPU_PHYADDR sCpuPAddr;
+       IMG_UINT32 ui32NumPages = (1 << psMemHandle->uiOrder);
+       PVR_UNREFERENCED_PARAMETER(uiSize);
+
+       PhysHeapDevPAddrToCpuPAddr(psPhysHeap, 1, &sCpuPAddr, psDevPAddr);
+       *pvPtr = OSMapPhysToLin(sCpuPAddr,
+                                                       ui32NumPages * OSGetPageSize(),
+                                                       PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC);
+       PVR_RETURN_IF_NOMEM(*pvPtr);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+       PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+                                   ui32NumPages * OSGetPageSize(),
+                                   OSGetCurrentClientProcessIDKM());
+#else
+       {
+               PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+                                                                        *pvPtr,
+                                                                        sCpuPAddr,
+                                                                        ui32NumPages * OSGetPageSize(),
+                                                                        NULL,
+                                                                        OSGetCurrentClientProcessIDKM()
+                                                                        DEBUG_MEMSTATS_VALUES);
+       }
+#endif
+#endif
+       return PVRSRV_OK;
+}
+
+static void
+LMA_PhyContigPagesUnmap(PHYS_HEAP *psPhysHeap,
+                        PG_HANDLE *psMemHandle,
+                        void *pvPtr)
+{
+       IMG_UINT32 ui32NumPages = (1 << psMemHandle->uiOrder);
+       PVR_UNREFERENCED_PARAMETER(psPhysHeap);
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
+       PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+                                           ui32NumPages * OSGetPageSize(),
+                                           OSGetCurrentClientProcessIDKM());
+#else
+       PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
+                                       (IMG_UINT64)(uintptr_t)pvPtr,
+                                       OSGetCurrentClientProcessIDKM());
+#endif
+#endif
+
+       OSUnMapPhysToLin(pvPtr, ui32NumPages * OSGetPageSize());
+}
+
+static PVRSRV_ERROR
+LMA_PhyContigPagesClean(PHYS_HEAP *psPhysHeap,
+                                               PG_HANDLE *psMemHandle,
+                                               IMG_UINT32 uiOffset,
+                                               IMG_UINT32 uiLength)
+{
+       /* No need to flush because we map as uncached */
+       PVR_UNREFERENCED_PARAMETER(psPhysHeap);
+       PVR_UNREFERENCED_PARAMETER(psMemHandle);
+       PVR_UNREFERENCED_PARAMETER(uiOffset);
+       PVR_UNREFERENCED_PARAMETER(uiLength);
+
+       return PVRSRV_OK;
+}
+
 static PHEAP_IMPL_FUNCS _sPHEAPImplFuncs =
 {
        .pfnDestroyData = &_DestroyImplData,
        .pfnGetDevPAddr = &_GetDevPAddr,
        .pfnGetCPUPAddr = &_GetCPUPAddr,
        .pfnGetSize = &_GetSize,
+       .pfnGetPageShift = &_GetPageShift,
+       .pfnGetPMRFactoryMemStats = &PhysmemGetLocalRamMemStats,
        .pfnCreatePMR = &PhysmemNewLocalRamBackedPMR,
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+       .pfnPagesAllocGPV = &LMA_PhyContigPagesAllocGPV,
+#endif
+       .pfnPagesAlloc = &LMA_PhyContigPagesAlloc,
+       .pfnPagesFree = &LMA_PhyContigPagesFree,
+       .pfnPagesMap = &LMA_PhyContigPagesMap,
+       .pfnPagesUnMap = &LMA_PhyContigPagesUnmap,
+       .pfnPagesClean = &LMA_PhyContigPagesClean,
 };
 
 PVRSRV_ERROR
@@ -304,11 +736,11 @@ _PoisonAlloc(PHYS_HEAP *psPhysHeap,
        eError = _MapAlloc(psPhysHeap,
                                           psDevPAddr,
                                           uiContigAllocSize,
-                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC,
                                           &pvKernLin);
        PVR_GOTO_IF_ERROR(eError, map_failed);
 
-       OSDeviceMemSet(pvKernLin, ui8PoisonValue, uiContigAllocSize);
+       OSCachedMemSetWMB(pvKernLin, ui8PoisonValue, uiContigAllocSize);
 
        _UnMapAlloc(uiContigAllocSize, pvKernLin);
 
@@ -330,11 +762,11 @@ _ZeroAlloc(PHYS_HEAP *psPhysHeap,
        eError = _MapAlloc(psPhysHeap,
                                           psDevPAddr,
                                           uiContigAllocSize,
-                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC,
                                           &pvKernLin);
        PVR_GOTO_IF_ERROR(eError, map_failed);
 
-       OSDeviceMemSet(pvKernLin, 0, uiContigAllocSize);
+       OSCachedMemSetWMB(pvKernLin, 0, uiContigAllocSize);
 
        _UnMapAlloc(uiContigAllocSize, pvKernLin);
 
@@ -871,7 +1303,9 @@ PMRSysPhysAddrLocalMem(PMR_IMPL_PRIVDATA pvPriv,
                                uiAllocIndex = puiOffset[idx] >> uiLog2AllocSize;
                                uiInAllocOffset = puiOffset[idx] - (uiAllocIndex << uiLog2AllocSize);
 
-                               PVR_ASSERT(uiAllocIndex < uiNumAllocs);
+                               PVR_LOG_RETURN_IF_FALSE(uiAllocIndex < uiNumAllocs,
+                                                       "puiOffset out of range", PVRSRV_ERROR_OUT_OF_RANGE);
+
                                PVR_ASSERT(uiInAllocOffset < (1ULL << uiLog2AllocSize));
 
                                psDevPAddr[idx].uiAddr = psLMAllocArrayData->pasDevPAddr[uiAllocIndex].uiAddr + uiInAllocOffset;
@@ -892,25 +1326,13 @@ PMRSysPhysAddrLocalMem(PMR_IMPL_PRIVDATA pvPriv,
        return PVRSRV_OK;
 }
 
-
-#ifdef CACHE_TEST
-static PVRSRV_ERROR
-PMRAcquireKernelMappingDataLocalMem(PMR_IMPL_PRIVDATA pvPriv,
-                                                                size_t uiOffset,
-                                                                size_t uiSize,                           
-                                                                size_t uilogicSize,                                     
-                                                                void **ppvKernelAddressOut,
-                                                                IMG_HANDLE *phHandleOut,
-                                                                PMR_FLAGS_T ulFlags)
-#else
 static PVRSRV_ERROR
 PMRAcquireKernelMappingDataLocalMem(PMR_IMPL_PRIVDATA pvPriv,
                                                                 size_t uiOffset,
-                                                                size_t uiSize,                           
+                                                                size_t uiSize,
                                                                 void **ppvKernelAddressOut,
                                                                 IMG_HANDLE *phHandleOut,
                                                                 PMR_FLAGS_T ulFlags)
-#endif
 {
        PVRSRV_ERROR eError;
        PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = NULL;
@@ -959,74 +1381,11 @@ e0:
        return eError;
 }
 
-#if defined(INTEGRITY_OS)
-static PVRSRV_ERROR PMRMapMemoryObjectLocalMem(PMR_IMPL_PRIVDATA pvPriv, IMG_HANDLE *phMemObj, void **ppvClientAddr, IMG_HANDLE *phHandleOut)
-{
-       PVRSRV_ERROR ePVRError = PVRSRV_OK;
-       Error eOSError = Success;
-       PMR_MAP_DATA *psMapData = (PMR_MAP_DATA *)pvPriv;
-       PMR_MAP_DATA_ARRAY *psMapDataArray = psMapData->paMemObj;
-
-       /* Create a private copy of the mapping data to keep the mapping information separate for every new client */
-       struct _PMR_MAP_DATA_ARRAY_ *psMapDataArrayCopy = OSAllocMem(sizeof(struct _PMR_MAP_DATA_ARRAY_));
-       PVR_LOG_RETURN_IF_NOMEM(psMapDataArrayCopy, OSAllocMem);
-
-       memcpy(psMapDataArrayCopy, psMapDataArray, sizeof(struct _PMR_MAP_DATA_ARRAY_));
-
-       ePVRError = IntegrityMapMemoryObject(psMapDataArrayCopy->hFrameMem, *phMemObj);
-
-       if (ePVRError == PVRSRV_OK)
-       {
-               ePVRError = IntegrityGetMemoryObjectCPUVAddrRange(*phMemObj, ppvClientAddr, NULL);
-
-               if (ePVRError == PVRSRV_OK)
-               {
-                       psMapDataArrayCopy->hVirtMemObj=*phMemObj;
-                       *phHandleOut = (IMG_HANDLE)psMapDataArrayCopy;
-               }
-               else
-               {
-                       ePVRError = PVRSRV_ERROR_FAILED_TO_MAP_KERNELVIRTUAL;
-                       PVR_DPF((PVR_DBG_ERROR, "%s: IntegrityGetMemoryObjectCPUVAddrRange failed.", __func__));
-               }
-       }
-       else
-       {
-               OSFreeMem(psMapDataArrayCopy);
-               ePVRError = PVRSRV_ERROR_FAILED_TO_MAP_KERNELVIRTUAL;
-               PVR_DPF((PVR_DBG_ERROR, "%s: failed.", __func__));
-       }
-
-       return ePVRError;
-}
-
-static PVRSRV_ERROR PMRUnmapMemoryObjectLocalMem(PMR_IMPL_PRIVDATA pvPriv)
-{
-       PVRSRV_ERROR ePVRError = PVRSRV_OK;
-
-       struct _PMR_MAP_DATA_ARRAY_ *psMapDataArray = (struct _PMR_MAP_DATA_ARRAY_ *)pvPriv;
-       PVR_LOG_GOTO_IF_INVALID_PARAM(psMapDataArray != NULL, ePVRError, e0);
-
-       ePVRError = IntegrityUnmapMemoryObject(psMapDataArray->hVirtMemObj);
-       if (ePVRError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: failed to unmap", __func__));
-       }
-
-       OSFreeMem(psMapDataArray);
-
-e0:
-       return ePVRError;
-}
-#endif
-
 static void PMRReleaseKernelMappingDataLocalMem(PMR_IMPL_PRIVDATA pvPriv,
-                                                                                                IMG_HANDLE hHandle, struct _PMR_ *psPMR)
+                                                                                                IMG_HANDLE hHandle)
 {
        PMR_LMALLOCARRAY_DATA *psLMAllocArrayData = NULL;
        void *pvKernLinAddr = NULL;
-       
-       PVR_UNREFERENCED_PARAMETER(psPMR);
 
        psLMAllocArrayData = (PMR_LMALLOCARRAY_DATA *) pvPriv;
        pvKernLinAddr = (void *) hHandle;
@@ -1084,7 +1443,7 @@ CopyBytesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
                        eError = _MapAlloc(psLMAllocArrayData->psPhysHeap,
                                                                &psLMAllocArrayData->pasDevPAddr[uiAllocIndex],
                                                                psLMAllocArrayData->uiContigAllocSize,
-                                                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+                                                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC,
                                                                &pvMapping);
                        PVR_GOTO_IF_ERROR(eError, e0);
                        pcKernelPointer = pvMapping;
@@ -1106,7 +1465,7 @@ CopyBytesLocalMem(PMR_IMPL_PRIVDATA pvPriv,
                        eError = _MapAlloc(psLMAllocArrayData->psPhysHeap,
                                                                &psLMAllocArrayData->pasDevPAddr[0],
                                                                psLMAllocArrayData->uiContigAllocSize,
-                                                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED,
+                                                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC,
                                                                &pvMapping);
                        PVR_GOTO_IF_ERROR(eError, e0);
                        pcKernelPointer = pvMapping;
@@ -1128,10 +1487,8 @@ static void ReadLocalMem(IMG_UINT8 *pcBuffer,
                                                 IMG_UINT8 *pcPMR,
                                                 size_t uiSize)
 {
-       /* NOTE: 'CachedMemCopy' means the operating system default memcpy, which
-        *       we *assume* in the LMA code will be faster, and doesn't need to
-        *       worry about ARM64.
-        */
+       /* the memory is mapped as WC (and also aligned to page size) so we can
+        * safely call "Cached" memcpy */
        OSCachedMemCopy(pcBuffer, pcPMR, uiSize);
 }
 
@@ -1154,11 +1511,10 @@ static void WriteLocalMem(IMG_UINT8 *pcBuffer,
                                                  IMG_UINT8 *pcPMR,
                                                  size_t uiSize)
 {
-       /* NOTE: 'CachedMemCopy' means the operating system default memcpy, which
-        *       we *assume* in the LMA code will be faster, and doesn't need to
-        *       worry about ARM64.
-        */
-       OSCachedMemCopy(pcPMR, pcBuffer, uiSize);
+       /* the memory is mapped as WC (and also aligned to page size) so we can
+        * safely call "Cached" memcpy but need to issue a write memory barrier
+        * to flush the write buffers after */
+       OSCachedMemCopyWMB(pcPMR, pcBuffer, uiSize);
 }
 
 static PVRSRV_ERROR
@@ -1235,7 +1591,7 @@ PMRChangeSparseMemLocalMem(PMR_IMPL_PRIVDATA pPriv,
                ui32CommonRequstCount = (ui32AllocPageCount > ui32FreePageCount) ?
                                ui32FreePageCount : ui32AllocPageCount;
 
-               PDUMP_PANIC(SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
+               PDUMP_PANIC(PMR_DeviceNode(psPMR), SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
        }
 
        if (SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
@@ -1496,12 +1852,6 @@ static PMR_IMPL_FUNCTAB _sPMRLMAFuncTab = {
        &PMRAcquireKernelMappingDataLocalMem,
        /* pfnReleaseKernelMappingData */
        &PMRReleaseKernelMappingDataLocalMem,
-#if defined(INTEGRITY_OS)
-       /* pfnMapMemoryObject */
-       PMRMapMemoryObjectLocalMem,
-       /* pfnUnmapMemoryObject */
-       PMRUnmapMemoryObjectLocalMem,
-#endif
        /* pfnReadBytes */
        &PMRReadBytesLocalMem,
        /* pfnWriteBytes */
@@ -1568,7 +1918,11 @@ PhysmemNewLocalRamBackedPMR(PHYS_HEAP *psPhysHeap,
        bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiFlags) ? IMG_TRUE : IMG_FALSE;
        bZero = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
        bPoisonOnAlloc = PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags) ? IMG_TRUE : IMG_FALSE;
+#if defined(DEBUG)
        bPoisonOnFree = PVRSRV_CHECK_POISON_ON_FREE(uiFlags) ? IMG_TRUE : IMG_FALSE;
+#else
+       bPoisonOnFree = IMG_FALSE;
+#endif
 
        /* Create Array structure that holds the physical pages */
        eError = _AllocLMPageArray(uiChunkSize * ui32NumVirtChunks,
@@ -1609,7 +1963,7 @@ PhysmemNewLocalRamBackedPMR(PHYS_HEAP *psPhysHeap,
 
        if (bOnDemand)
        {
-               PDUMPCOMMENT("Deferred Allocation PMR (LMA)");
+               PDUMPCOMMENT(PhysHeapDeviceNode(psPhysHeap), "Deferred Allocation PMR (LMA)");
        }
 
        eError = PMRCreatePMR(psPhysHeap,
index bdb317a..8c4575b 100644 (file)
@@ -93,6 +93,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "proc_stats.h"
 #endif
 
+#include "pdump_km.h"
+
 /* Memalloc flags can be converted into pmr, ra or psplay flags.
  * Ensure flags types are same size.
  */
@@ -314,6 +316,46 @@ struct _PMR_PAGELIST_
        struct _PMR_ *psReferencePMR;
 };
 
+#if defined(PDUMP)
+static INLINE IMG_BOOL _IsHostDevicePMR(const PMR *const psPMR)
+{
+       const PVRSRV_DEVICE_NODE *psDevNode = PVRSRVGetPVRSRVData()->psHostMemDeviceNode;
+       return psPMR->psPhysHeap == psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_CPU_LOCAL];
+}
+
+static void
+PDumpPMRFreePMR(PMR *psPMR,
+                IMG_DEVMEM_SIZE_T uiSize,
+                IMG_DEVMEM_ALIGN_T uiBlockSize,
+                IMG_UINT32 uiLog2Contiguity,
+                IMG_HANDLE hPDumpAllocationInfoHandle);
+
+static void
+PDumpPMRMallocPMR(PMR *psPMR,
+                  IMG_DEVMEM_SIZE_T uiSize,
+                  IMG_DEVMEM_ALIGN_T uiBlockSize,
+                  IMG_UINT32 ui32ChunkSize,
+                  IMG_UINT32 ui32NumPhysChunks,
+                  IMG_UINT32 ui32NumVirtChunks,
+                  IMG_UINT32 *puiMappingTable,
+                  IMG_UINT32 uiLog2Contiguity,
+                  IMG_BOOL bInitialise,
+                  IMG_UINT32 ui32InitValue,
+                  IMG_HANDLE *phPDumpAllocInfoOut,
+                  IMG_UINT32 ui32PDumpFlags);
+
+static void
+PDumpPMRChangeSparsePMR(PMR *psPMR,
+                        IMG_UINT32 uiBlockSize,
+                        IMG_UINT32 ui32AllocPageCount,
+                        IMG_UINT32 *pai32AllocIndices,
+                        IMG_UINT32 ui32FreePageCount,
+                        IMG_UINT32 *pai32FreeIndices,
+                        IMG_BOOL bInitialise,
+                        IMG_UINT32 ui32InitValue,
+                        IMG_HANDLE *phPDumpAllocInfoOut);
+#endif /* defined PDUMP */
+
 PPVRSRV_DEVICE_NODE PMRGetExportDeviceNode(PMR_EXPORT *psExportPMR)
 {
        PPVRSRV_DEVICE_NODE psReturnedDeviceNode = NULL;
@@ -529,11 +571,15 @@ _UnrefAndMaybeDestroy(PMR *psPMR)
                        PVR_ASSERT (eError2 == PVRSRV_OK); /* can we do better? */
                }
 #if defined(PDUMP)
-               PDumpPMRFreePMR(psPMR,
-                               psPMR->uiLogicalSize,
-                               (1 << psPMR->uiLog2ContiguityGuarantee),
-                               psPMR->uiLog2ContiguityGuarantee,
-                               psPMR->hPDumpAllocHandle);
+               /* if allocation is done on the host node don't include it in the PDUMP */
+               if (!_IsHostDevicePMR(psPMR))
+               {
+                       PDumpPMRFreePMR(psPMR,
+                                       psPMR->uiLogicalSize,
+                                       (1 << psPMR->uiLog2ContiguityGuarantee),
+                                       psPMR->uiLog2ContiguityGuarantee,
+                                       psPMR->hPDumpAllocHandle);
+               }
 #endif
 
 #if defined(PVRSRV_ENABLE_LINUX_MMAP_STATS)
@@ -644,6 +690,8 @@ PMRCreatePMR(PHYS_HEAP *psPhysHeap,
        OSStringLCopy(psPMR->szAnnotation, pszAnnotation, DEVMEM_ANNOTATION_MAX_LEN);
 
 #if defined(PDUMP)
+       /* if allocation was done on the host node don't include it in the PDUMP */
+       if (!_IsHostDevicePMR(psPMR))
        {
                PMR_FLAGS_T uiFlags = psPMR->uiFlags;
                IMG_BOOL bInitialise = IMG_FALSE;
@@ -1168,10 +1216,6 @@ _PMRAcquireKernelMappingData(PMR *psPMR,
        eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                               uiLogicalOffset,
                                                               uiSize,
-#ifdef CACHE_TEST                                                               
-                                                                                                                  pmr_size(psPMR),
-#endif
-
                                                               &pvKernelAddress,
                                                               &hPriv,
                                                               psPMR->uiFlags);
@@ -1244,44 +1288,11 @@ PMRReleaseKernelMappingData(PMR *psPMR,
        PVR_ASSERT (psPMR->psFuncTab->pfnReleaseKernelMappingData != NULL);
 
        psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
-                                                     hPriv, psPMR);
+                                                     hPriv);
 
        return PVRSRV_OK;
 }
 
-#if defined(INTEGRITY_OS)
-
-PVRSRV_ERROR
-PMRMapMemoryObject(PMR *psPMR,
-                   IMG_HANDLE *phMemObj,
-                   void **pvClientAddr,
-                   IMG_HANDLE *phPrivOut)
-{
-       PVRSRV_ERROR eError = PVRSRV_OK;
-       IMG_HANDLE hPriv = *phPrivOut;
-
-       PVR_ASSERT (psPMR->psFuncTab->pfnMapMemoryObject != NULL);
-
-       eError = psPMR->psFuncTab->pfnMapMemoryObject(hPriv, phMemObj, pvClientAddr, phPrivOut);
-
-       return eError;
-}
-
-PVRSRV_ERROR
-PMRUnmapMemoryObject(PMR *psPMR,
-                     IMG_HANDLE hPriv)
-{
-       PVRSRV_ERROR eError = PVRSRV_OK;
-
-       PVR_ASSERT (psPMR->psFuncTab->pfnUnmapMemoryObject != NULL);
-
-       eError = psPMR->psFuncTab->pfnUnmapMemoryObject(hPriv);
-
-       return eError;
-}
-
-#endif /* INTEGRITY_OS */
-
 /*
        _PMRLogicalOffsetToPhysicalOffset
 
@@ -1413,9 +1424,6 @@ _PMR_ReadBytesPhysical(PMR *psPMR,
                eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                                       (size_t) uiPhysicalOffset,
                                                                       uiBufSz,
-#ifdef CACHE_TEST                                                               
-                                                                                                                          pmr_size(psPMR),
-#endif                                                                
                                                                       (void **)&pcKernelAddress,
                                                                       &hKernelMappingHandle,
                                                                       psPMR->uiFlags);
@@ -1429,7 +1437,7 @@ _PMR_ReadBytesPhysical(PMR *psPMR,
                *puiNumBytes = uiBufSz;
 
                psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
-                                                             hKernelMappingHandle, psPMR);
+                                                             hKernelMappingHandle);
        }
        else
        {
@@ -1564,10 +1572,6 @@ _PMR_WriteBytesPhysical(PMR *psPMR,
                eError = psPMR->psFuncTab->pfnAcquireKernelMappingData(psPMR->pvFlavourData,
                                                                       (size_t) uiPhysicalOffset,
                                                                       uiBufSz,
-#ifdef CACHE_TEST                                                               
-                                                                                                                          pmr_size(psPMR),
-#endif
-
                                                                       (void **)&pcKernelAddress,
                                                                       &hKernelMappingHandle,
                                                                       psPMR->uiFlags);
@@ -1581,7 +1585,7 @@ _PMR_WriteBytesPhysical(PMR *psPMR,
                *puiNumBytes = uiBufSz;
 
                psPMR->psFuncTab->pfnReleaseKernelMappingData(psPMR->pvFlavourData,
-                                                             hKernelMappingHandle, psPMR);
+                                                             hKernelMappingHandle);
        }
        else
        {
@@ -1764,14 +1768,13 @@ IMG_BOOL PMR_IsMemLayoutFixed(PMR *psPMR)
        return psPMR->bNoLayoutChange;
 }
 
-PVRSRV_ERROR
+void
 PMR_LogicalSize(const PMR *psPMR,
                 IMG_DEVMEM_SIZE_T *puiLogicalSize)
 {
        PVR_ASSERT(psPMR != NULL);
 
        *puiLogicalSize = psPMR->uiLogicalSize;
-       return PVRSRV_OK;
 }
 
 PVRSRV_ERROR
@@ -1913,7 +1916,7 @@ PMR_DevPhysAddr(const PMR *psPMR,
        if (ui32NumOfPages > PMR_MAX_TRANSLATION_STACK_ALLOC)
        {
                puiPhysicalOffset = OSAllocMem(ui32NumOfPages * sizeof(IMG_DEVMEM_OFFSET_T));
-               PVR_GOTO_IF_NOMEM(puiPhysicalOffset, eError, e0);
+               PVR_RETURN_IF_NOMEM(puiPhysicalOffset);
        }
 
        _PMRLogicalOffsetToPhysicalOffset(psPMR,
@@ -1932,13 +1935,17 @@ PMR_DevPhysAddr(const PMR *psPMR,
                                                          puiPhysicalOffset,
                                                          pbValid,
                                                          psDevAddrPtr);
-#if defined(PVR_PMR_TRANSLATE_UMA_ADDRESSES)
-               /* Currently excluded from the default build because of performance concerns.
-                * We do not need this part in all systems because the GPU has the same address view of system RAM as the CPU.
-                * Alternatively this could be implemented as part of the PMR-factories directly */
+               PVR_GOTO_IF_ERROR(eError, FreeOffsetArray);
 
+#if defined(PVR_PMR_TRANSLATE_UMA_ADDRESSES)
+               /* Currently excluded from the default build because of performance
+                * concerns.
+                * We do not need this part in all systems because the GPU has the same
+                * address view of system RAM as the CPU.
+                * Alternatively this could be implemented as part of the PMR-factories
+                * directly */
                if (PhysHeapGetType(psPMR->psPhysHeap) == PHYS_HEAP_TYPE_UMA ||
-                               PhysHeapGetType(psPMR->psPhysHeap) == PHYS_HEAP_TYPE_DMA)
+                   PhysHeapGetType(psPMR->psPhysHeap) == PHYS_HEAP_TYPE_DMA)
                {
                        IMG_UINT32 i;
                        IMG_DEV_PHYADDR sDevPAddrCorrected;
@@ -1956,17 +1963,12 @@ PMR_DevPhysAddr(const PMR *psPMR,
 #endif
        }
 
+FreeOffsetArray:
        if (puiPhysicalOffset != auiPhysicalOffset)
        {
                OSFreeMem(puiPhysicalOffset);
        }
 
-       PVR_GOTO_IF_ERROR(eError, e0);
-
-       return PVRSRV_OK;
-
-e0:
-       PVR_ASSERT(eError != PVRSRV_OK);
        return eError;
 }
 
@@ -2222,6 +2224,14 @@ PMR_PDumpSymbolicAddr(const PMR *psPMR,
 
        PVR_ASSERT(uiLogicalOffset < psPMR->uiLogicalSize);
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        _PMRLogicalOffsetToPhysicalOffset(psPMR,
                                          0,
                                          1,
@@ -2272,6 +2282,14 @@ PMRPDumpLoadMemValue32(PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiNextSymName;
        IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        PVR_ASSERT(uiLogicalOffset + sizeof(ui32Value) <= psPMR->uiLogicalSize);
        /* Especially make sure to not cross a block boundary */
        PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui32Value))
@@ -2292,7 +2310,8 @@ PMRPDumpLoadMemValue32(PMR *psPMR,
        PVR_ASSERT(eError == PVRSRV_OK);
 
        /* Write the WRW script command */
-       eError = PDumpPMRWRW32(aszMemspaceName,
+       eError = PDumpPMRWRW32(PMR_DeviceNode(psPMR),
+                              aszMemspaceName,
                               aszSymbolicName,
                               uiPDumpSymbolicOffset,
                               ui32Value,
@@ -2344,7 +2363,6 @@ PMRPDumpCopyMem32(PMR *psDstPMR,
        PVR_ASSERT(( ((uiDstLogicalOffset & (uiDstPMRPageSize-1)) + sizeof(IMG_UINT32))
                        <= uiDstPMRPageSize));
 
-
        eError = PMRLockSysPhysAddresses(psSrcPMR);
        PVR_ASSERT(eError == PVRSRV_OK);
 
@@ -2360,7 +2378,8 @@ PMRPDumpCopyMem32(PMR *psDstPMR,
        PVR_ASSERT(eError == PVRSRV_OK);
 
        /* Issue PDump read command */
-       eError = PDumpPMRRDW32MemToInternalVar(pszTmpVar,
+       eError = PDumpPMRRDW32MemToInternalVar(PMR_DeviceNode(psSrcPMR),
+                                              pszTmpVar,
                                               aszMemspaceName,
                                               aszSymbolicName,
                                               uiPDumpSymbolicOffset,
@@ -2389,7 +2408,8 @@ PMRPDumpCopyMem32(PMR *psDstPMR,
 
 
        /* Write the WRW script command */
-       eError = PDumpPMRWRW32InternalVarToMem(aszMemspaceName,
+       eError = PDumpPMRWRW32InternalVarToMem(PMR_DeviceNode(psDstPMR),
+                                              aszMemspaceName,
                                               aszSymbolicName,
                                               uiPDumpSymbolicOffset,
                                               pszTmpVar,
@@ -2426,6 +2446,13 @@ PMRPDumpLoadMemValue64(PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiNextSymName;
        IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
 
        PVR_ASSERT(uiLogicalOffset + sizeof(ui64Value) <= psPMR->uiLogicalSize);
        /* Especially make sure to not cross a block boundary */
@@ -2447,7 +2474,8 @@ PMRPDumpLoadMemValue64(PMR *psPMR,
        PVR_ASSERT(eError == PVRSRV_OK);
 
        /* Write the WRW script command */
-       eError = PDumpPMRWRW64(aszMemspaceName,
+       eError = PDumpPMRWRW64(PMR_DeviceNode(psPMR),
+                              aszMemspaceName,
                               aszSymbolicName,
                               uiPDumpSymbolicOffset,
                               ui64Value,
@@ -2499,7 +2527,6 @@ PMRPDumpCopyMem64(PMR *psDstPMR,
        PVR_ASSERT(( ((uiDstLogicalOffset & (uiDstPMRPageSize-1)) + sizeof(IMG_UINT32))
                        <= uiDstPMRPageSize));
 
-
        eError = PMRLockSysPhysAddresses(psSrcPMR);
        PVR_ASSERT(eError == PVRSRV_OK);
 
@@ -2515,7 +2542,8 @@ PMRPDumpCopyMem64(PMR *psDstPMR,
        PVR_ASSERT(eError == PVRSRV_OK);
 
        /* Issue PDump read command */
-       eError = PDumpPMRRDW64MemToInternalVar(pszTmpVar,
+       eError = PDumpPMRRDW64MemToInternalVar(PMR_DeviceNode(psSrcPMR),
+                                              pszTmpVar,
                                               aszMemspaceName,
                                               aszSymbolicName,
                                               uiPDumpSymbolicOffset,
@@ -2544,7 +2572,8 @@ PMRPDumpCopyMem64(PMR *psDstPMR,
 
 
        /* Write the WRW script command */
-       eError = PDumpPMRWRW64InternalVarToMem(aszMemspaceName,
+       eError = PDumpPMRWRW64InternalVarToMem(PMR_DeviceNode(psDstPMR),
+                                              aszMemspaceName,
                                               aszSymbolicName,
                                               uiPDumpSymbolicOffset,
                                               pszTmpVar,
@@ -2592,11 +2621,21 @@ PMRPDumpLoadMem(PMR *psPMR,
        size_t uiBufSz;
        IMG_BOOL bValid;
        IMG_DEVMEM_SIZE_T uiSizeRemain = uiSize;
+       PVRSRV_DEVICE_NODE *psDevNode = PMR_DeviceNode(psPMR);
+
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(psDevNode))
+       {
+               return PVRSRV_OK;
+       }
 
        PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
 
        /* Check if pdump client is connected */
-       if (!PDumpIsContCaptureOn())
+       if (!PDumpCheckFlagsWrite(psDevNode,
+                                     PDUMP_FLAGS_CONTINUOUS))
        {
                /* Dumping of memory in Pdump buffer will be rejected for no client connected case.
                 * So return early and save reading of data from PMR. */
@@ -2606,7 +2645,8 @@ PMRPDumpLoadMem(PMR *psPMR,
        /* Get the correct PDump stream file name */
        if (bZero)
        {
-               PDumpCommentWithFlags(uiPDumpFlags,
+               PDumpCommentWithFlags(psDevNode,
+                                     uiPDumpFlags,
                                      "Zeroing allocation (" IMG_DEVMEM_SIZE_FMTSPEC " bytes)",
                                      uiSize);
 
@@ -2677,7 +2717,8 @@ PMRPDumpLoadMem(PMR *psPMR,
                                                       &uiNumBytes);
                                PVR_ASSERT(eError == PVRSRV_OK);
 
-                               eError = PDumpWriteParameterBlob(pcBuffer,
+                               eError = PDumpWriteParameterBlob(psDevNode,
+                                                         pcBuffer,
                                                          uiNumBytes,
                                                          uiPDumpFlags,
                                                          &aszParamStreamFilename[0],
@@ -2692,12 +2733,14 @@ PMRPDumpLoadMem(PMR *psPMR,
                                }
                                else if (eError != PVRSRV_OK)
                                {
-                                       PDUMP_ERROR(eError, "Failed to write PMR memory to parameter file");
+                                       PDUMP_ERROR(psDevNode,
+                                                   eError, "Failed to write PMR memory to parameter file");
                                }
                        }
 
                        /* Emit the LDB command to the current symbolic address */
-                       eError = PDumpPMRLDB(aszMemspaceName,
+                       eError = PDumpPMRLDB(psDevNode,
+                                            aszMemspaceName,
                                             aszSymbolicName,
                                             uiOutOffset,
                                             uiNumBytes,
@@ -2740,6 +2783,14 @@ PMRPDumpSaveToFile(const PMR *psPMR,
 
        PVR_UNREFERENCED_PARAMETER(uiArraySize);
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        PVR_ASSERT(uiLogicalOffset + uiSize <= psPMR->uiLogicalSize);
 
        while (uiCurrentOffset < (uiLogicalOffset + uiSize))
@@ -2761,7 +2812,8 @@ PMRPDumpSaveToFile(const PMR *psPMR,
                                uiLogicalOffset + uiSize - uiCurrentOffset :
                                uiNextSymName - uiCurrentOffset);
 
-               eError = PDumpPMRSAB(aszMemspaceName,
+               eError = PDumpPMRSAB(PMR_DeviceNode(psPMR),
+                                    aszMemspaceName,
                                     aszSymbolicName,
                                     uiOutOffset,
                                     uiReadOffset,
@@ -2791,6 +2843,14 @@ PMRPDumpPol32(const PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiNextSymName;
        IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        /* Make sure to not cross a block boundary */
        PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui32Value))
                        <= uiPMRPageSize));
@@ -2808,7 +2868,8 @@ PMRPDumpPol32(const PMR *psPMR,
 #define _MEMPOLL_DELAY         (1000)
 #define _MEMPOLL_COUNT         (2000000000 / _MEMPOLL_DELAY)
 
-       eError = PDumpPMRPOL(aszMemspaceName,
+       eError = PDumpPMRPOL(PMR_DeviceNode(psPMR),
+                            aszMemspaceName,
                             aszSymbolicName,
                             uiPDumpOffset,
                             ui32Value,
@@ -2842,6 +2903,14 @@ PMRPDumpCheck32(const PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiNextSymName;
        IMG_UINT32 uiPMRPageSize = 1 << psPMR->uiLog2ContiguityGuarantee;
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        /* Make sure to not cross a block boundary */
        PVR_ASSERT(( ((uiLogicalOffset & (uiPMRPageSize-1)) + sizeof(ui32Value))
                   < uiPMRPageSize));
@@ -2859,7 +2928,8 @@ PMRPDumpCheck32(const PMR *psPMR,
                goto e0;
        }
 
-       eError = PDumpPMRPOL(aszMemspaceName,
+       eError = PDumpPMRPOL(PMR_DeviceNode(psPMR),
+                            aszMemspaceName,
                             aszSymbolicName,
                             uiPDumpOffset,
                             ui32Value,
@@ -2894,6 +2964,14 @@ PMRPDumpCBP(const PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiPDumpOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
 
+       /* Confirm that the device node's ui32InternalID matches the bound
+        * PDump device stored* in PVRSRV_DATA.
+        */
+       if (!PDumpIsDevicePermitted(PMR_DeviceNode(psPMR)))
+       {
+               return PVRSRV_OK;
+       }
+
        eError = PMR_PDumpSymbolicAddr(psPMR,
                                       uiReadOffset,
                                       sizeof(aszMemspaceName),
@@ -2904,7 +2982,8 @@ PMRPDumpCBP(const PMR *psPMR,
                                       &uiNextSymName);
        PVR_GOTO_IF_ERROR(eError, e0);
 
-       eError = PDumpPMRCBP(aszMemspaceName,
+       eError = PDumpPMRCBP(PMR_DeviceNode(psPMR),
+                            aszMemspaceName,
                             aszSymbolicName,
                             uiPDumpOffset,
                             uiWriteOffset,
@@ -2920,7 +2999,7 @@ e0:
        return eError;
 }
 
-void
+static void
 PDumpPMRChangeSparsePMR(PMR *psPMR,
                         IMG_UINT32 uiBlockSize,
                         IMG_UINT32 ui32AllocPageCount,
@@ -2939,13 +3018,15 @@ PDumpPMRChangeSparsePMR(PMR *psPMR,
        IMG_DEVMEM_OFFSET_T uiOffset;
        IMG_DEVMEM_OFFSET_T uiNextSymName;
        IMG_UINT32 i, uiIndex;
+       PVRSRV_DEVICE_NODE *psDevNode = PMR_DeviceNode(psPMR);
 
        /* Remove pages from the PMR */
        for (i = 0; i < ui32FreePageCount; i++)
        {
                uiIndex = pai32FreeIndices[i];
 
-               eError = PDumpFree(phPDumpAllocInfo[uiIndex]);
+               eError = PDumpFree(psDevNode,
+                                  phPDumpAllocInfo[uiIndex]);
                PVR_ASSERT(eError == PVRSRV_OK);
                phPDumpAllocInfo[uiIndex] = NULL;
        }
@@ -2967,7 +3048,8 @@ PDumpPMRChangeSparsePMR(PMR *psPMR,
                                               &uiNextSymName);
                PVR_ASSERT(eError == PVRSRV_OK);
 
-               eError = PDumpMalloc(aszMemspaceName,
+               eError = PDumpMalloc(psDevNode,
+                                    aszMemspaceName,
                                     aszSymbolicName,
                                     uiBlockSize,
                                     uiBlockSize,
@@ -2982,7 +3064,7 @@ PDumpPMRChangeSparsePMR(PMR *psPMR,
        *phPDumpAllocInfoOut = (IMG_HANDLE) phPDumpAllocInfo;
 }
 
-void
+static void
 PDumpPMRFreePMR(PMR *psPMR,
                 IMG_DEVMEM_SIZE_T uiSize,
                 IMG_DEVMEM_ALIGN_T uiBlockSize,
@@ -2999,7 +3081,8 @@ PDumpPMRFreePMR(PMR *psPMR,
        {
                if (ahPDumpAllocHandleArray[i] != NULL)
                {
-                       eError = PDumpFree(ahPDumpAllocHandleArray[i]);
+                       eError = PDumpFree(PMR_DeviceNode(psPMR),
+                                          ahPDumpAllocHandleArray[i]);
                        PVR_ASSERT(eError == PVRSRV_OK);
                        ahPDumpAllocHandleArray[i] = NULL;
                }
@@ -3008,8 +3091,7 @@ PDumpPMRFreePMR(PMR *psPMR,
        OSFreeMem(ahPDumpAllocHandleArray);
 }
 
-
-void
+static void
 PDumpPMRMallocPMR(PMR *psPMR,
                   IMG_DEVMEM_SIZE_T uiSize,
                   IMG_DEVMEM_ALIGN_T uiBlockSize,
@@ -3069,7 +3151,8 @@ PDumpPMRMallocPMR(PMR *psPMR,
                                               &uiNextSymName);
                PVR_ASSERT(eError == PVRSRV_OK);
 
-               eError = PDumpMalloc(aszMemspaceName,
+               eError = PDumpMalloc(PMR_DeviceNode(psPMR),
+                                    aszMemspaceName,
                                     aszSymbolicName,
                                     uiBlockSize,
                                     uiBlockSize,
@@ -3077,6 +3160,8 @@ PDumpPMRMallocPMR(PMR *psPMR,
                                     ui32InitValue,
                                     &phPDumpAllocInfo[uiIndex],
                                     ui32PDumpFlags);
+               PVR_LOG_RETURN_VOID_IF_FALSE((eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE),
+                                            "PDumpPMRMalloc PDump capture bound to other device");
                PVR_ASSERT(eError == PVRSRV_OK);
        }
 
@@ -3239,7 +3324,8 @@ PMRWritePMPageList(/* Target PMR, offset, and length */
                                               &uiNextSymName);
                PVR_ASSERT(eError == PVRSRV_OK);
 
-               eError = PDumpWriteShiftedMaskedValue(/* destination */
+               eError = PDumpWriteShiftedMaskedValue(PMR_DeviceNode(psReferencePMR),
+                                                     /* destination */
                                                      aszTableEntryMemspaceName,
                                                      aszTableEntrySymbolicName,
                                                      uiTableEntryPDumpOffset,
@@ -3322,7 +3408,7 @@ PMRWritePMPageList(/* Target PMR, offset, and length */
         * buffers */
        if (PVRSRV_CHECK_CPU_WRITE_COMBINE(psPageListPMR->uiFlags))
        {
-               OSWriteMemoryBarrier();
+               OSWriteMemoryBarrier(NULL);
        }
 
 #if !defined(NO_HARDWARE)
@@ -3609,15 +3695,3 @@ out:
        PVR_ASSERT(eError == PVRSRV_OK);
        return eError;
 }
-
-
-void show_pmr_info(PMR *psPMR)
-{
-       printk("PMR: name:%s\n", &psPMR->szAnnotation[0]);
-}
-
-size_t pmr_size(PMR *psPMR)
-{
-       return (size_t)psPMR->uiLogicalSize;
-}
-
index 73e4122..5ad6695 100644 (file)
@@ -320,7 +320,7 @@ PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(PPVRSRV_DEVICE_NODE psDeviceNode)
 
  @Input                psPowerDevice : Power device
  @Input                eNewPowerState : New power state
- @Input                bForced : TRUE if the transition should not fail (e.g. OS request)
+ @Input                ePwrFlags : Power state change flags
 
  @Return       PVRSRV_ERROR
 
@@ -328,7 +328,7 @@ PVRSRV_ERROR PVRSRVDeviceIdleCancelRequestKM(PPVRSRV_DEVICE_NODE psDeviceNode)
 static
 PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV              *psPowerDevice,
                                                                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
-                                                                                IMG_BOOL                               bForced)
+                                                                                PVRSRV_POWER_FLAGS             ePwrFlags)
 {
        PVRSRV_DEV_POWER_STATE eCurrentPowerState;
        IMG_UINT64 ui64SysTimer1 = 0;
@@ -349,7 +349,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV           *psPowerDevice,
                eError = psPowerDevice->pfnDevicePrePower(psPowerDevice->hDevCookie,
                                                                                                  eNewPowerState,
                                                                                                  eCurrentPowerState,
-                                                                                                 bForced);
+                                                                                                 BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED));
 
                ui64DevTimer2 = PVRSRVProcessStatsGetTimeNs();
 
@@ -368,7 +368,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV           *psPowerDevice,
                                                                                                  (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) ?
                                                                                                        PVRSRV_SYS_POWER_STATE_ON :
                                                                                                        PVRSRV_SYS_POWER_STATE_OFF,
-                                                                                                 bForced);
+                                                                                                 ePwrFlags);
 
                ui64SysTimer2 = PVRSRVProcessStatsGetTimeNs();
 
@@ -377,7 +377,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV           *psPowerDevice,
 
        InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
                                                         ui64DevTimer1, ui64DevTimer2,
-                                                        bForced,
+                                                        BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED),
                                                         eNewPowerState == PVRSRV_DEV_POWER_STATE_ON,
                                                         IMG_TRUE);
 
@@ -395,7 +395,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV           *psPowerDevice,
 
  @Input                psPowerDevice : Power device
  @Input                eNewPowerState : New power state
- @Input                bForced : TRUE if the transition should not fail (e.g. OS request)
+ @Input                ePwrFlags : Power state change flags
 
  @Return       PVRSRV_ERROR
 
@@ -403,7 +403,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(PVRSRV_POWER_DEV           *psPowerDevice,
 static
 PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV                     *psPowerDevice,
                                                                                  PVRSRV_DEV_POWER_STATE        eNewPowerState,
-                                                                                 IMG_BOOL                                      bForced)
+                                                                                 PVRSRV_POWER_FLAGS            ePwrFlags)
 {
        PVRSRV_DEV_POWER_STATE eCurrentPowerState;
        IMG_UINT64 ui64SysTimer1 = 0;
@@ -428,7 +428,7 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV                  *psPowerDevice,
                                                                                                   (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON) ?
                                                                                                         PVRSRV_SYS_POWER_STATE_ON :
                                                                                                         PVRSRV_SYS_POWER_STATE_OFF,
-                                                                                                  bForced);
+                                                                                                  ePwrFlags);
 
                ui64SysTimer2 = PVRSRVProcessStatsGetTimeNs();
 
@@ -443,7 +443,7 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV                  *psPowerDevice,
                eError = psPowerDevice->pfnDevicePostPower(psPowerDevice->hDevCookie,
                                                                                                   eNewPowerState,
                                                                                                   eCurrentPowerState,
-                                                                                                  bForced);
+                                                                                                  BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED));
 
                ui64DevTimer2 = PVRSRVProcessStatsGetTimeNs();
 
@@ -452,7 +452,7 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV                  *psPowerDevice,
 
        InsertPowerTimeStatistic(ui64SysTimer1, ui64SysTimer2,
                                                         ui64DevTimer1, ui64DevTimer2,
-                                                        bForced,
+                                                        BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED),
                                                         eNewPowerState == PVRSRV_DEV_POWER_STATE_ON,
                                                         IMG_FALSE);
 
@@ -462,8 +462,8 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(PVRSRV_POWER_DEV                  *psPowerDevice,
 }
 
 PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(PPVRSRV_DEVICE_NODE psDeviceNode,
-                                                                                PVRSRV_DEV_POWER_STATE eNewPowerState,
-                                                                                IMG_BOOL                               bForced)
+                                                                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                                PVRSRV_POWER_FLAGS ePwrFlags)
 {
        PVRSRV_ERROR    eError;
        PVRSRV_DATA*    psPVRSRVData = PVRSRVGetPVRSRVData();
@@ -484,12 +484,12 @@ PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(PPVRSRV_DEVICE_NODE psDeviceNode,
        {
                eError = PVRSRVDevicePrePowerStateKM(psPowerDevice,
                                                                                         eNewPowerState,
-                                                                                        bForced);
+                                                                                        ePwrFlags);
                PVR_GOTO_IF_ERROR(eError, ErrorExit);
 
                eError = PVRSRVDevicePostPowerStateKM(psPowerDevice,
                                                                                          eNewPowerState,
-                                                                                         bForced);
+                                                                                         ePwrFlags);
                PVR_GOTO_IF_ERROR(eError, ErrorExit);
 
                /* Signal Device Watchdog Thread about power mode change. */
@@ -522,8 +522,8 @@ ErrorExit:
        if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
        {
                PVR_DPF((PVR_DBG_MESSAGE,
-                                "%s: Transition to %d was denied, Forced=%d",
-                                __func__, eNewPowerState, bForced));
+                                "%s: Transition to %d was denied, Flags=0x%08x",
+                                __func__, eNewPowerState, ePwrFlags));
        }
        else if (eError != PVRSRV_OK)
        {
@@ -536,7 +536,8 @@ ErrorExit:
 }
 
 PVRSRV_ERROR PVRSRVSetDeviceSystemPowerState(PPVRSRV_DEVICE_NODE psDeviceNode,
-                                                                                        PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+                                                                                        PVRSRV_SYS_POWER_STATE eNewSysPowerState,
+                                                                                        PVRSRV_POWER_FLAGS ePwrFlags)
 {
        PVRSRV_ERROR eError;
        IMG_UINT uiStage = 0;
@@ -574,7 +575,7 @@ PVRSRV_ERROR PVRSRVSetDeviceSystemPowerState(PPVRSRV_DEVICE_NODE psDeviceNode,
        }
 
        eError = PVRSRVSetDevicePowerStateKM(psDeviceNode, eNewDevicePowerState,
-                                                                                IMG_TRUE);
+                                                                                ePwrFlags | PVRSRV_POWER_FLAGS_FORCED);
        if (eError != PVRSRV_OK)
        {
                uiStage++;
@@ -628,7 +629,7 @@ PVRSRV_ERROR PVRSRVSetSystemPowerState(PVRSRV_DEVICE_CONFIG *psDevConfig,
                eError = psDevConfig->pfnPrePowerState(psDevConfig->hSysData,
                                                                                                  eNewSysPowerState,
                                                                                                  eCurrentSysPowerState,
-                                                                                                 IMG_TRUE);
+                                                                                                 PVRSRV_POWER_FLAGS_FORCED);
 
                PVR_RETURN_IF_ERROR(eError);
        }
@@ -638,7 +639,7 @@ PVRSRV_ERROR PVRSRVSetSystemPowerState(PVRSRV_DEVICE_CONFIG *psDevConfig,
                eError = psDevConfig->pfnPostPowerState(psDevConfig->hSysData,
                                                                                                   eNewSysPowerState,
                                                                                                   eCurrentSysPowerState,
-                                                                                                  IMG_TRUE);
+                                                                                                  PVRSRV_POWER_FLAGS_FORCED);
 
                PVR_RETURN_IF_ERROR(eError);
        }
@@ -727,15 +728,13 @@ PVRSRV_ERROR PVRSRVRegisterPowerDevice(PPVRSRV_DEVICE_NODE psDeviceNode,
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR PVRSRVRemovePowerDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
+void PVRSRVRemovePowerDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
 {
        if (psDeviceNode->psPowerDev)
        {
                OSFreeMem(psDeviceNode->psPowerDev);
                psDeviceNode->psPowerDev = NULL;
        }
-
-       return PVRSRV_OK;
 }
 
 PVRSRV_ERROR PVRSRVGetDevicePowerState(PCPVRSRV_DEVICE_NODE psDeviceNode,
@@ -796,7 +795,12 @@ PVRSRVDevicePreClockSpeedChange(PPVRSRV_DEVICE_NODE psDeviceNode,
 
                        if (eError != PVRSRV_OK)
                        {
-                               PVR_DPF((PVR_DBG_WARNING, "%s() failed (%s) in %s()", "PVRSRVDeviceIdleRequestKM", PVRSRVGETERRORSTRING(eError), __func__));
+                               /* FW Can signal denied when busy with SPM or other work it can not idle */
+                               if (eError != PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s: Error (%s) from %s()", __func__,
+                                                PVRSRVGETERRORSTRING(eError), "PVRSRVDeviceIdleRequestKM"));
+                               }
                                if (eError != PVRSRV_ERROR_PWLOCK_RELEASED_REACQ_FAILED)
                                {
                                        PVRSRVPowerUnlock(psDeviceNode);
index b15cb0e..5867e2a 100644 (file)
@@ -120,7 +120,7 @@ int GlobalStatsPrintElements(OSDI_IMPL_ENTRY *psEntry, void *pvData);
 
 /* Macros for fetching stat values */
 #define GET_STAT_VALUE(ptr,var) (ptr)->i32StatValue[(var)]
-#define GET_GLOBAL_STAT_VALUE(idx) gsGlobalStats.ui32StatValue[idx]
+#define GET_GLOBAL_STAT_VALUE(idx) gsGlobalStats.ui64StatValue[idx]
 
 #define GET_GPUMEM_GLOBAL_STAT_VALUE() \
        GET_GLOBAL_STAT_VALUE(PVRSRV_DRIVER_STAT_TYPE_ALLOC_PT_MEMORY_UMA) + \
@@ -140,14 +140,14 @@ int GlobalStatsPrintElements(OSDI_IMPL_ENTRY *psEntry, void *pvData);
  */
 #define UPDATE_MAX_VALUE(a,b)                                  do { if ((b) > (a)) {(a) = (b);} } while (0)
 #define INCREASE_STAT_VALUE(ptr,var,val)               do { (ptr)->i32StatValue[(var)] += (val); if ((ptr)->i32StatValue[(var)] > (ptr)->i32StatValue[(var##_MAX)]) {(ptr)->i32StatValue[(var##_MAX)] = (ptr)->i32StatValue[(var)];} } while (0)
-#define INCREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { (var).ui32StatValue[(idx)] += (val); if ((var).ui32StatValue[(idx)] > (var).ui32StatValue[(idx##_MAX)]) {(var).ui32StatValue[(idx##_MAX)] = (var).ui32StatValue[(idx)];} } while (0)
+#define INCREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { (var).ui64StatValue[(idx)] += (val); if ((var).ui64StatValue[(idx)] > (var).ui64StatValue[(idx##_MAX)]) {(var).ui64StatValue[(idx##_MAX)] = (var).ui64StatValue[(idx)];} } while (0)
 #if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
 /* Allow stats to go negative */
 #define DECREASE_STAT_VALUE(ptr,var,val)               do { (ptr)->i32StatValue[(var)] -= (val); } while (0)
-#define DECREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { (var).ui32StatValue[(idx)] -= (val); } while (0)
+#define DECREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { (var).ui64StatValue[(idx)] -= (val); } while (0)
 #else
 #define DECREASE_STAT_VALUE(ptr,var,val)               do { if ((ptr)->i32StatValue[(var)] >= (val)) { (ptr)->i32StatValue[(var)] -= (val); } else { (ptr)->i32StatValue[(var)] = 0; } } while (0)
-#define DECREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { if ((var).ui32StatValue[(idx)] >= (val)) { (var).ui32StatValue[(idx)] -= (val); } else { (var).ui32StatValue[(idx)] = 0; } } while (0)
+#define DECREASE_GLOBAL_STAT_VALUE(var,idx,val)                do { if ((var).ui64StatValue[(idx)] >= (val)) { (var).ui64StatValue[(idx)] -= (val); } else { (var).ui64StatValue[(idx)] = 0; } } while (0)
 #endif
 #define MAX_CACHEOP_STAT 16
 #define INCREMENT_CACHEOP_STAT_IDX_WRAP(x) ((x+1) >= MAX_CACHEOP_STAT ? 0 : (x+1))
@@ -205,7 +205,6 @@ typedef struct _PVRSRV_PROCESS_STATS_ {
                IMG_DEVMEM_SIZE_T      uiSize;
                IMG_UINT64             ui64ExecuteTime;
                IMG_BOOL               bUserModeFlush;
-               IMG_UINT32             ui32OpSeqNum;
                IMG_BOOL               bIsFence;
                IMG_PID                ownerPid;
        }                              asCacheOp[MAX_CACHEOP_STAT];
@@ -412,7 +411,7 @@ static IMG_HANDLE g_hDriverProcessStats;
 /* Global driver-data folders */
 typedef struct _GLOBAL_STATS_
 {
-       IMG_UINT32 ui32StatValue[PVRSRV_DRIVER_STAT_TYPE_COUNT];
+       IMG_UINT64 ui64StatValue[PVRSRV_DRIVER_STAT_TYPE_COUNT];
        POS_LOCK   hGlobalStatsLock;
 } GLOBAL_STATS;
 
@@ -1931,34 +1930,33 @@ PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE eAllocType,
 
        /* Alloc untracked memory for the new hash table entry */
        psNewTrackingHashEntry = (_PVR_STATS_TRACKING_HASH_ENTRY *)OSAllocMemNoStats(sizeof(*psNewTrackingHashEntry));
-       if (psNewTrackingHashEntry)
+       if (psNewTrackingHashEntry == NULL)
        {
-               /* Fill-in the size of the allocation and PID of the allocating process */
-               psNewTrackingHashEntry->uiSizeInBytes = uiBytes;
-               psNewTrackingHashEntry->uiPid = uiPid;
-               OSLockAcquire(gpsSizeTrackingHashTableLock);
-               /* Insert address of the new struct into the hash table */
-               bRes = HASH_Insert(gpsSizeTrackingHashTable, uiCpuVAddr, (uintptr_t)psNewTrackingHashEntry);
-               OSLockRelease(gpsSizeTrackingHashTableLock);
+               PVR_DPF((PVR_DBG_ERROR,
+                                "*** %s : @ line %d Failed to alloc memory for psNewTrackingHashEntry!",
+                                __func__, __LINE__));
+               return;
        }
 
-       if (psNewTrackingHashEntry)
+       /* Fill-in the size of the allocation and PID of the allocating process */
+       psNewTrackingHashEntry->uiSizeInBytes = uiBytes;
+       psNewTrackingHashEntry->uiPid = uiPid;
+       OSLockAcquire(gpsSizeTrackingHashTableLock);
+       /* Insert address of the new struct into the hash table */
+       bRes = HASH_Insert(gpsSizeTrackingHashTable, uiCpuVAddr, (uintptr_t)psNewTrackingHashEntry);
+       OSLockRelease(gpsSizeTrackingHashTableLock);
+       if (bRes)
        {
-               if (bRes)
-               {
-                       PVRSRVStatsIncrMemAllocStat(eAllocType, uiBytes, uiPid);
-               }
-               else
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "*** %s : @ line %d HASH_Insert() failed!",
-                                        __func__, __LINE__));
-               }
+               PVRSRVStatsIncrMemAllocStat(eAllocType, uiBytes, uiPid);
        }
        else
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                                "*** %s : @ line %d Failed to alloc memory for psNewTrackingHashEntry!",
+               PVR_DPF((PVR_DBG_ERROR, "*** %s : @ line %d HASH_Insert() failed!",
                                 __func__, __LINE__));
+               /* Free the memory allocated for psNewTrackingHashEntry, as we
+                * failed to insert it into the Hash table.
+                */
+               OSFreeMemNoStats(psNewTrackingHashEntry);
        }
 }
 
@@ -2314,13 +2312,14 @@ int RawProcessStatsPrintElements(OSDI_IMPL_ENTRY *psEntry, void *pvData)
        PVRSRV_PROCESS_STATS *psProcessStats;
 
        DIPrintf(psEntry,
-                "%s,%s,%s,%s,%s,%s\n",
+                "%s,%s,%s,%s,%s,%s,%s\n",
                 "PID",
                 "MemoryUsageKMalloc",           // PVRSRV_PROCESS_STAT_TYPE_KMALLOC
                 "MemoryUsageAllocPTMemoryUMA",  // PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA
                 "MemoryUsageAllocPTMemoryLMA",  // PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA
                 "MemoryUsageAllocGPUMemLMA",    // PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES
-                "MemoryUsageAllocGPUMemUMA");   // PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES
+                "MemoryUsageAllocGPUMemUMA",    // PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES
+                "MemoryUsageDmaBufImport");     // PVRSRV_PROCESS_STAT_TYPE_DMA_BUF_IMPORT
 
        OSLockAcquire(g_psLinkedListLock);
 
@@ -2331,13 +2330,14 @@ int RawProcessStatsPrintElements(OSDI_IMPL_ENTRY *psEntry, void *pvData)
                if (psProcessStats->pid != PVR_SYS_ALLOC_PID)
                {
                        DIPrintf(psEntry,
-                                "%d,%d,%d,%d,%d,%d\n",
+                                "%d,%d,%d,%d,%d,%d,%d\n",
                                 psProcessStats->pid,
                                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_KMALLOC],
                                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_UMA],
                                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_PAGES_PT_LMA],
                                 psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_LMA_PAGES],
-                                psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES]);
+                                psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_ALLOC_UMA_PAGES],
+                                psProcessStats->i32StatValue[PVRSRV_PROCESS_STAT_TYPE_DMA_BUF_IMPORT]);
                }
 
                psProcessStats = psProcessStats->psNext;
@@ -2807,17 +2807,14 @@ ProcessStatsPrintElements(OSDI_IMPL_ENTRY *psEntry,
 #if defined(PVRSRV_ENABLE_CACHEOP_STATS)
 void
 PVRSRVStatsUpdateCacheOpStats(PVRSRV_CACHE_OP uiCacheOp,
-                                                       IMG_UINT32 ui32OpSeqNum,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                                                        IMG_DEV_VIRTADDR sDevVAddr,
                                                        IMG_DEV_PHYADDR sDevPAddr,
-                                                       IMG_UINT32 eFenceOpType,
 #endif
                                                        IMG_DEVMEM_SIZE_T uiOffset,
                                                        IMG_DEVMEM_SIZE_T uiSize,
                                                        IMG_UINT64 ui64ExecuteTime,
                                                        IMG_BOOL bUserModeFlush,
-                                                       IMG_BOOL bIsFence,
                                                        IMG_PID ownerPid)
 {
        IMG_PID                           currentPid = (ownerPid!=0)?ownerPid:OSGetCurrentClientProcessIDKM();
@@ -2849,14 +2846,11 @@ PVRSRVStatsUpdateCacheOpStats(PVRSRV_CACHE_OP uiCacheOp,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                psProcessStats->asCacheOp[Idx].sDevVAddr = sDevVAddr;
                psProcessStats->asCacheOp[Idx].sDevPAddr = sDevPAddr;
-               psProcessStats->asCacheOp[Idx].eFenceOpType = eFenceOpType;
 #endif
                psProcessStats->asCacheOp[Idx].uiOffset = uiOffset;
                psProcessStats->asCacheOp[Idx].uiSize = uiSize;
                psProcessStats->asCacheOp[Idx].bUserModeFlush = bUserModeFlush;
                psProcessStats->asCacheOp[Idx].ui64ExecuteTime = ui64ExecuteTime;
-               psProcessStats->asCacheOp[Idx].ui32OpSeqNum = ui32OpSeqNum;
-               psProcessStats->asCacheOp[Idx].bIsFence = bIsFence;
 
                OSLockRelease(psProcessStats->hLock);
        }
@@ -2879,18 +2873,14 @@ CacheOpStatsPrintElements(OSDI_IMPL_ENTRY *psEntry,
 
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
        #define CACHEOP_RI_PRINTF_HEADER \
-               "%-10s %-10s %-5s %-16s %-16s %-10s %-10s %-12s %-12s\n"
-       #define CACHEOP_RI_PRINTF_FENCE  \
-               "%-10s %-10s %-5s %-16s %-16s %-10s %-10s %-12llu 0x%-10x\n"
+               "%-10s %-10s %-5s %-16s %-16s %-10s %-10s %-12s\n"
        #define CACHEOP_RI_PRINTF               \
-               "%-10s %-10s %-5s 0x%-14llx 0x%-14llx 0x%-8llx 0x%-8llx %-12llu 0x%-10x\n"
+               "%-10s %-10s %-5s 0x%-14llx 0x%-14llx 0x%-8llx 0x%-8llx %-12llu\n"
 #else
        #define CACHEOP_PRINTF_HEADER   \
-               "%-10s %-10s %-5s %-10s %-10s %-12s %-12s\n"
-       #define CACHEOP_PRINTF_FENCE     \
-               "%-10s %-10s %-5s %-10s %-10s %-12llu 0x%-10x\n"
+               "%-10s %-10s %-5s %-10s %-10s %-12s\n"
        #define CACHEOP_PRINTF                  \
-               "%-10s %-10s %-5s 0x%-8llx 0x%-8llx %-12llu 0x%-10x\n"
+               "%-10s %-10s %-5s 0x%-8llx 0x%-8llx %-12llu\n"
 #endif
 
        DIPrintf(psEntry, "PID %u\n", psProcessStats->pid);
@@ -2911,8 +2901,7 @@ CacheOpStatsPrintElements(OSDI_IMPL_ENTRY *psEntry,
 #endif
                                        "Offset",
                                        "Size",
-                                       "Time (us)",
-                                       "SeqNo");
+                                       "Time (us)");
 
        /* Take a snapshot of write index, read backwards in buffer
           and wrap round at boundary */
@@ -2921,111 +2910,47 @@ CacheOpStatsPrintElements(OSDI_IMPL_ENTRY *psEntry,
                 i32ReadIdx != i32WriteIdx;
                 i32ReadIdx = DECREMENT_CACHEOP_STAT_IDX_WRAP(i32ReadIdx))
        {
-               IMG_UINT64 ui64ExecuteTime;
+               IMG_UINT64 ui64ExecuteTime = psProcessStats->asCacheOp[i32ReadIdx].ui64ExecuteTime;
+               IMG_DEVMEM_SIZE_T ui64NumOfPages = psProcessStats->asCacheOp[i32ReadIdx].uiSize >> OSGetPageShift();
 
-               if (! psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum)
+               if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
                {
-                       break;
+                       pszFlushType = "RBF.Fast";
                }
-
-               ui64ExecuteTime = psProcessStats->asCacheOp[i32ReadIdx].ui64ExecuteTime;
-
-               if (psProcessStats->asCacheOp[i32ReadIdx].bIsFence)
+               else
                {
-                       IMG_CHAR *pszFenceType = "";
-                       pszCacheOpType = "Fence";
-
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                       switch (psProcessStats->asCacheOp[i32ReadIdx].eFenceOpType)
-                       {
-                               case RGXFWIF_DM_GP:
-                                       pszFenceType = "GP";
-                                       break;
-
-                               case RGXFWIF_DM_TDM:
-                                       /* Also case RGXFWIF_DM_2D: */
-                                       pszFenceType = "TDM/2D";
-                                       break;
-
-                               case RGXFWIF_DM_GEOM:
-                                       pszFenceType = "GEOM";
-                                       break;
-
-                               case RGXFWIF_DM_3D:
-                                       pszFenceType = "3D";
-                                       break;
-
-                               case RGXFWIF_DM_CDM:
-                                       pszFenceType = "CDM";
-                                       break;
-
-                               default:
-                                       PVR_ASSERT(0);
-                                       break;
-                       }
-#endif
+                       pszFlushType = "RBF.Slow";
+               }
 
-                       DIPrintf(psEntry,
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       CACHEOP_RI_PRINTF_FENCE,
-#else
-                                                       CACHEOP_PRINTF_FENCE,
-#endif
-                                                       pszCacheOpType,
-                                                       pszFenceType,
-                                                       "",
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
-                                                       "",
-                                                       "",
-#endif
-                                                       "",
-                                                       "",
-                                                       ui64ExecuteTime,
-                                                       psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum);
+               if (psProcessStats->asCacheOp[i32ReadIdx].bUserModeFlush)
+               {
+                       pszFlushMode = "UM";
                }
                else
                {
-                       IMG_DEVMEM_SIZE_T ui64NumOfPages;
-
-                       ui64NumOfPages = psProcessStats->asCacheOp[i32ReadIdx].uiSize >> OSGetPageShift();
-                       if (ui64NumOfPages <= PMR_MAX_TRANSLATION_STACK_ALLOC)
-                       {
-                               pszFlushType = "RBF.Fast";
-                       }
-                       else
-                       {
-                               pszFlushType = "RBF.Slow";
-                       }
-
-                       if (psProcessStats->asCacheOp[i32ReadIdx].bUserModeFlush)
-                       {
-                               pszFlushMode = "UM";
-                       }
-                       else
-                       {
-                               pszFlushMode = "KM";
-                       }
+                       pszFlushMode = "KM";
+               }
 
-                       switch (psProcessStats->asCacheOp[i32ReadIdx].uiCacheOp)
-                       {
-                               case PVRSRV_CACHE_OP_NONE:
-                                       pszCacheOpType = "None";
-                                       break;
-                               case PVRSRV_CACHE_OP_CLEAN:
-                                       pszCacheOpType = "Clean";
-                                       break;
-                               case PVRSRV_CACHE_OP_INVALIDATE:
-                                       pszCacheOpType = "Invalidate";
-                                       break;
-                               case PVRSRV_CACHE_OP_FLUSH:
-                                       pszCacheOpType = "Flush";
-                                       break;
-                               default:
-                                       pszCacheOpType = "Unknown";
-                                       break;
-                       }
+               switch (psProcessStats->asCacheOp[i32ReadIdx].uiCacheOp)
+               {
+                       case PVRSRV_CACHE_OP_NONE:
+                               pszCacheOpType = "None";
+                               break;
+                       case PVRSRV_CACHE_OP_CLEAN:
+                               pszCacheOpType = "Clean";
+                               break;
+                       case PVRSRV_CACHE_OP_INVALIDATE:
+                               pszCacheOpType = "Invalidate";
+                               break;
+                       case PVRSRV_CACHE_OP_FLUSH:
+                               pszCacheOpType = "Flush";
+                               break;
+                       default:
+                               pszCacheOpType = "Unknown";
+                               break;
+               }
 
-                       DIPrintf(psEntry,
+               DIPrintf(psEntry,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                                                        CACHEOP_RI_PRINTF,
 #else
@@ -3040,10 +2965,9 @@ CacheOpStatsPrintElements(OSDI_IMPL_ENTRY *psEntry,
 #endif
                                                        psProcessStats->asCacheOp[i32ReadIdx].uiOffset,
                                                        psProcessStats->asCacheOp[i32ReadIdx].uiSize,
-                                                       ui64ExecuteTime,
-                                                       psProcessStats->asCacheOp[i32ReadIdx].ui32OpSeqNum);
+                                                       ui64ExecuteTime);
                }
-       }
+
 } /* CacheOpStatsPrintElements */
 #endif
 
@@ -3257,7 +3181,7 @@ int GlobalStatsPrintElements(OSDI_IMPL_ENTRY *psEntry, void *pvData)
        {
                if (OSStringNCompare(pszDriverStatType[ui32StatNumber], "", 1) != 0)
                {
-                       DIPrintf(psEntry, "%-34s%10d\n",
+                       DIPrintf(psEntry, "%-34s%12llu\n",
                                    pszDriverStatType[ui32StatNumber],
                                    GET_GLOBAL_STAT_VALUE(ui32StatNumber));
                }
index 6175fbf..3bc2beb 100644 (file)
@@ -217,59 +217,78 @@ PVRSRVCheckStatus(PVRSRV_CMDCOMP_HANDLE hCmdCompCallerHandle)
 Debug Notifier Interface
 */ /**************************************************************************/
 
+/* Lockdep sees both locks as the same class due to same struct used thus warns
+ * about a possible deadlock (false positive),
+ * using nested api we can supply separate Class'
+ * */
+#define DN_LOCKCLASS_DRIVER 0
+#define DN_LOCKCLASS_DEVICE 1
+
 typedef struct DEBUG_REQUEST_ENTRY_TAG
 {
-       IMG_UINT32              ui32RequesterID;
-       DLLIST_NODE             sListHead;
+       IMG_UINT32      ui32RequesterID;
+       DLLIST_NODE     sListHead;
 } DEBUG_REQUEST_ENTRY;
 
 typedef struct DEBUG_REQUEST_TABLE_TAG
 {
-       POSWR_LOCK                              hLock;
-       IMG_UINT32                              ui32RequestCount;
-       DEBUG_REQUEST_ENTRY             asEntry[1];
+       POSWR_LOCK              hLock;
+       DEBUG_REQUEST_ENTRY     asEntry[1];
 } DEBUG_REQUEST_TABLE;
 
 typedef struct DEBUG_REQUEST_NOTIFY_TAG
 {
-       PVRSRV_DEVICE_NODE              *psDevNode;
-       PVRSRV_DBGREQ_HANDLE    hDbgRequestHandle;
-       PFN_DBGREQ_NOTIFY               pfnDbgRequestNotify;
-       IMG_UINT32                              ui32RequesterID;
-       DLLIST_NODE                             sListNode;
+       IMG_HANDLE              hDebugTable;
+       PVRSRV_DBGREQ_HANDLE    hDbgRequestHandle;
+       PFN_DBGREQ_NOTIFY       pfnDbgRequestNotify;
+       IMG_UINT32              ui32RequesterID;
+       DLLIST_NODE             sListNode;
 } DEBUG_REQUEST_NOTIFY;
 
-
-PVRSRV_ERROR
-PVRSRVRegisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode,
-                                               const IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length)
+static DEBUG_REQUEST_TABLE *g_psDriverDebugTable;
+
+static const IMG_UINT32 g_aui32DebugOrderTable[] = {
+       DEBUG_REQUEST_SRV,
+       DEBUG_REQUEST_RGX,
+       DEBUG_REQUEST_SYS,
+       DEBUG_REQUEST_APPHINT,
+       DEBUG_REQUEST_HTB,
+       DEBUG_REQUEST_DC,
+       DEBUG_REQUEST_SYNCCHECKPOINT,
+       DEBUG_REQUEST_SYNCTRACKING,
+       DEBUG_REQUEST_ANDROIDSYNC,
+       DEBUG_REQUEST_FALLBACKSYNC,
+       DEBUG_REQUEST_LINUXFENCE
+};
+static const IMG_UINT32 g_ui32DebugOrderTableReqCount = ARRAY_SIZE(g_aui32DebugOrderTable);
+
+static PVRSRV_ERROR
+_RegisterDebugTableI(DEBUG_REQUEST_TABLE **ppsDebugTable)
 {
        DEBUG_REQUEST_TABLE *psDebugTable;
        IMG_UINT32 i;
        PVRSRV_ERROR eError;
 
-       if (psDevNode->hDebugTable)
+       if (*ppsDebugTable)
        {
                return PVRSRV_ERROR_DBGTABLE_ALREADY_REGISTERED;
        }
 
        psDebugTable = OSAllocMem(sizeof(DEBUG_REQUEST_TABLE) +
-                                                         (sizeof(DEBUG_REQUEST_ENTRY) * (ui32Length-1)));
+                                                         (sizeof(DEBUG_REQUEST_ENTRY) * (g_ui32DebugOrderTableReqCount-1)));
        PVR_RETURN_IF_NOMEM(psDebugTable);
 
        eError = OSWRLockCreate(&psDebugTable->hLock);
        PVR_GOTO_IF_ERROR(eError, ErrorFreeDebugTable);
 
-       psDebugTable->ui32RequestCount = ui32Length;
-
        /* Init the list heads */
-       for (i = 0; i < ui32Length; i++)
+       for (i = 0; i < g_ui32DebugOrderTableReqCount; i++)
        {
-               psDebugTable->asEntry[i].ui32RequesterID = paui32Table[i];
+               psDebugTable->asEntry[i].ui32RequesterID = g_aui32DebugOrderTable[i];
                dllist_init(&psDebugTable->asEntry[i].sListHead);
        }
 
-       psDevNode->hDebugTable = (IMG_HANDLE *) psDebugTable;
+       *ppsDebugTable = psDebugTable;
 
        return PVRSRV_OK;
 
@@ -279,17 +298,28 @@ ErrorFreeDebugTable:
        return eError;
 }
 
-void
-PVRSRVUnregisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
+PVRSRV_ERROR
+PVRSRVRegisterDeviceDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
+{
+       return _RegisterDebugTableI((DEBUG_REQUEST_TABLE**)&psDevNode->hDebugTable);
+}
+
+PVRSRV_ERROR
+PVRSRVRegisterDriverDbgTable(void)
+{
+       return _RegisterDebugTableI(&g_psDriverDebugTable);
+}
+
+static void _UnregisterDbgTableI(DEBUG_REQUEST_TABLE **ppsDebugTable)
 {
        DEBUG_REQUEST_TABLE *psDebugTable;
        IMG_UINT32 i;
 
-       PVR_ASSERT(psDevNode->hDebugTable);
-       psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
-       psDevNode->hDebugTable = NULL;
+       PVR_ASSERT(*ppsDebugTable);
+       psDebugTable = *ppsDebugTable;
+       *ppsDebugTable = NULL;
 
-       for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+       for (i = 0; i < g_ui32DebugOrderTableReqCount; i++)
        {
                if (!dllist_is_empty(&psDebugTable->asEntry[i].sListHead))
                {
@@ -304,34 +334,43 @@ PVRSRVUnregisterDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
        OSFreeMem(psDebugTable);
 }
 
-PVRSRV_ERROR
-PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
-                                                          PVRSRV_DEVICE_NODE *psDevNode,
-                                                          PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
-                                                          IMG_UINT32 ui32RequesterID,
-                                                          PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
+void
+PVRSRVUnregisterDeviceDbgTable(PVRSRV_DEVICE_NODE *psDevNode)
+{
+       _UnregisterDbgTableI((DEBUG_REQUEST_TABLE**)&psDevNode->hDebugTable);
+       PVR_ASSERT(!psDevNode->hDebugTable);
+}
+
+void
+PVRSRVUnregisterDriverDbgTable(void)
+{
+       _UnregisterDbgTableI(&g_psDriverDebugTable);
+       PVR_ASSERT(!g_psDriverDebugTable);
+}
+
+static PVRSRV_ERROR
+_RegisterDbgRequestNotifyI(IMG_HANDLE *phNotify,
+                                  DEBUG_REQUEST_TABLE *psDebugTable,
+                                  PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+                                  IMG_UINT32 ui32RequesterID,
+                                  PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
 {
-       DEBUG_REQUEST_TABLE *psDebugTable;
        DEBUG_REQUEST_NOTIFY *psNotify;
        PDLLIST_NODE psHead = NULL;
        IMG_UINT32 i;
        PVRSRV_ERROR eError;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(phNotify, "phNotify");
-       PVR_LOG_RETURN_IF_INVALID_PARAM(psDevNode, "psDevNode");
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psDebugTable, "psDebugTable");
        PVR_LOG_RETURN_IF_INVALID_PARAM(pfnDbgRequestNotify, "pfnDbRequestNotify");
 
-       psDebugTable = (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
-
-       PVR_ASSERT(psDebugTable);
-
        /* NoStats used since this may be called outside of the register/de-register
         * process calls which track memory use. */
        psNotify = OSAllocMemNoStats(sizeof(*psNotify));
        PVR_LOG_RETURN_IF_NOMEM(psNotify, "psNotify");
 
        /* Set-up the notify data */
-       psNotify->psDevNode = psDevNode;
+       psNotify->hDebugTable = psDebugTable;
        psNotify->hDbgRequestHandle = hDbgRequestHandle;
        psNotify->pfnDbgRequestNotify = pfnDbgRequestNotify;
        psNotify->ui32RequesterID = ui32RequesterID;
@@ -340,7 +379,7 @@ PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
        OSWRLockAcquireWrite(psDebugTable->hLock);
 
        /* Find which list to add it to */
-       for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+       for (i = 0; i < g_ui32DebugOrderTableReqCount; i++)
        {
                if (psDebugTable->asEntry[i].ui32RequesterID == ui32RequesterID)
                {
@@ -369,28 +408,70 @@ ErrorReleaseLock:
 }
 
 PVRSRV_ERROR
+PVRSRVRegisterDeviceDbgRequestNotify(IMG_HANDLE *phNotify,
+                                        PVRSRV_DEVICE_NODE *psDevNode,
+                                        PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+                                        IMG_UINT32 ui32RequesterID,
+                                        PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
+{
+       PVR_LOG_RETURN_IF_INVALID_PARAM(psDevNode, "psDevNode");
+       if (!psDevNode->hDebugTable)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: psDevNode->hDebugTable not yet initialised!",
+                                __func__));
+               return PVRSRV_ERROR_NOT_INITIALISED;
+       }
+
+       return _RegisterDbgRequestNotifyI(phNotify,
+                                                 (DEBUG_REQUEST_TABLE *)psDevNode->hDebugTable,
+                                                 pfnDbgRequestNotify,
+                                                 ui32RequesterID,
+                                                 hDbgRequestHandle);
+}
+
+PVRSRV_ERROR
+PVRSRVRegisterDriverDbgRequestNotify(IMG_HANDLE *phNotify,
+                                        PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+                                        IMG_UINT32 ui32RequesterID,
+                                        PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
+{
+       if (!g_psDriverDebugTable)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: g_psDriverDebugTable not yet initialised!",
+                                __func__));
+               return PVRSRV_ERROR_NOT_INITIALISED;
+       }
+
+       return _RegisterDbgRequestNotifyI(phNotify,
+                                                 g_psDriverDebugTable,
+                                                 pfnDbgRequestNotify,
+                                                 ui32RequesterID,
+                                                 hDbgRequestHandle);
+}
+
+PVRSRV_ERROR
 SOPvrDbgRequestNotifyRegister(IMG_HANDLE *phNotify,
                                                          PVRSRV_DEVICE_NODE *psDevNode,
                                                          PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
                                                          IMG_UINT32 ui32RequesterID,
                                                          PVRSRV_DBGREQ_HANDLE hDbgRequestHandle)
 {
-       return PVRSRVRegisterDbgRequestNotify(phNotify,
+       return PVRSRVRegisterDeviceDbgRequestNotify(phNotify,
                        psDevNode,
                        pfnDbgRequestNotify,
                        ui32RequesterID,
                        hDbgRequestHandle);
 }
 
-PVRSRV_ERROR
-PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
+static PVRSRV_ERROR
+_UnregisterDbgRequestNotify(IMG_HANDLE hNotify)
 {
        DEBUG_REQUEST_NOTIFY *psNotify = (DEBUG_REQUEST_NOTIFY *) hNotify;
        DEBUG_REQUEST_TABLE *psDebugTable;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(psNotify, "psNotify");
 
-       psDebugTable = (DEBUG_REQUEST_TABLE *) psNotify->psDevNode->hDebugTable;
+       psDebugTable = (DEBUG_REQUEST_TABLE *) psNotify->hDebugTable;
 
        OSWRLockAcquireWrite(psDebugTable->hLock);
        dllist_remove_node(&psNotify->sListNode);
@@ -402,9 +483,21 @@ PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify)
 }
 
 PVRSRV_ERROR
+PVRSRVUnregisterDeviceDbgRequestNotify(IMG_HANDLE hNotify)
+{
+       return _UnregisterDbgRequestNotify(hNotify);
+}
+
+PVRSRV_ERROR
+PVRSRVUnregisterDriverDbgRequestNotify(IMG_HANDLE hNotify)
+{
+       return _UnregisterDbgRequestNotify(hNotify);
+}
+
+PVRSRV_ERROR
 SOPvrDbgRequestNotifyUnregister(IMG_HANDLE hNotify)
 {
-       return PVRSRVUnregisterDbgRequestNotify(hNotify);
+       return _UnregisterDbgRequestNotify(hNotify);
 }
 
 void
@@ -416,6 +509,8 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        DEBUG_REQUEST_TABLE *psDebugTable =
                (DEBUG_REQUEST_TABLE *) psDevNode->hDebugTable;
+       DEBUG_REQUEST_TABLE *psDriverDebugTable =
+               (DEBUG_REQUEST_TABLE *) g_psDriverDebugTable;
        static const IMG_CHAR *apszVerbosityTable[] = { "Low", "Medium", "High" };
        const IMG_CHAR *szVerbosityLevel;
        const IMG_CHAR *Bit32 = "32 Bit", *Bit64 = "64 Bit";
@@ -425,8 +520,7 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
                      "Incorrect number of verbosity levels");
 
        PVR_ASSERT(psDebugTable);
-
-       OSWRLockAcquireRead(psDebugTable->hLock);
+       PVR_ASSERT(psDriverDebugTable);
 
        if (ui32VerbLevel < ARRAY_SIZE(apszVerbosityTable))
        {
@@ -441,7 +535,12 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
        PVR_DUMPDEBUG_LOG("------------[ PVR DBG: START (%s) ]------------",
                          szVerbosityLevel);
 
-       OSDumpVersionInfo(pfnDumpDebugPrintf, pvDumpDebugFile);
+#if defined(RGX_IRQ_HYPERV_HANDLER)
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+#endif
+       {
+               OSDumpVersionInfo(pfnDumpDebugPrintf, pvDumpDebugFile);
+       }
 
        PVR_DUMPDEBUG_LOG("DDK info: %s (%s) %s",
                          PVRVERSION_STRING, PVR_BUILD_TYPE, PVR_BUILD_DIR);
@@ -469,7 +568,7 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
        PVR_DUMPDEBUG_LOG("Server Errors: %d",
                  PVRSRV_KM_ERRORS);
 
-       PVRSRVConnectionDebugNotify(pfnDumpDebugPrintf, pvDumpDebugFile);
+       PVRSRVConnectionDebugNotify(psDevNode, pfnDumpDebugPrintf, pvDumpDebugFile);
 
        PVR_DUMPDEBUG_LOG("------[ Driver Info ]------");
 
@@ -492,10 +591,11 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
                {
                        PVR_DUMPDEBUG_LOG("UM Connected Clients Arch: %s and %s", Bit64, Bit32);
 
-               }else
+               }
+               else
                {
                        PVR_DUMPDEBUG_LOG("UM Connected Clients: %s",
-                                         (psPVRSRVData->sDriverInfo.ui8UMSupportedArch & BUILD_ARCH_64BIT) ? Bit64 : Bit32);
+                                        (psPVRSRVData->sDriverInfo.ui8UMSupportedArch & BUILD_ARCH_64BIT) ? Bit64 : Bit32);
                }
        }
 
@@ -504,13 +604,27 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
 
        PVR_DUMPDEBUG_LOG("Window system: %s", (IS_DECLARED(WINDOW_SYSTEM)) ? (WINDOW_SYSTEM) : "Not declared");
 
-       /* For each requester */
-       for (i = 0; i < psDebugTable->ui32RequestCount; i++)
+       /* Driver debug table */
+       OSWRLockAcquireReadNested(psDriverDebugTable->hLock, DN_LOCKCLASS_DRIVER);
+       /* Device debug table*/
+       OSWRLockAcquireReadNested(psDebugTable->hLock, DN_LOCKCLASS_DEVICE);
+
+       /* For each requester in Driver and Device table */
+       for (i = 0; i < g_ui32DebugOrderTableReqCount; i++)
        {
                DLLIST_NODE *psNode;
                DLLIST_NODE *psNext;
 
                /* For each notifier on this requestor */
+               dllist_foreach_node(&psDriverDebugTable->asEntry[i].sListHead, psNode, psNext)
+               {
+                       DEBUG_REQUEST_NOTIFY *psNotify =
+                               IMG_CONTAINER_OF(psNode, DEBUG_REQUEST_NOTIFY, sListNode);
+                       psNotify->pfnDbgRequestNotify(psNotify->hDbgRequestHandle, ui32VerbLevel,
+                                                         pfnDumpDebugPrintf, pvDumpDebugFile);
+               }
+
+               /* For each notifier on this requestor */
                dllist_foreach_node(&psDebugTable->asEntry[i].sListHead, psNode, psNext)
                {
                        DEBUG_REQUEST_NOTIFY *psNotify =
@@ -520,8 +634,10 @@ PVRSRVDebugRequest(PVRSRV_DEVICE_NODE *psDevNode,
                }
        }
 
-       PVR_DUMPDEBUG_LOG("------------[ PVR DBG: END ]------------");
        OSWRLockReleaseRead(psDebugTable->hLock);
+       OSWRLockReleaseRead(psDriverDebugTable->hLock);
+
+       PVR_DUMPDEBUG_LOG("------------[ PVR DBG: END ]------------");
 
        if (!pfnDumpDebugPrintf)
        {
index 8a88230..b866907 100644 (file)
@@ -93,7 +93,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #if defined(MULTI_DEVICE_BRINGUP)
 #define MULTI_DEVICE_BRINGUP_DPF(msg, ...) PVR_DPF((PVR_DBG_MESSAGE, msg, __VA_ARGS__))
 #else
-#define MULTI_DEVICE_BRINGUP_DPF(msg, ...)
+#define MULTI_DEVICE_BRINGUP_DPF(msg, ...) PVR_DPF((PVR_DBG_MESSAGE, msg, __VA_ARGS__))
 #endif
 
 #if defined(SUPPORT_RGX)
@@ -140,6 +140,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "virt_validation_defs.h"
 #endif
 
+#if defined(__linux__)
+#include "km_apphint.h"
+#endif /* defined(__linux__) */
+
 #if defined(PVRSRV_SERVER_THREADS_INDEFINITE_SLEEP)
 #define INFINITE_SLEEP_TIMEOUT 0ULL
 #endif
@@ -158,8 +162,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /*! When unloading try a few times to free everything remaining on the list */
 #define CLEANUP_THREAD_UNLOAD_RETRY 4
 
-#define PVRSRV_PROC_HANDLE_BASE_INIT 10
-
 #define PVRSRV_TL_CTLR_STREAM_SIZE 4096
 
 static PVRSRV_DATA     *gpsPVRSRVData;
@@ -168,18 +170,6 @@ static IMG_UINT32 g_ui32InitFlags;
 /* mark which parts of Services were initialised */
 #define                INIT_DATA_ENABLE_PDUMPINIT      0x1U
 
-static IMG_UINT32 g_aui32DebugOrderTable[] = {
-       DEBUG_REQUEST_SYS,
-       DEBUG_REQUEST_APPHINT,
-       DEBUG_REQUEST_HTB,
-       DEBUG_REQUEST_DC,
-       DEBUG_REQUEST_SYNCCHECKPOINT,
-       DEBUG_REQUEST_SYNCTRACKING,
-       DEBUG_REQUEST_ANDROIDSYNC,
-       DEBUG_REQUEST_FALLBACKSYNC,
-       DEBUG_REQUEST_LINUXFENCE
-};
-
 /* Callback to dump info of cleanup thread in debug_dump */
 static void CleanupThreadDumpInfo(DUMPDEBUG_PRINTF_FUNC* pfnDumpDebugPrintf,
                                   void *pvDumpDebugFile)
@@ -187,8 +177,11 @@ static void CleanupThreadDumpInfo(DUMPDEBUG_PRINTF_FUNC* pfnDumpDebugPrintf,
        PVRSRV_DATA *psPVRSRVData;
        psPVRSRVData = PVRSRVGetPVRSRVData();
 
-       PVR_DUMPDEBUG_LOG("    Number of deferred cleanup items : %u",
-                         OSAtomicRead(&psPVRSRVData->i32NumCleanupItems));
+       PVR_DUMPDEBUG_LOG("    Number of deferred cleanup items Queued : %u",
+                             OSAtomicRead(&psPVRSRVData->i32NumCleanupItemsQueued));
+       PVR_DUMPDEBUG_LOG("    Number of deferred cleanup items dropped after "
+                             "retry limit reached : %u",
+                             OSAtomicRead(&psPVRSRVData->i32NumCleanupItemsNotCompleted));
 }
 
 /* Add work to the cleanup thread work list.
@@ -231,7 +224,7 @@ void PVRSRVCleanupThreadAddWork(PVRSRV_CLEANUP_THREAD_WORK *psData)
                dllist_add_to_tail(&psPVRSRVData->sCleanupThreadWorkList, &psData->sNode);
                OSSpinLockRelease(psPVRSRVData->hCleanupThreadWorkListLock, uiFlags);
 
-               OSAtomicIncrement(&psPVRSRVData->i32NumCleanupItems);
+               OSAtomicIncrement(&psPVRSRVData->i32NumCleanupItemsQueued);
 
                /* signal the cleanup thread to ensure this item gets processed */
                eError = OSEventObjectSignal(psPVRSRVData->hCleanupEventObject);
@@ -332,11 +325,14 @@ static IMG_BOOL _CleanupThreadProcessWorkList(PVRSRV_DATA *psPVRSRVData,
                                                                "(callback " IMG_PFN_FMTSPEC "). "
                                                                "Retry limit reached",
                                                                pfnFree));
+                                       OSAtomicDecrement(&psPVRSRVData->i32NumCleanupItemsQueued);
+                                       OSAtomicIncrement(&psPVRSRVData->i32NumCleanupItemsNotCompleted);
+
                                }
                        }
                        else
                        {
-                               OSAtomicDecrement(&psPVRSRVData->i32NumCleanupItems);
+                               OSAtomicDecrement(&psPVRSRVData->i32NumCleanupItemsQueued);
                        }
                }
        } while ((psNodeIter != NULL) && (psNodeIter != psNodeLast));
@@ -382,7 +378,9 @@ static void CleanupThread(void *pvData)
 
        /* Store the process id (pid) of the clean-up thread */
        psPVRSRVData->cleanupThreadPid = OSGetCurrentProcessID();
-       OSAtomicWrite(&psPVRSRVData->i32NumCleanupItems, 0);
+       psPVRSRVData->cleanupThreadTid = OSGetCurrentThreadID();
+       OSAtomicWrite(&psPVRSRVData->i32NumCleanupItemsQueued, 0);
+       OSAtomicWrite(&psPVRSRVData->i32NumCleanupItemsNotCompleted, 0);
 
        PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread starting... "));
 
@@ -458,6 +456,16 @@ static void CleanupThread(void *pvData)
        PVR_DPF((CLEANUP_DPFL, "CleanupThread: thread ending... "));
 }
 
+IMG_PID PVRSRVCleanupThreadGetPid(void)
+{
+       return gpsPVRSRVData->cleanupThreadPid;
+}
+
+uintptr_t PVRSRVCleanupThreadGetTid(void)
+{
+       return gpsPVRSRVData->cleanupThreadTid;
+}
+
 static void DevicesWatchdogThread_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                                                          va_list va)
 {
@@ -524,8 +532,6 @@ static void HWPerfPeriodicHostEventsThread(void *pvData)
        PVRSRV_DATA *psPVRSRVData = pvData;
        IMG_HANDLE hOSEvent;
        PVRSRV_ERROR eError;
-       IMG_BOOL bHostStreamIsOpenForReading;
-       PVRSRV_RGXDEV_INFO *psDevInfo;
 
        eError = OSEventObjectOpen(psPVRSRVData->hHWPerfHostPeriodicEvObj, &hOSEvent);
        PVR_LOG_RETURN_VOID_IF_ERROR(eError, "OSEventObjectOpen");
@@ -537,6 +543,9 @@ static void HWPerfPeriodicHostEventsThread(void *pvData)
        while (!psPVRSRVData->bUnload && !psPVRSRVData->bHWPerfHostThreadStop)
 #endif
        {
+               PVRSRV_DEVICE_NODE *psDeviceNode;
+               IMG_BOOL bInfiniteSleep = IMG_TRUE;
+
                eError = OSEventObjectWaitKernel(hOSEvent, (IMG_UINT64)psPVRSRVData->ui32HWPerfHostThreadTimeout * 1000);
                if (eError == PVRSRV_OK && (psPVRSRVData->bUnload || psPVRSRVData->bHWPerfHostThreadStop))
                {
@@ -544,25 +553,41 @@ static void HWPerfPeriodicHostEventsThread(void *pvData)
                        break;
                }
 
-               psDevInfo = (PVRSRV_RGXDEV_INFO*)psPVRSRVData->psDeviceNodeList->pvDevice;
+               for (psDeviceNode = psPVRSRVData->psDeviceNodeList;
+                    psDeviceNode != NULL;
+                    psDeviceNode = psDeviceNode->psNext)
+               {
+                       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
-               /* Check if the HWPerf host stream is open for reading before writing a packet,
-                  this covers cases where the event filter is not zeroed before a reader disconnects. */
-               bHostStreamIsOpenForReading = TLStreamIsOpenForReading(psDevInfo->hHWPerfHostStream);
+                       /* If the psDevInfo or hHWPerfHostStream are NULL it most
+                        * likely means that this device or stream has not been
+                        * initialised yet, so just skip */
+                       if (psDevInfo == NULL || psDevInfo->hHWPerfHostStream == NULL)
+                       {
+                               continue;
+                       }
 
-               if (bHostStreamIsOpenForReading)
-               {
+                       /* Check if the HWPerf host stream is open for reading before writing
+                        * a packet, this covers cases where the event filter is not zeroed
+                        * before a reader disconnects. */
+                       if (TLStreamIsOpenForReading(psDevInfo->hHWPerfHostStream))
+                       {
+                               /* As long as any of the streams is opened don't go into
+                                * indefinite sleep. */
+                               bInfiniteSleep = IMG_FALSE;
 #if defined(SUPPORT_RGX)
-                       RGXSRV_HWPERF_HOST_INFO(psPVRSRVData->psDeviceNodeList->pvDevice, RGX_HWPERF_INFO_EV_MEM_USAGE);
+                               RGXSRV_HWPERF_HOST_INFO(psDevInfo, RGX_HWPERF_INFO_EV_MEM_USAGE);
 #endif
+                       }
                }
-               else
+
+               if (bInfiniteSleep)
                {
 #if defined(PVRSRV_SERVER_THREADS_INDEFINITE_SLEEP)
                        psPVRSRVData->ui32HWPerfHostThreadTimeout = INFINITE_SLEEP_TIMEOUT;
 #else
-                       /* This 'long' timeout is temporary until functionality is added to services to put a thread to sleep indefinitely. */
-                       psPVRSRVData->ui32HWPerfHostThreadTimeout = 60 * 60 * 8 * 1000; // 8 hours
+                       /* Use an 8 hour timeout if indefinite sleep is not supported. */
+                       psPVRSRVData->ui32HWPerfHostThreadTimeout = 60 * 60 * 8 * 1000;
 #endif
                }
        }
@@ -835,8 +860,14 @@ static void DevicesWatchdogThread(void *pvData)
                        bTimeOut = IMG_TRUE;
                }
 
+               OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+               List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
+                                                  DevicesWatchdogThread_ForEachVaCb,
+                                                  &ePreviousHealthStatus,
+                                                  bTimeOut);
                bPwrIsOn = List_PVRSRV_DEVICE_NODE_IMG_BOOL_Any(psPVRSRVData->psDeviceNodeList,
                                                                                                                PVRSRVIsDevicePowered);
+               OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
 
                if (bPwrIsOn || psPVRSRVData->ui32DevicesWatchdogPwrTrans)
                {
@@ -862,11 +893,6 @@ static void DevicesWatchdogThread(void *pvData)
                        }
                }
 
-               List_PVRSRV_DEVICE_NODE_ForEach_va(psPVRSRVData->psDeviceNodeList,
-                                                  DevicesWatchdogThread_ForEachVaCb,
-                                                  &ePreviousHealthStatus,
-                                                  bTimeOut);
-
 #endif /* defined(PVRSRV_SERVER_THREADS_INDEFINITE_SLEEP) */
        }
 
@@ -982,6 +1008,20 @@ static PVRSRV_ERROR PopulateInfoPageBridges(PVRSRV_DATA *psPVRSRVData)
        return PVRSRV_OK;
 }
 
+static void _ThreadsDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgRequestHandle,
+                                       IMG_UINT32 ui32VerbLevel,
+                                       DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile)
+{
+       PVR_UNREFERENCED_PARAMETER(hDbgRequestHandle);
+
+       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_HIGH))
+       {
+               PVR_DUMPDEBUG_LOG("------[ Server Thread Summary ]------");
+               OSThreadDumpInfo(pfnDumpDebugPrintf, pvDumpDebugFile);
+       }
+}
+
 PVRSRV_ERROR
 PVRSRVCommonDriverInit(void)
 {
@@ -1008,6 +1048,29 @@ PVRSRVCommonDriverInit(void)
                return PVRSRV_ERROR_ALREADY_EXISTS;
        }
 
+       /*
+        * Allocate the device-independent data
+        */
+       psPVRSRVData = OSAllocZMem(sizeof(*gpsPVRSRVData));
+       PVR_GOTO_IF_NOMEM(psPVRSRVData, eError, Error);
+
+       /* Now it is set up, point gpsPVRSRVData to the actual data */
+       gpsPVRSRVData = psPVRSRVData;
+
+       eError = OSWRLockCreate(&gpsPVRSRVData->hDeviceNodeListLock);
+       PVR_GOTO_IF_ERROR(eError, Error);
+
+       /* Register the driver context debug table */
+       eError = PVRSRVRegisterDriverDbgTable();
+       PVR_GOTO_IF_ERROR(eError, Error);
+
+       /* Register the Server Thread Debug notifier */
+       eError = PVRSRVRegisterDriverDbgRequestNotify(&gpsPVRSRVData->hThreadsDbgReqNotify,
+                                                         _ThreadsDebugRequestNotify,
+                                                         DEBUG_REQUEST_SRV,
+                                                         NULL);
+       PVR_GOTO_IF_ERROR(eError, Error);
+
        eError = DIInit();
        PVR_GOTO_IF_ERROR(eError, Error);
 
@@ -1036,16 +1099,7 @@ PVRSRVCommonDriverInit(void)
        eError = DevmemIntInit();
        PVR_GOTO_IF_ERROR(eError, Error);
 
-       /*
-        * Allocate the device-independent data
-        */
-       psPVRSRVData = OSAllocZMem(sizeof(*gpsPVRSRVData));
-       PVR_GOTO_IF_NOMEM(psPVRSRVData, eError, Error);
-
-       /* Now it is set up, point gpsPVRSRVData to the actual data */
-       gpsPVRSRVData = psPVRSRVData;
-
-       eError = DebugCommonInit();
+       eError = DebugCommonInitDriver();
        PVR_GOTO_IF_ERROR(eError, Error);
 
        eError = BridgeDispatcherInit();
@@ -1064,9 +1118,8 @@ PVRSRVCommonDriverInit(void)
 #endif
 
        ui32AppHintDefault = PVRSRV_APPHINT_ENABLEPAGEFAULTDEBUG;
-
        OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintBOOL(pvAppHintState, EnablePageFaultDebug,
+       OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, EnablePageFaultDebug,
                        &ui32AppHintDefault, &bEnablePageFaultDebug);
        OSFreeKMAppHintState(pvAppHintState);
 
@@ -1100,15 +1153,15 @@ PVRSRVCommonDriverInit(void)
 
        OSCreateKMAppHintState(&pvAppHintState);
        ui32AppHintDefault = PVRSRV_APPHINT_CLEANUPTHREADPRIORITY;
-       OSGetKMAppHintUINT32(pvAppHintState, CleanupThreadPriority,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, CleanupThreadPriority,
                             &ui32AppHintDefault, &ui32AppHintCleanupThreadPriority);
 
        ui32AppHintDefault = PVRSRV_APPHINT_WATCHDOGTHREADPRIORITY;
-       OSGetKMAppHintUINT32(pvAppHintState, WatchdogThreadPriority,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, WatchdogThreadPriority,
                             &ui32AppHintDefault, &ui32AppHintWatchdogThreadPriority);
 
        ui32AppHintDefault = PVRSRV_APPHINT_ENABLEFULLSYNCTRACKING;
-       OSGetKMAppHintBOOL(pvAppHintState, EnableFullSyncTracking,
+       OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, EnableFullSyncTracking,
                        &ui32AppHintDefault, &bEnableFullSyncTracking);
        OSFreeKMAppHintState(pvAppHintState);
        pvAppHintState = NULL;
@@ -1156,19 +1209,9 @@ PVRSRVCommonDriverInit(void)
        PVR_LOG_GOTO_IF_ERROR(eError, "OSThreadCreatePriority:3", Error);
 #endif /* SUPPORT_AUTOVZ */
 
-       gpsPVRSRVData->psProcessHandleBase_Table = HASH_Create(PVRSRV_PROC_HANDLE_BASE_INIT);
-
-       if (gpsPVRSRVData->psProcessHandleBase_Table == NULL)
-       {
-               PVR_LOG_GOTO_WITH_ERROR("psProcessHandleBase_Table", eError, PVRSRV_ERROR_UNABLE_TO_CREATE_HASH_TABLE, Error);
-       }
-
-       eError = OSLockCreate(&gpsPVRSRVData->hProcessHandleBase_Lock);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate:1", Error);
-
 #if defined(SUPPORT_RGX)
        eError = OSLockCreate(&gpsPVRSRVData->hHWPerfHostPeriodicThread_Lock);
-       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate:2", Error);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate", Error);
 #endif
 
        eError = HostMemDeviceCreate(&gpsPVRSRVData->psHostMemDeviceNode);
@@ -1233,6 +1276,22 @@ PVRSRVCommonDriverInit(void)
        PVR_LOG_GOTO_IF_ERROR(eError, "SyncFbRegisterSyncFunctions", Error);
 #endif
 
+#if defined(PDUMP)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       /* If initialising the device on first connection, we will
+        * bind PDump capture to the first device we connect to later.
+        */
+       psPVRSRVData->ui32PDumpBoundDevice = PVRSRV_MAX_DEVICES;
+#else
+       /* If not initialising the device on first connection, bind PDump
+        * capture to device 0. This is because we need to capture PDump
+        * during device initialisation but only want to capture PDump for
+        * a single device (by default, device 0).
+        */
+       psPVRSRVData->ui32PDumpBoundDevice = 0;
+#endif
+#endif
+
        return 0;
 
 Error:
@@ -1260,12 +1319,6 @@ PVRSRVCommonDriverDeInit(void)
 
        gpsPVRSRVData->bUnload = IMG_TRUE;
 
-       if (gpsPVRSRVData->hProcessHandleBase_Lock)
-       {
-               OSLockDestroy(gpsPVRSRVData->hProcessHandleBase_Lock);
-               gpsPVRSRVData->hProcessHandleBase_Lock = NULL;
-       }
-
 #if defined(SUPPORT_RGX)
        PVRSRVDestroyHWPerfHostThread();
        if (gpsPVRSRVData->hHWPerfHostPeriodicThread_Lock)
@@ -1275,12 +1328,6 @@ PVRSRVCommonDriverDeInit(void)
        }
 #endif
 
-       if (gpsPVRSRVData->psProcessHandleBase_Table)
-       {
-               HASH_Delete(gpsPVRSRVData->psProcessHandleBase_Table);
-               gpsPVRSRVData->psProcessHandleBase_Table = NULL;
-       }
-
        if (gpsPVRSRVData->hGlobalEventObject)
        {
                OSEventObjectSignal(gpsPVRSRVData->hGlobalEventObject);
@@ -1443,11 +1490,9 @@ PVRSRVCommonDriverDeInit(void)
 
        (void) DevmemIntDeInit();
 
-       eError = ServerBridgeDeInit();
-       PVR_LOG_IF_ERROR(eError, "ServerBridgeDeinit");
+       ServerBridgeDeInit();
 
-       eError = PhysHeapDeinit();
-       PVR_LOG_IF_ERROR(eError, "PhysHeapDeinit");
+       PhysHeapDeinit();
 
        HTB_DestroyDIEntry();
 
@@ -1455,156 +1500,23 @@ PVRSRVCommonDriverDeInit(void)
        PVRSRVStatsDestroy();
 #endif /* PVRSRV_ENABLE_PROCESS_STATS */
 
-       DebugCommonDeInit();
+       DebugCommonDeInitDriver();
 
        DIDeInit();
 
-       OSFreeMem(gpsPVRSRVData);
-       gpsPVRSRVData = NULL;
-}
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-/*************************************************************************/ /*!
-@Function       CreateGpuVirtValArenas
-@Description    Create virtualization validation arenas
-@Input          psDeviceNode The device node
-@Return         PVRSRV_ERROR PVRSRV_OK on success
-*/ /**************************************************************************/
-static PVRSRV_ERROR CreateGpuVirtValArenas(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-       /* aui64OSidMin and aui64OSidMax are what we program into HW registers.
-          The values are different from base/size of arenas. */
-       IMG_UINT64 aui64OSidMin[GPUVIRT_VALIDATION_NUM_REGIONS][GPUVIRT_VALIDATION_NUM_OS];
-       IMG_UINT64 aui64OSidMax[GPUVIRT_VALIDATION_NUM_REGIONS][GPUVIRT_VALIDATION_NUM_OS];
-       PHYS_HEAP_CONFIG *psGPULocalHeap = FindPhysHeapConfig(psDeviceNode->psDevConfig, PHYS_HEAP_USAGE_GPU_LOCAL);
-       PHYS_HEAP_CONFIG *psDisplayHeap = FindPhysHeapConfig(psDeviceNode->psDevConfig, PHYS_HEAP_USAGE_DISPLAY);
-       IMG_UINT64 uBase;
-       IMG_UINT64 uSize;
-       IMG_UINT64 uBaseShared;
-       IMG_UINT64 uSizeShared;
-       IMG_UINT64 uSizeSharedReg;
-       IMG_UINT32 i;
-
-       /* Shared region is fixed size, the remaining space is divided amongst OSes */
-       uSizeShared = PVR_ALIGN(GPUVIRT_SIZEOF_SHARED, (IMG_DEVMEM_SIZE_T)OSGetPageSize());
-       uSize = psGPULocalHeap->uiSize - uSizeShared;
-       uSize /= GPUVIRT_VALIDATION_NUM_OS;
-       uSize = uSize & ~((IMG_UINT64)OSGetPageSize() - 1ULL); /* Align, round down */
-
-       uBase = psGPULocalHeap->sCardBase.uiAddr;
-       uBaseShared = uBase + uSize * GPUVIRT_VALIDATION_NUM_OS;
-       uSizeShared = psGPULocalHeap->uiSize - (uBaseShared - uBase);
-
-       PVR_LOG(("GPUVIRT_VALIDATION split GPU_LOCAL base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".",
-                        psGPULocalHeap->sCardBase.uiAddr,
-                        psGPULocalHeap->uiSize));
-
-       /* If a display heap config exists, include the display heap in the non-secure regions */
-       if (psDisplayHeap)
-       {
-               /* Only works when DISPLAY heap follows GPU_LOCAL heap. */
-               PVR_LOG(("GPUVIRT_VALIDATION include DISPLAY in shared, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".",
-                                psDisplayHeap->sCardBase.uiAddr,
-                                psDisplayHeap->uiSize));
-
-               uSizeSharedReg = uSizeShared + psDisplayHeap->uiSize;
-       }
-       else
+       if (gpsPVRSRVData->hThreadsDbgReqNotify)
        {
-               uSizeSharedReg = uSizeShared;
+               PVRSRVUnregisterDriverDbgRequestNotify(gpsPVRSRVData->hThreadsDbgReqNotify);
        }
 
-       PVR_ASSERT(uSize >= GPUVIRT_MIN_SIZE);
-       PVR_ASSERT(uSizeSharedReg >= GPUVIRT_SIZEOF_SHARED);
-
-       for (i = 0; i < GPUVIRT_VALIDATION_NUM_OS; i++)
-       {
-               IMG_CHAR aszOSRAName[RA_MAX_NAME_LENGTH];
-
-               PVR_LOG(("GPUVIRT_VALIDATION create arena OS: %d, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".", i, uBase, uSize));
-
-               OSSNPrintf(aszOSRAName, RA_MAX_NAME_LENGTH, "GPUVIRT_OS%d", i);
-
-               psDeviceNode->psOSidSubArena[i] = RA_Create_With_Span(aszOSRAName,
-                                                                     OSGetPageShift(),
-                                                                     0,
-                                                                     uBase,
-                                                                     uSize);
-               PVR_LOG_RETURN_IF_NOMEM(psDeviceNode->psOSidSubArena[i], "RA_Create_With_Span");
-
-               aui64OSidMin[GPUVIRT_VAL_REGION_SECURE][i] = uBase;
-
-               if (i == 0)
-               {
-                       /* OSid0 has access to all regions */
-                       aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i] = psGPULocalHeap->uiSize - 1ULL;
-               }
-               else
-               {
-                       aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i] = uBase + uSize - 1ULL;
-               }
+       PVRSRVUnregisterDriverDbgTable();
 
-               /* uSizeSharedReg includes display heap */
-               aui64OSidMin[GPUVIRT_VAL_REGION_SHARED][i] = uBaseShared;
-               aui64OSidMax[GPUVIRT_VAL_REGION_SHARED][i] = uBaseShared + uSizeSharedReg - 1ULL;
+       OSWRLockDestroy(gpsPVRSRVData->hDeviceNodeListLock);
 
-               PVR_LOG(("GPUVIRT_VALIDATION HW reg regions %d: min[0]: 0x%" IMG_UINT64_FMTSPECX ", max[0]: 0x%" IMG_UINT64_FMTSPECX ", min[1]: 0x%" IMG_UINT64_FMTSPECX ", max[1]: 0x%" IMG_UINT64_FMTSPECX ",",
-                                i,
-                                aui64OSidMin[GPUVIRT_VAL_REGION_SECURE][i],
-                                aui64OSidMax[GPUVIRT_VAL_REGION_SECURE][i],
-                                aui64OSidMin[GPUVIRT_VAL_REGION_SHARED][i],
-                                aui64OSidMax[GPUVIRT_VAL_REGION_SHARED][i]));
-               uBase += uSize;
-       }
-
-       PVR_LOG(("GPUVIRT_VALIDATION create arena Shared, base: 0x%" IMG_UINT64_FMTSPECX ", size: 0x%" IMG_UINT64_FMTSPECX ".", uBaseShared, uSizeShared));
-
-       PVR_ASSERT(uSizeShared >= GPUVIRT_SIZEOF_SHARED);
-
-       /* uSizeShared does not include  display heap */
-       psDeviceNode->psOSSharedArena = RA_Create_With_Span("GPUVIRT_SHARED",
-                                                           OSGetPageShift(),
-                                                           0,
-                                                           uBaseShared,
-                                                           uSizeShared);
-       PVR_LOG_RETURN_IF_NOMEM(psDeviceNode->psOSSharedArena, "RA_Create_With_Span");
-
-       if (psDeviceNode->psDevConfig->pfnSysDevVirtInit != NULL)
-       {
-               psDeviceNode->psDevConfig->pfnSysDevVirtInit(aui64OSidMin, aui64OSidMax);
-       }
-
-       return PVRSRV_OK;
-}
-
-/*
- * Counter-part to CreateGpuVirtValArenas.
- */
-static void DestroyGpuVirtValArenas(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
-       IMG_UINT32      uiCounter = 0;
-
-       /*
-        * NOTE: We overload psOSidSubArena[0] into the psLocalMemArena so we must
-        * not free it here as it gets cleared later.
-        */
-       for (uiCounter = 1; uiCounter < GPUVIRT_VALIDATION_NUM_OS; uiCounter++)
-       {
-               if (psDeviceNode->psOSidSubArena[uiCounter] == NULL)
-               {
-                       continue;
-               }
-               RA_Delete(psDeviceNode->psOSidSubArena[uiCounter]);
-       }
-
-       if (psDeviceNode->psOSSharedArena != NULL)
-       {
-               RA_Delete(psDeviceNode->psOSSharedArena);
-       }
+       OSFreeMem(gpsPVRSRVData);
+       gpsPVRSRVData = NULL;
 }
 
-#endif
-
 static void _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
                                        IMG_UINT32 ui32VerbLevel,
                                        DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
@@ -1635,19 +1547,7 @@ static void _SysDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
        SysDebugInfo(psDeviceNode->psDevConfig, pfnDumpDebugPrintf, pvDumpDebugFile);
 }
 
-static void _ThreadsDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgRequestHandle,
-                                       IMG_UINT32 ui32VerbLevel,
-                                       DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                                       void *pvDumpDebugFile)
-{
-       PVR_UNREFERENCED_PARAMETER(hDbgRequestHandle);
-
-       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_HIGH))
-       {
-               PVR_DUMPDEBUG_LOG("------[ Server Thread Summary ]------");
-               OSThreadDumpInfo(pfnDumpDebugPrintf, pvDumpDebugFile);
-       }
-}
+#define PVRSRV_MIN_DEFAULT_LMA_PHYS_HEAP_SIZE (0x100000ULL * 32ULL) /* 32MB */
 
 static PVRSRV_ERROR PVRSRVValidatePhysHeapConfig(PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
@@ -1671,11 +1571,36 @@ static PVRSRV_ERROR PVRSRVValidatePhysHeapConfig(PVRSRV_DEVICE_CONFIG *psDevConf
                                                                "Phys heap config %d: duplicate usage flags.", i);
 
                ui32FlagsAccumulate |= psHeapConf->ui32UsageFlags;
+
+               /* Output message if default heap is LMA and smaller than recommended minimum */
+               if ((i == psDevConfig->eDefaultHeap) &&
+#if defined(__KERNEL__)
+                   ((psHeapConf->eType == PHYS_HEAP_TYPE_LMA) ||
+                    (psHeapConf->eType == PHYS_HEAP_TYPE_DMA)) &&
+#else
+                   (psHeapConf->eType == PHYS_HEAP_TYPE_LMA) &&
+#endif
+                   (psHeapConf->uiSize < PVRSRV_MIN_DEFAULT_LMA_PHYS_HEAP_SIZE))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Size of default heap is 0x%" IMG_UINT64_FMTSPECX 
+                                " (recommended minimum heap size is 0x%llx)",
+                                __func__, psHeapConf->uiSize,
+                                PVRSRV_MIN_DEFAULT_LMA_PHYS_HEAP_SIZE));
+               }
        }
 
-       PVR_LOG_RETURN_IF_FALSE((ui32FlagsAccumulate & PHYS_HEAP_USAGE_GPU_LOCAL) != 0 ,
+       if (psDevConfig->eDefaultHeap == PVRSRV_PHYS_HEAP_GPU_LOCAL)
+       {
+               PVR_LOG_RETURN_IF_FALSE(((ui32FlagsAccumulate & PHYS_HEAP_USAGE_GPU_LOCAL) != 0) ,
                                                        "Device config must specify GPU local phys heap config.",
                                                        PVRSRV_ERROR_PHYSHEAP_CONFIG);
+       }
+       else if (psDevConfig->eDefaultHeap == PVRSRV_PHYS_HEAP_CPU_LOCAL)
+       {
+               PVR_LOG_RETURN_IF_FALSE(((ui32FlagsAccumulate & PHYS_HEAP_USAGE_CPU_LOCAL) != 0) ,
+                                               "Device config must specify CPU local phys heap config.",
+                                               PVRSRV_ERROR_PHYSHEAP_CONFIG);
+       }
 
        return PVRSRV_OK;
 }
@@ -1683,78 +1608,38 @@ static PVRSRV_ERROR PVRSRVValidatePhysHeapConfig(PVRSRV_DEVICE_CONFIG *psDevConf
 PVRSRV_ERROR PVRSRVPhysMemHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
        PVRSRV_ERROR eError;
-       PHYS_HEAP *psPhysHeap;
-       PHYS_HEAP_TYPE eHeapType;
        PVRSRV_PHYS_HEAP ePhysHeap;
 
        eError = PVRSRVValidatePhysHeapConfig(psDevConfig);
        PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVValidatePhysHeapConfig");
 
-       /* Register the physical memory heaps */
-       psDeviceNode->papsRegisteredPhysHeaps =
-               OSAllocZMem(sizeof(*psDeviceNode->papsRegisteredPhysHeaps) *
-                                       psDevConfig->ui32PhysHeapCount);
-       PVR_RETURN_IF_NOMEM(psDeviceNode->papsRegisteredPhysHeaps);
+       eError = PhysHeapCreateDeviceHeapsFromConfigs(psDeviceNode,
+                                                     psDevConfig->pasPhysHeaps,
+                                                     psDevConfig->ui32PhysHeapCount);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapCreateDeviceHeapsFromConfigs", ErrorDeinit);
 
-       eError = PhysHeapCreateHeapsFromConfigs(psDeviceNode,
-                                                                                       psDevConfig->pasPhysHeaps,
-                                                                                       psDevConfig->ui32PhysHeapCount,
-                                                                                       psDeviceNode->papsRegisteredPhysHeaps,
-                                                                                       &psDeviceNode->ui32RegisteredPhysHeaps);
-       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapCreateHeapsFromConfigs", ErrorDeinit);
-
-       for (ePhysHeap = 0;  ePhysHeap < PVRSRV_PHYS_HEAP_LAST; ePhysHeap++)
+       for (ePhysHeap = PVRSRV_PHYS_HEAP_DEFAULT+1;  ePhysHeap < PVRSRV_PHYS_HEAP_LAST; ePhysHeap++)
        {
                if (PhysHeapPVRLayerAcquire(ePhysHeap))
                {
                        eError = PhysHeapAcquireByDevPhysHeap(ePhysHeap, psDeviceNode, &psDeviceNode->apsPhysHeap[ePhysHeap]);
                        PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquireByDevPhysHeap", ErrorDeinit);
                }
-       }
 
-       eHeapType = PhysHeapGetType(psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL]);
+               /* Calculate the total number of user accessible physical heaps */
+               if (psDeviceNode->apsPhysHeap[ePhysHeap] && PhysHeapUserModeAlloc(ePhysHeap))
+               {
+                       psDeviceNode->ui32UserAllocHeapCount++;
+               }
+       }
 
-       if (eHeapType == PHYS_HEAP_TYPE_UMA)
+       if (PhysHeapValidateDefaultHeapExists(psDeviceNode))
        {
-               PVR_DPF((PVR_DBG_MESSAGE, "%s: GPU physical heap uses OS System memory (UMA)", __func__));
-
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxAlloc = OSPhyContigPagesAlloc;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxFree = OSPhyContigPagesFree;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxMap = OSPhyContigPagesMap;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxUnMap = OSPhyContigPagesUnmap;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxClean = OSPhyContigPagesClean;
-               psDeviceNode->sDevMMUPxSetup.psPxRA = NULL;
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-               PVR_DPF((PVR_DBG_ERROR, "%s: Virtualisation Validation builds are currently only"
-                                                                " supported on systems with local memory (LMA).", __func__));
-               eError = PVRSRV_ERROR_NOT_SUPPORTED;
-               goto ErrorDeinit;
-#endif
+               PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVPhysHeapCheckUsageFlags", ErrorDeinit);
        }
-       else
-       {
-               psPhysHeap      = psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL];
-
-               PVR_DPF((PVR_DBG_MESSAGE, "%s: GPU physical heap uses local memory managed by the driver (LMA)", __func__));
 
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxAlloc = LMA_PhyContigPagesAlloc;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxFree = LMA_PhyContigPagesFree;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxMap = LMA_PhyContigPagesMap;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxUnMap = LMA_PhyContigPagesUnmap;
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxClean = LMA_PhyContigPagesClean;
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-               eError = CreateGpuVirtValArenas(psDeviceNode);
-               PVR_LOG_GOTO_IF_ERROR(eError, "CreateGpuVirtValArenas", ErrorDeinit);
-
-               psDeviceNode->sDevMMUPxSetup.psPxRA = psDeviceNode->psOSidSubArena[0];
-               psDeviceNode->sDevMMUPxSetup.pfnDevPxAllocGPV = LMA_PhyContigPagesAllocGPV;
-#else
-               eError = PhysmemGetArenaLMA(psPhysHeap, &psDeviceNode->sDevMMUPxSetup.psPxRA);
-               PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemGetArenaLMA", ErrorDeinit);
-#endif
-       }
+       eError = PhysHeapMMUPxSetup(psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapMMUPxSetup", ErrorDeinit);
 
        return PVRSRV_OK;
 
@@ -1770,18 +1655,15 @@ void PVRSRVPhysMemHeapsDeinit(PVRSRV_DEVICE_NODE *psDeviceNode)
        PVRSRV_PHYS_HEAP ePhysHeapIdx;
        IMG_UINT32 i;
 
-       if (psDeviceNode->psFwMMUReservedMemArena)
+#if defined(SUPPORT_AUTOVZ)
+       if (psDeviceNode->psFwMMUReservedPhysHeap)
        {
-               RA_Delete(psDeviceNode->psFwMMUReservedMemArena);
-               psDeviceNode->psFwMMUReservedMemArena = NULL;
+               PhysHeapDestroy(psDeviceNode->psFwMMUReservedPhysHeap);
+               psDeviceNode->psFwMMUReservedPhysHeap = NULL;
        }
+#endif
 
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-       /* Remove local LMA subarenas */
-       DestroyGpuVirtValArenas(psDeviceNode);
-#endif /* defined(SUPPORT_GPUVIRT_VALIDATION) */
-
-       psDeviceNode->sDevMMUPxSetup.psPxRA = NULL;
+       PhysHeapMMUPxDeInit(psDeviceNode);
 
        /* Release heaps */
        for (ePhysHeapIdx = 0;
@@ -1815,13 +1697,7 @@ void PVRSRVPhysMemHeapsDeinit(PVRSRV_DEVICE_NODE *psDeviceNode)
                }
        }
 
-       /* Unregister heaps */
-       for (i = 0; i < psDeviceNode->ui32RegisteredPhysHeaps; i++)
-       {
-               PhysHeapDestroy(psDeviceNode->papsRegisteredPhysHeaps[i]);
-       }
-
-       OSFreeMem(psDeviceNode->papsRegisteredPhysHeaps);
+       PhysHeapDestroyDeviceHeaps(psDeviceNode);
 }
 
 PHYS_HEAP_CONFIG* FindPhysHeapConfig(PVRSRV_DEVICE_CONFIG *psDevConfig,
@@ -1864,7 +1740,7 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
           required by SysDevInit */
        ui32AppHintDefault = PVRSRV_APPHINT_DRIVERMODE;
        OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintUINT32(pvAppHintState, DriverMode,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, DriverMode,
                                                 &ui32AppHintDefault, &ui32AppHintDriverMode);
        psPVRSRVData->eDriverMode = PVRSRV_VZ_APPHINT_MODE(ui32AppHintDriverMode);
        psPVRSRVData->bForceApphintDriverMode = PVRSRV_VZ_APPHINT_MODE_IS_OVERRIDE(ui32AppHintDriverMode);
@@ -1890,15 +1766,33 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
        PVR_ASSERT(psDevConfig->pvOSDevice == pvOSDevice);
        PVR_ASSERT(!psDevConfig->psDevNode);
 
+       if ((psDevConfig->eDefaultHeap != PVRSRV_PHYS_HEAP_GPU_LOCAL) &&
+           (psDevConfig->eDefaultHeap != PVRSRV_PHYS_HEAP_CPU_LOCAL))
+       {
+               PVR_LOG_MSG(PVR_DBG_ERROR, "DEFAULT Heap is invalid, "
+                                          "it must be GPU_LOCAL or CPU_LOCAL");
+               PVR_LOG_GOTO_IF_ERROR(eError, "SysDevInit", ErrorDeregisterStats);
+       }
+
        psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_INIT;
 
+       if (psDevConfig->pfnGpuDomainPower)
+       {
+               psDeviceNode->eCurrentSysPowerState = psDevConfig->pfnGpuDomainPower(psDeviceNode);
+       }
+       else
+       {
+               /* If the System Layer doesn't provide a function to query the power state
+                * of the system hardware, use a default implementation that keeps track of
+                * the power state locally and assumes the system starting state */
+               psDevConfig->pfnGpuDomainPower = PVRSRVDefaultDomainPower;
+
 #if defined(SUPPORT_AUTOVZ)
-       /* AutoVz platforms should have the GPU domain powered on before startup */
-       psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_ON;
+               psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_ON;
 #else
-       /* Assume system power is off at start of day and turned on by the time we hit RGXInitDevPart2 */
-       psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_OFF;
+               psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_OFF;
 #endif
+       }
 
        psDeviceNode->psDevConfig = psDevConfig;
        psDevConfig->psDevNode = psDeviceNode;
@@ -1909,7 +1803,7 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
                /* Read AppHint - Configurable memory test pass count */
                ui32AppHintDefault = 0;
                OSCreateKMAppHintState(&pvAppHintState);
-               OSGetKMAppHintUINT32(pvAppHintState, PhysMemTestPasses,
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, PhysMemTestPasses,
                                &ui32AppHintDefault, &ui32AppHintPhysMemTestPasses);
                OSFreeKMAppHintState(pvAppHintState);
                pvAppHintState = NULL;
@@ -1925,13 +1819,20 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
        /* Initialise the paravirtualised connection */
        if (!PVRSRV_VZ_MODE_IS(NATIVE))
        {
+               /* If a device already exists */
+               if (psPVRSRVData->psDeviceNodeList != NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Virtualization is currently supported only on single device systems.",
+                                        __func__));
+                       eError = PVRSRV_ERROR_NOT_SUPPORTED;
+                       goto ErrorSysDevDeInit;
+               }
+
                PvzConnectionInit(psDevConfig);
                PVR_GOTO_IF_ERROR(eError, ErrorSysDevDeInit);
        }
 
-       eError = PVRSRVRegisterDbgTable(psDeviceNode,
-                                                                       g_aui32DebugOrderTable,
-                                                                       ARRAY_SIZE(g_aui32DebugOrderTable));
+       eError = PVRSRVRegisterDeviceDbgTable(psDeviceNode);
        PVR_GOTO_IF_ERROR(eError, ErrorPvzConnectionDeInit);
 
        eError = PVRSRVPowerLockInit(psDeviceNode);
@@ -1965,8 +1866,6 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
                PVR_GOTO_IF_ERROR(eError, ErrorFwMMUDeinit);
        }
 
-       psDeviceNode->sDevMMUPxSetup.uiMMUPxLog2AllocGran = OSGetPageShift();
-
        eError = SyncServerInit(psDeviceNode);
        PVR_GOTO_IF_ERROR(eError, ErrorDeInitRgx);
 
@@ -1977,28 +1876,16 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
         * This is registered before doing device specific initialisation to ensure
         * generic device information is dumped first during a debug request.
         */
-       eError = PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hDbgReqNotify,
-                                                                                       psDeviceNode,
-                                                                                       _SysDebugRequestNotify,
-                                                                                       DEBUG_REQUEST_SYS,
-                                                                                       psDeviceNode);
-       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify", ErrorRegDbgReqNotify);
-
-       eError = PVRSRVRegisterDbgRequestNotify(&psDeviceNode->hThreadsDbgReqNotify,
-                                                                                               psDeviceNode,
-                                                                                               _ThreadsDebugRequestNotify,
-                                                                                               DEBUG_REQUEST_SYS,
-                                                                                               NULL);
-       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVRegisterDbgRequestNotify(threads)", ErrorRegThreadsDbgReqNotify);
-
-       eError = HTBDeviceCreate(psDeviceNode);
-       PVR_LOG_GOTO_IF_ERROR(eError, "HTBDeviceCreate", ErrorHTBDeviceCreate);
-
-       psPVRSRVData->ui32RegisteredDevices++;
+       eError = PVRSRVRegisterDeviceDbgRequestNotify(&psDeviceNode->hDbgReqNotify,
+                                                         psDeviceNode,
+                                                         _SysDebugRequestNotify,
+                                                         DEBUG_REQUEST_SYS,
+                                                         psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVRegisterDeviceDbgRequestNotify", ErrorRegDbgReqNotify);
 
 #if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE)
        eError = InitDVFS(psDeviceNode);
-       PVR_LOG_GOTO_IF_ERROR(eError, "InitDVFS", ErrorDecrementDeviceCount);
+       PVR_LOG_GOTO_IF_ERROR(eError, "InitDVFS", ErrorDVFSInitFail);
 #endif
 
        OSAtomicWrite(&psDeviceNode->iNumClockSpeedChanges, 0);
@@ -2012,7 +1899,7 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock for PF notify list",
                        __func__));
-               goto ErrorDecrementDeviceCount;
+               goto ErrorPageFaultLockFailCreate;
        }
 
        dllist_init(&psDeviceNode->sMemoryContextPageFaultNotifyListHead);
@@ -2038,12 +1925,39 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
        }
 #endif
 
+#if defined(__linux__)
+       /* register the AppHint device control before device initialisation
+        * so individual AppHints can be configured during the init phase
+        */
+       {
+               int iError = pvr_apphint_device_register(psDeviceNode);
+               PVR_LOG_IF_FALSE(iError == 0, "pvr_apphint_device_register() failed");
+       }
+#endif /* defined(__linux__) */
+
+#if defined(SUPPORT_RGX)
+       RGXHWPerfInitAppHintCallbacks(psDeviceNode);
+#endif
+
+       eError = DebugCommonInitDevice(psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DebugCommonInitDevice",
+                             ErrorDestroyMemoryContextPageFaultNotifyListLock);
+
        /* Finally insert the device into the dev-list and set it as active */
+       OSWRLockAcquireWrite(psPVRSRVData->hDeviceNodeListLock);
        List_PVRSRV_DEVICE_NODE_InsertTail(&psPVRSRVData->psDeviceNodeList,
                                                                           psDeviceNode);
+       psPVRSRVData->ui32RegisteredDevices++;
+       OSWRLockReleaseWrite(psPVRSRVData->hDeviceNodeListLock);
 
        *ppsDeviceNode = psDeviceNode;
 
+#if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE)
+       /* Register the DVFS device now the device node is present in the dev-list */
+       eError = RegisterDVFSDevice(psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RegisterDVFSDevice", ErrorRegisterDVFSDeviceFail);
+#endif
+
 #if defined(PVRSRV_ENABLE_PROCESS_STATS) && !defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS)
        /* Close the process statistics */
        PVRSRVStatsDeregisterProcess(hProcessStats);
@@ -2055,23 +1969,31 @@ PVRSRV_ERROR PVRSRVCommonDeviceCreate(void *pvOSDevice,
 
        return PVRSRV_OK;
 
-ErrorDecrementDeviceCount:
+#if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE)
+ErrorRegisterDVFSDeviceFail:
+       /* Remove the device from the list */
+       OSWRLockAcquireWrite(psPVRSRVData->hDeviceNodeListLock);
+       List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
        psPVRSRVData->ui32RegisteredDevices--;
+       OSWRLockReleaseWrite(psPVRSRVData->hDeviceNodeListLock);
+#endif
+
+ErrorDestroyMemoryContextPageFaultNotifyListLock:
+       OSWRLockDestroy(psDeviceNode->hMemoryContextPageFaultNotifyListLock);
+       psDeviceNode->hMemoryContextPageFaultNotifyListLock = NULL;
+
+ErrorPageFaultLockFailCreate:
 #if defined(PVR_TESTING_UTILS)
        TUtilsDeinit(psDeviceNode);
 #endif
-       HTBDeviceDestroy(psDeviceNode);
 
-ErrorHTBDeviceCreate:
-       if (psDeviceNode->hThreadsDbgReqNotify)
-       {
-               PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hThreadsDbgReqNotify);
-       }
+#if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE)
+ErrorDVFSInitFail:
+#endif
 
-ErrorRegThreadsDbgReqNotify:
        if (psDeviceNode->hDbgReqNotify)
        {
-               PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
+               PVRSRVUnregisterDeviceDbgRequestNotify(psDeviceNode->hDbgReqNotify);
        }
 
 ErrorRegDbgReqNotify:
@@ -2090,7 +2012,7 @@ ErrorPhysMemHeapsDeinit:
 ErrorPowerLockDeInit:
        PVRSRVPowerLockDeInit(psDeviceNode);
 ErrorUnregisterDbgTable:
-       PVRSRVUnregisterDbgTable(psDeviceNode);
+       PVRSRVUnregisterDeviceDbgTable(psDeviceNode);
 ErrorPvzConnectionDeInit:
        psDevConfig->psDevNode = NULL;
        if (!PVRSRV_VZ_MODE_IS(NATIVE))
@@ -2118,6 +2040,8 @@ static PVRSRV_ERROR _SetDeviceFlag(const PVRSRV_DEVICE_NODE *psDevice,
        IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
 
        PVR_RETURN_IF_INVALID_PARAM(ui32Flag);
+       PVR_RETURN_IF_FALSE(psDevice != APPHINT_OF_DRIVER_NO_DEVICE,
+                           PVRSRV_ERROR_INVALID_PARAMS);
 
        eResult = RGXSetDeviceFlags((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
                                    ui32Flag, bValue);
@@ -2133,6 +2057,8 @@ static PVRSRV_ERROR _ReadDeviceFlag(const PVRSRV_DEVICE_NODE *psDevice,
        IMG_UINT32 ui32State;
 
        PVR_RETURN_IF_INVALID_PARAM(ui32Flag);
+       PVR_RETURN_IF_FALSE(psDevice != APPHINT_OF_DRIVER_NO_DEVICE,
+                           PVRSRV_ERROR_INVALID_PARAMS);
 
        eResult = RGXGetDeviceFlags((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
                                    &ui32State);
@@ -2151,6 +2077,8 @@ static PVRSRV_ERROR _SetStateFlag(const PVRSRV_DEVICE_NODE *psDevice,
        IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
 
        PVR_RETURN_IF_INVALID_PARAM(ui32Flag);
+       PVR_RETURN_IF_FALSE(psDevice != APPHINT_OF_DRIVER_NO_DEVICE,
+                           PVRSRV_ERROR_INVALID_PARAMS);
 
        eResult = RGXStateFlagCtrl((PVRSRV_RGXDEV_INFO *)psDevice->pvDevice,
                                   ui32Flag, NULL, bValue);
@@ -2163,10 +2091,13 @@ static PVRSRV_ERROR _ReadStateFlag(const PVRSRV_DEVICE_NODE *psDevice,
 {
        IMG_UINT32 ui32Flag = (IMG_UINT32)((uintptr_t)psPrivate);
        IMG_UINT32 ui32State;
-       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDevice->pvDevice;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
 
        PVR_RETURN_IF_INVALID_PARAM(ui32Flag);
+       PVR_RETURN_IF_FALSE(psDevice != APPHINT_OF_DRIVER_NO_DEVICE,
+                           PVRSRV_ERROR_INVALID_PARAMS);
 
+       psDevInfo = (PVRSRV_RGXDEV_INFO *)psDevice->pvDevice;
        ui32State = psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags;
 
        if (pbValue)
@@ -2194,6 +2125,20 @@ PVRSRV_ERROR PVRSRVCommonDeviceInitialise(PVRSRV_DEVICE_NODE *psDeviceNode)
                return PVRSRV_ERROR_INIT_FAILURE;
        }
 
+#if defined(PDUMP)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       {
+               PVRSRV_DATA *psSRVData = PVRSRVGetPVRSRVData();
+
+               /* If first connection, bind this and future PDump clients to use this device */
+               if (psSRVData->ui32PDumpBoundDevice == PVRSRV_MAX_DEVICES)
+               {
+                       psSRVData->ui32PDumpBoundDevice = psDeviceNode->sDevId.ui32InternalID;
+               }
+       }
+#endif
+#endif
+
        /* Initialise Connection_Data access mechanism */
        dllist_init(&psDeviceNode->sConnections);
        eError = OSLockCreate(&psDeviceNode->hConnectionsLock);
@@ -2228,11 +2173,11 @@ Exit:
        {
                PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisableClockGating,
                                                  _ReadStateFlag, _SetStateFlag,
-                                                 psDeviceNode,
+                                                 APPHINT_OF_DRIVER_NO_DEVICE,
                                                  (void*)((uintptr_t)RGXFWIF_INICFG_DISABLE_CLKGATING_EN));
                PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_DisableDMOverlap,
                                                  _ReadStateFlag, _SetStateFlag,
-                                                 psDeviceNode,
+                                                 APPHINT_OF_DRIVER_NO_DEVICE,
                                                  (void*)((uintptr_t)RGXFWIF_INICFG_DISABLE_DM_OVERLAP));
                PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_AssertOnHWRTrigger,
                                                  _ReadStateFlag, _SetStateFlag,
@@ -2291,9 +2236,22 @@ PVRSRV_ERROR PVRSRVCommonDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
 
        MULTI_DEVICE_BRINGUP_DPF("PVRSRVCommonDeviceDestroy: DevId %d", psDeviceNode->sDevId.i32OsDeviceID);
 
+       psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
+
+#if defined(SUPPORT_LINUX_DVFS) && !defined(NO_HARDWARE)
+       UnregisterDVFSDevice(psDeviceNode);
+#endif
+
+       OSWRLockAcquireWrite(psPVRSRVData->hDeviceNodeListLock);
+       List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
        psPVRSRVData->ui32RegisteredDevices--;
+       OSWRLockReleaseWrite(psPVRSRVData->hDeviceNodeListLock);
 
-       psDeviceNode->eDevState = PVRSRV_DEVICE_STATE_DEINIT;
+#if defined(__linux__)
+       pvr_apphint_device_unregister(psDeviceNode);
+#endif /* defined(__linux__) */
+
+       DebugCommonDeInitDevice(psDeviceNode);
 
        if (psDeviceNode->hMemoryContextPageFaultNotifyListLock != NULL)
        {
@@ -2370,7 +2328,7 @@ PVRSRV_ERROR PVRSRVCommonDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
                /* Power down the device if necessary */
                eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                                                         PVRSRV_DEV_POWER_STATE_OFF,
-                                                                                        IMG_TRUE);
+                                                                                        PVRSRV_POWER_FLAGS_FORCED);
                PVRSRVPowerUnlock(psDeviceNode);
 
                if (eError != PVRSRV_OK)
@@ -2404,16 +2362,9 @@ PVRSRV_ERROR PVRSRVCommonDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
        DeinitDVFS(psDeviceNode);
 #endif
 
-       HTBDeviceDestroy(psDeviceNode);
-
-       if (psDeviceNode->hThreadsDbgReqNotify)
-       {
-               PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hThreadsDbgReqNotify);
-       }
-
        if (psDeviceNode->hDbgReqNotify)
        {
-               PVRSRVUnregisterDbgRequestNotify(psDeviceNode->hDbgReqNotify);
+               PVRSRVUnregisterDeviceDbgRequestNotify(psDeviceNode->hDbgReqNotify);
        }
 
        SyncCheckpointDeinit(psDeviceNode);
@@ -2424,18 +2375,15 @@ PVRSRV_ERROR PVRSRVCommonDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
        DevDeInitRGX(psDeviceNode);
 #endif
 
-       List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-
        PVRSRVPhysMemHeapsDeinit(psDeviceNode);
        PVRSRVPowerLockDeInit(psDeviceNode);
 
-       PVRSRVUnregisterDbgTable(psDeviceNode);
+       PVRSRVUnregisterDeviceDbgTable(psDeviceNode);
 
        /* Release the Connection-Data lock as late as possible. */
        if (psDeviceNode->hConnectionsLock)
        {
-               eError = OSLockDestroy(psDeviceNode->hConnectionsLock);
-               PVR_LOG_IF_ERROR(eError, "ConnectionLock destruction failed");
+               OSLockDestroy(psDeviceNode->hConnectionsLock);
        }
 
        psDeviceNode->psDevConfig->psDevNode = NULL;
@@ -2451,264 +2399,6 @@ PVRSRV_ERROR PVRSRVCommonDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode)
        return PVRSRV_OK;
 }
 
-static PVRSRV_ERROR _LMA_DoPhyContigPagesAlloc(RA_ARENA *pArena,
-                                               size_t uiSize,
-                                               PG_HANDLE *psMemHandle,
-                                               IMG_DEV_PHYADDR *psDevPAddr,
-                                               IMG_PID uiPid)
-{
-       RA_BASE_T uiCardAddr = 0;
-       RA_LENGTH_T uiActualSize;
-       PVRSRV_ERROR eError;
-#if defined(DEBUG)
-       static IMG_UINT32       ui32MaxLog2NumPages = 4;        /* 16 pages => 64KB */
-#endif /* defined(DEBUG) */
-
-       IMG_UINT32 ui32Log2NumPages = 0;
-
-       PVR_ASSERT(uiSize != 0);
-       ui32Log2NumPages = OSGetOrder(uiSize);
-       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
-
-       eError = RA_Alloc(pArena,
-                         uiSize,
-                         RA_NO_IMPORT_MULTIPLIER,
-                         0,                         /* No flags */
-                         uiSize,
-                         "LMA_PhyContigPagesAlloc",
-                         &uiCardAddr,
-                         &uiActualSize,
-                         NULL);                     /* No private handle */
-
-       PVR_ASSERT(uiSize == uiActualSize);
-
-       psMemHandle->u.ui64Handle = uiCardAddr;
-       psDevPAddr->uiAddr = (IMG_UINT64) uiCardAddr;
-
-       if (PVRSRV_OK == eError)
-       {
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-               PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
-                                                   uiSize,
-                                                   uiCardAddr,
-                                                   uiPid);
-#else
-               IMG_CPU_PHYADDR sCpuPAddr;
-               sCpuPAddr.uiAddr = psDevPAddr->uiAddr;
-
-               PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
-                                            NULL,
-                                            sCpuPAddr,
-                                            uiSize,
-                                            NULL,
-                                            uiPid
-                                            DEBUG_MEMSTATS_VALUES);
-#endif
-#endif
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-               PVR_DPF((PVR_DBG_MESSAGE,
-                       "%s: (GPU Virtualisation) Allocated 0x" IMG_SIZE_FMTSPECX " at 0x%" IMG_UINT64_FMTSPECX ", Arena ID %u",
-                       __func__, uiSize, psDevPAddr->uiAddr, psMemHandle->uiOSid));
-#endif
-
-#if defined(DEBUG)
-               PVR_ASSERT((ui32Log2NumPages <= ui32MaxLog2NumPages));
-               if (ui32Log2NumPages > ui32MaxLog2NumPages)
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                               "%s: ui32MaxLog2NumPages = %u, increasing to %u", __func__,
-                               ui32MaxLog2NumPages, ui32Log2NumPages ));
-                       ui32MaxLog2NumPages = ui32Log2NumPages;
-               }
-#endif /* defined(DEBUG) */
-               psMemHandle->uiOrder = ui32Log2NumPages;
-       }
-
-       return eError;
-}
-
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-PVRSRV_ERROR LMA_PhyContigPagesAllocGPV(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
-                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       IMG_UINT32 ui32OSid, IMG_PID uiPid)
-{
-       RA_ARENA *pArena;
-       IMG_UINT32 ui32Log2NumPages = 0;
-       PVRSRV_ERROR eError;
-
-       PVR_ASSERT(uiSize != 0);
-       ui32Log2NumPages = OSGetOrder(uiSize);
-       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
-
-       PVR_ASSERT(ui32OSid < GPUVIRT_VALIDATION_NUM_OS);
-       if (ui32OSid >= GPUVIRT_VALIDATION_NUM_OS)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Arena index %u defaulting to 0",
-                       __func__, ui32OSid));
-               ui32OSid = 0;
-       }
-       pArena = psDevNode->psOSidSubArena[ui32OSid];
-
-       if (psMemHandle->uiOSid != ui32OSid)
-       {
-               PVR_LOG(("%s: Unexpected OSid value %u - expecting %u", __func__,
-                       psMemHandle->uiOSid, ui32OSid));
-       }
-
-       psMemHandle->uiOSid = ui32OSid;         /* For Free() use */
-
-       eError =  _LMA_DoPhyContigPagesAlloc(pArena, uiSize, psMemHandle,
-                                            psDevPAddr, uiPid);
-       PVR_LOG_IF_ERROR(eError, "_LMA_DoPhyContigPagesAlloc");
-
-       return eError;
-}
-#endif
-
-PVRSRV_ERROR LMA_PhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
-                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       IMG_PID uiPid)
-{
-       PVRSRV_ERROR eError;
-
-       RA_ARENA *pArena = psDevNode->sDevMMUPxSetup.psPxRA;
-       IMG_UINT32 ui32Log2NumPages = 0;
-
-       PVR_ASSERT(uiSize != 0);
-       ui32Log2NumPages = OSGetOrder(uiSize);
-       uiSize = (1 << ui32Log2NumPages) * OSGetPageSize();
-
-       eError = _LMA_DoPhyContigPagesAlloc(pArena, uiSize, psMemHandle,
-                                           psDevPAddr, uiPid);
-       PVR_LOG_IF_ERROR(eError, "_LMA_DoPhyContigPagesAlloc");
-
-       return eError;
-}
-
-void LMA_PhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
-{
-       RA_BASE_T uiCardAddr = (RA_BASE_T) psMemHandle->u.ui64Handle;
-       RA_ARENA        *pArena;
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-       IMG_UINT32      ui32OSid = psMemHandle->uiOSid;
-
-       /*
-        * The Arena ID is set by the originating allocation, and maintained via
-        * the call stacks into this function. We have a limited range of IDs
-        * and if the passed value falls outside this we simply treat it as a
-        * 'global' arena ID of 0. This is where all default OS-specific allocations
-        * are created.
-        */
-       PVR_ASSERT(ui32OSid < GPUVIRT_VALIDATION_NUM_OS);
-       if (ui32OSid >= GPUVIRT_VALIDATION_NUM_OS)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid Arena index %u PhysAddr 0x%"
-                        IMG_UINT64_FMTSPECx " Reverting to Arena 0", __func__,
-                        ui32OSid, uiCardAddr));
-               /*
-                * No way of determining what we're trying to free so default to the
-                * global default arena index 0.
-                */
-               ui32OSid = 0;
-       }
-
-       pArena = psDevNode->psOSidSubArena[ui32OSid];
-
-       PVR_DPF((PVR_DBG_MESSAGE, "%s: (GPU Virtualisation) Freeing 0x%"
-               IMG_UINT64_FMTSPECx ", Arena %u", __func__,
-               uiCardAddr, ui32OSid));
-
-#else
-       pArena = psDevNode->sDevMMUPxSetup.psPxRA;
-#endif
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-       PVRSRVStatsDecrMemAllocStatAndUntrack(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
-                                             (IMG_UINT64)uiCardAddr);
-#else
-       PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_ALLOC_PAGES_PT_LMA,
-                                                                       (IMG_UINT64)uiCardAddr,
-                                                                       OSGetCurrentClientProcessIDKM());
-#endif
-#endif
-
-       RA_Free(pArena, uiCardAddr);
-       psMemHandle->uiOrder = 0;
-}
-
-PVRSRV_ERROR LMA_PhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-                                                       size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       void **pvPtr)
-{
-       IMG_CPU_PHYADDR sCpuPAddr;
-       IMG_UINT32 ui32NumPages = (1 << psMemHandle->uiOrder);
-       PVR_UNREFERENCED_PARAMETER(psMemHandle);
-       PVR_UNREFERENCED_PARAMETER(uiSize);
-
-       PhysHeapDevPAddrToCpuPAddr(psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL], 1, &sCpuPAddr, psDevPAddr);
-       *pvPtr = OSMapPhysToLin(sCpuPAddr,
-                                                       ui32NumPages * OSGetPageSize(),
-                                                       PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC);
-       PVR_RETURN_IF_NOMEM(*pvPtr);
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-       PVRSRVStatsIncrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
-                                   ui32NumPages * OSGetPageSize(),
-                                   OSGetCurrentClientProcessIDKM());
-#else
-       {
-               PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
-                                                                        *pvPtr,
-                                                                        sCpuPAddr,
-                                                                        ui32NumPages * OSGetPageSize(),
-                                                                        NULL,
-                                                                        OSGetCurrentClientProcessIDKM()
-                                                                        DEBUG_MEMSTATS_VALUES);
-       }
-#endif
-#endif
-       return PVRSRV_OK;
-}
-
-void LMA_PhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-                                               void *pvPtr)
-{
-       IMG_UINT32 ui32NumPages = (1 << psMemHandle->uiOrder);
-       PVR_UNREFERENCED_PARAMETER(psMemHandle);
-       PVR_UNREFERENCED_PARAMETER(psDevNode);
-
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if !defined(PVRSRV_ENABLE_MEMORY_STATS)
-       PVRSRVStatsDecrMemAllocStat(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
-                                           ui32NumPages * OSGetPageSize(),
-                                           OSGetCurrentClientProcessIDKM());
-#else
-       PVRSRVStatsRemoveMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE_IOREMAP_PT_LMA,
-                                       (IMG_UINT64)(uintptr_t)pvPtr,
-                                       OSGetCurrentClientProcessIDKM());
-#endif
-#endif
-
-       OSUnMapPhysToLin(pvPtr, ui32NumPages * OSGetPageSize());
-}
-
-PVRSRV_ERROR LMA_PhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
-                                     PG_HANDLE *psMemHandle,
-                                     IMG_UINT32 uiOffset,
-                                     IMG_UINT32 uiLength)
-{
-       /* No need to flush because we map as uncached */
-       PVR_UNREFERENCED_PARAMETER(psDevNode);
-       PVR_UNREFERENCED_PARAMETER(psMemHandle);
-       PVR_UNREFERENCED_PARAMETER(uiOffset);
-       PVR_UNREFERENCED_PARAMETER(uiLength);
-
-       return PVRSRV_OK;
-}
-
 /**************************************************************************/ /*!
 @Function     PVRSRVDeviceFinalise
 @Description  Performs the final parts of device initialisation.
@@ -2766,7 +2456,8 @@ PVRSRV_ERROR PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
                 * and PDUMPPOWCMDEND.
                 */
                eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
-                                                                                        PVRSRV_DEV_POWER_STATE_ON, IMG_TRUE);
+                                                                                        PVRSRV_DEV_POWER_STATE_ON,
+                                                                                        PVRSRV_POWER_FLAGS_FORCED);
                if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR,
@@ -2776,7 +2467,7 @@ PVRSRV_ERROR PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
                        goto ErrorExit;
                }
 
-#if defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
                eError = ValidateFWOnLoad(psDeviceNode->pvDevice);
                if (eError != PVRSRV_OK)
                {
@@ -2797,7 +2488,7 @@ PVRSRV_ERROR PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
                        goto ErrorExit;
                }
 
-               PDUMPPOWCMDSTART();
+               PDUMPPOWCMDSTART(psDeviceNode);
 
                /* Force the device to idle if its default power state is off */
                eError = PVRSRVDeviceIdleRequestKM(psDeviceNode,
@@ -2816,8 +2507,8 @@ PVRSRV_ERROR PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
                /* Place device into its default power state. */
                eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                                                         PVRSRV_DEV_POWER_STATE_DEFAULT,
-                                                                                        IMG_TRUE);
-               PDUMPPOWCMDEND();
+                                                                                        PVRSRV_POWER_FLAGS_FORCED);
+               PDUMPPOWCMDEND(psDeviceNode);
 
                if (eError != PVRSRV_OK)
                {
@@ -2861,8 +2552,7 @@ PVRSRV_ERROR PVRSRVDeviceFinalise(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        /* Give PDump control a chance to end the init phase, depends on OS */
-       PDumpStopInitPhase();
-
+       PDUMPENDINITPHASE(psDeviceNode);
        return eError;
 
 ErrorExit:
@@ -3141,10 +2831,13 @@ PVRSRV_ERROR PVRSRVSystemInstallDeviceLISR(void *pvOSDevice,
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_NODE *psDeviceNode;
 
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
        psDeviceNode =
                List_PVRSRV_DEVICE_NODE_Any_va(psPVRSRVData->psDeviceNodeList,
                                                                           &PVRSRVSystemInstallDeviceLISR_Match_AnyVaCb,
                                                                           pvOSDevice);
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
        if (!psDeviceNode)
        {
                /* Device can't be found in the list so it isn't in the system */
@@ -3268,18 +2961,43 @@ PVRSRV_DEVICE_NODE *PVRSRVGetDeviceInstance(IMG_UINT32 uiInstance)
        {
                return NULL;
        }
+       OSWRLockAcquireRead(gpsPVRSRVData->hDeviceNodeListLock);
        for (psDevNode = gpsPVRSRVData->psDeviceNodeList;
             psDevNode != NULL; psDevNode = psDevNode->psNext)
        {
                if (uiInstance == psDevNode->sDevId.ui32InternalID)
                {
-                       return psDevNode;
+                       break;
                }
        }
+       OSWRLockReleaseRead(gpsPVRSRVData->hDeviceNodeListLock);
 
-       return NULL;
+       return psDevNode;
 }
 
+PVRSRV_DEVICE_NODE *PVRSRVGetDeviceInstanceByOSId(IMG_INT32 i32OSInstance)
+{
+       PVRSRV_DEVICE_NODE *psDevNode;
+
+       OSWRLockAcquireRead(gpsPVRSRVData->hDeviceNodeListLock);
+       for (psDevNode = gpsPVRSRVData->psDeviceNodeList;
+            psDevNode != NULL; psDevNode = psDevNode->psNext)
+       {
+               if (i32OSInstance == psDevNode->sDevId.i32OsDeviceID)
+               {
+                       break;
+               }
+       }
+       OSWRLockReleaseRead(gpsPVRSRVData->hDeviceNodeListLock);
+
+       return psDevNode;
+}
+
+/* Default function for querying the power state of the system */
+PVRSRV_SYS_POWER_STATE PVRSRVDefaultDomainPower(PVRSRV_DEVICE_NODE *psDevNode)
+{
+       return psDevNode->eCurrentSysPowerState;
+}
 /*****************************************************************************
  End of file (pvrsrv.c)
 *****************************************************************************/
index d0585b4..2ce4ae0 100644 (file)
@@ -47,107 +47,99 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /* These will go when full bridge gen comes in */
 #if defined(PDUMP)
 PVRSRV_ERROR InitPDUMPCTRLBridge(void);
-PVRSRV_ERROR DeinitPDUMPCTRLBridge(void);
+void DeinitPDUMPCTRLBridge(void);
 PVRSRV_ERROR InitPDUMPBridge(void);
-PVRSRV_ERROR DeinitPDUMPBridge(void);
+void DeinitPDUMPBridge(void);
 PVRSRV_ERROR InitRGXPDUMPBridge(void);
-PVRSRV_ERROR DeinitRGXPDUMPBridge(void);
+void DeinitRGXPDUMPBridge(void);
 #endif
 #if defined(SUPPORT_DISPLAY_CLASS)
 PVRSRV_ERROR InitDCBridge(void);
-PVRSRV_ERROR DeinitDCBridge(void);
+void DeinitDCBridge(void);
 #endif
 PVRSRV_ERROR InitMMBridge(void);
-PVRSRV_ERROR DeinitMMBridge(void);
+void DeinitMMBridge(void);
 #if !defined(EXCLUDE_CMM_BRIDGE)
 PVRSRV_ERROR InitCMMBridge(void);
-PVRSRV_ERROR DeinitCMMBridge(void);
+void DeinitCMMBridge(void);
 #endif
 PVRSRV_ERROR InitPDUMPMMBridge(void);
-PVRSRV_ERROR DeinitPDUMPMMBridge(void);
+void DeinitPDUMPMMBridge(void);
 PVRSRV_ERROR InitSRVCOREBridge(void);
-PVRSRV_ERROR DeinitSRVCOREBridge(void);
+void DeinitSRVCOREBridge(void);
 PVRSRV_ERROR InitSYNCBridge(void);
-PVRSRV_ERROR DeinitSYNCBridge(void);
+void DeinitSYNCBridge(void);
 #if defined(SUPPORT_DMA_TRANSFER)
 PVRSRV_ERROR InitDMABridge(void);
-PVRSRV_ERROR DeinitDMABridge(void);
+void DeinitDMABridge(void);
 #endif
 
 #if defined(SUPPORT_RGX)
 PVRSRV_ERROR InitRGXTA3DBridge(void);
-PVRSRV_ERROR DeinitRGXTA3DBridge(void);
+void DeinitRGXTA3DBridge(void);
 #if defined(SUPPORT_RGXTQ_BRIDGE)
 PVRSRV_ERROR InitRGXTQBridge(void);
-PVRSRV_ERROR DeinitRGXTQBridge(void);
+void DeinitRGXTQBridge(void);
 #endif /* defined(SUPPORT_RGXTQ_BRIDGE) */
-PVRSRV_ERROR InitRGXTQ2Bridge(void);
-PVRSRV_ERROR DeinitRGXTQ2Bridge(void);
-PVRSRV_ERROR InitRGXCMPBridge(void);
-PVRSRV_ERROR DeinitRGXCMPBridge(void);
+
 #if defined(SUPPORT_USC_BREAKPOINT)
 PVRSRV_ERROR InitRGXBREAKPOINTBridge(void);
-PVRSRV_ERROR DeinitRGXBREAKPOINTBridge(void);
+void DeinitRGXBREAKPOINTBridge(void);
 #endif
 PVRSRV_ERROR InitRGXFWDBGBridge(void);
-PVRSRV_ERROR DeinitRGXFWDBGBridge(void);
+void DeinitRGXFWDBGBridge(void);
 PVRSRV_ERROR InitRGXHWPERFBridge(void);
-PVRSRV_ERROR DeinitRGXHWPERFBridge(void);
+void DeinitRGXHWPERFBridge(void);
 #if !defined(EXCLUDE_RGXREGCONFIG_BRIDGE)
 PVRSRV_ERROR InitRGXREGCONFIGBridge(void);
-PVRSRV_ERROR DeinitRGXREGCONFIGBridge(void);
+void DeinitRGXREGCONFIGBridge(void);
 #endif
 PVRSRV_ERROR InitRGXKICKSYNCBridge(void);
-PVRSRV_ERROR DeinitRGXKICKSYNCBridge(void);
-PVRSRV_ERROR InitRGXSIGNALSBridge(void);
-PVRSRV_ERROR DeinitRGXSIGNALSBridge(void);
+void DeinitRGXKICKSYNCBridge(void);
 #endif /* SUPPORT_RGX */
 PVRSRV_ERROR InitCACHEBridge(void);
-PVRSRV_ERROR DeinitCACHEBridge(void);
+void DeinitCACHEBridge(void);
 #if defined(SUPPORT_SECURE_EXPORT)
 PVRSRV_ERROR InitSMMBridge(void);
-PVRSRV_ERROR DeinitSMMBridge(void);
+void DeinitSMMBridge(void);
 #endif
 #if !defined(EXCLUDE_HTBUFFER_BRIDGE)
 PVRSRV_ERROR InitHTBUFFERBridge(void);
-PVRSRV_ERROR DeinitHTBUFFERBridge(void);
+void DeinitHTBUFFERBridge(void);
 #endif
 PVRSRV_ERROR InitPVRTLBridge(void);
-PVRSRV_ERROR DeinitPVRTLBridge(void);
+void DeinitPVRTLBridge(void);
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
 PVRSRV_ERROR InitRIBridge(void);
-PVRSRV_ERROR DeinitRIBridge(void);
+void DeinitRIBridge(void);
 #endif
 PVRSRV_ERROR InitDEVICEMEMHISTORYBridge(void);
-PVRSRV_ERROR DeinitDEVICEMEMHISTORYBridge(void);
+void DeinitDEVICEMEMHISTORYBridge(void);
 #if defined(SUPPORT_VALIDATION_BRIDGE)
 PVRSRV_ERROR InitVALIDATIONBridge(void);
-PVRSRV_ERROR DeinitVALIDATIONBridge(void);
+void DeinitVALIDATIONBridge(void);
 #endif
 #if defined(PVR_TESTING_UTILS)
 PVRSRV_ERROR InitTUTILSBridge(void);
-PVRSRV_ERROR DeinitTUTILSBridge(void);
+void DeinitTUTILSBridge(void);
 #endif
 PVRSRV_ERROR InitSYNCTRACKINGBridge(void);
-PVRSRV_ERROR DeinitSYNCTRACKINGBridge(void);
+void DeinitSYNCTRACKINGBridge(void);
 #if defined(SUPPORT_WRAP_EXTMEM)
 PVRSRV_ERROR InitMMEXTMEMBridge(void);
-PVRSRV_ERROR DeinitMMEXTMEMBridge(void);
+void DeinitMMEXTMEMBridge(void);
 #endif
 #if defined(SUPPORT_FALLBACK_FENCE_SYNC)
 PVRSRV_ERROR InitSYNCFALLBACKBridge(void);
-PVRSRV_ERROR DeinitSYNCFALLBACKBridge(void);
+void DeinitSYNCFALLBACKBridge(void);
 #endif
 PVRSRV_ERROR InitRGXTIMERQUERYBridge(void);
-PVRSRV_ERROR DeinitRGXTIMERQUERYBridge(void);
+void DeinitRGXTIMERQUERYBridge(void);
 #if defined(SUPPORT_DI_BRG_IMPL)
 PVRSRV_ERROR InitDIBridge(void);
-PVRSRV_ERROR DeinitDIBridge(void);
+void DeinitDIBridge(void);
 #endif
 
-PVRSRV_ERROR InitRGXRAYBridge(void);
-PVRSRV_ERROR DeinitRGXRAYBridge(void);
-
 PVRSRV_ERROR
 ServerBridgeInit(void)
 {
@@ -289,223 +281,105 @@ ServerBridgeInit(void)
        return eError;
 }
 
-PVRSRV_ERROR
-ServerBridgeDeInit(void)
+void ServerBridgeDeInit(void)
 {
-       PVRSRV_ERROR eError;
-
-       eError = OSPlatformBridgeDeInit();
-       PVR_LOG_IF_ERROR(eError, "OSPlatformBridgeDeInit");
+       OSPlatformBridgeDeInit();
 
 #if defined(SUPPORT_DI_BRG_IMPL)
-       eError = DeinitDIBridge();
-       PVR_LOG_IF_ERROR(eError, "DeinitDIBridge");
+       DeinitDIBridge();
 #endif
 
 #if defined(SUPPORT_FALLBACK_FENCE_SYNC)
-       eError = DeinitSYNCFALLBACKBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitSYNCFALLBACKBridge");
+       DeinitSYNCFALLBACKBridge();
 #endif
 
 #if defined(SUPPORT_WRAP_EXTMEM)
-       eError = DeinitMMEXTMEMBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitMMEXTMEMBridge");
+       DeinitMMEXTMEMBridge();
 #endif
 
-       eError = DeinitSRVCOREBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitSRVCOREBridge");
+       DeinitSRVCOREBridge();
 
-       eError = DeinitSYNCBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitSYNCBridge");
+       DeinitSYNCBridge();
 
 #if defined(PDUMP)
-       eError = DeinitPDUMPCTRLBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitPDUMPCTRLBridge");
+       DeinitPDUMPCTRLBridge();
 #endif
 
-       eError = DeinitMMBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitMMBridge");
+       DeinitMMBridge();
 
 #if !defined(EXCLUDE_CMM_BRIDGE)
-       eError = DeinitCMMBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitCMMBridge");
+       DeinitCMMBridge();
 #endif
 
 #if defined(PDUMP)
-       eError = DeinitPDUMPMMBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitPDUMPMMBridge");
+       DeinitPDUMPMMBridge();
 
-       eError = DeinitPDUMPBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitPDUMPBridge");
+       DeinitPDUMPBridge();
 #endif
 
 #if defined(PVR_TESTING_UTILS)
-       eError = DeinitTUTILSBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitTUTILSBridge");
+       DeinitTUTILSBridge();
 #endif
 
 #if defined(SUPPORT_DISPLAY_CLASS)
-       eError = DeinitDCBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitDCBridge");
+       DeinitDCBridge();
 #endif
 
-       eError = DeinitCACHEBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitCACHEBridge");
+       DeinitCACHEBridge();
 
 #if defined(SUPPORT_SECURE_EXPORT)
-       eError = DeinitSMMBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitSMMBridge");
+       DeinitSMMBridge();
 #endif
 
 #if !defined(EXCLUDE_HTBUFFER_BRIDGE)
-       eError = DeinitHTBUFFERBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitHTBUFFERBridge");
+       DeinitHTBUFFERBridge();
 #endif
 
-       eError = DeinitPVRTLBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitPVRTLBridge");
+       DeinitPVRTLBridge();
 
 #if defined(SUPPORT_VALIDATION_BRIDGE)
-       eError = DeinitVALIDATIONBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitVALIDATIONBridge");
+       DeinitVALIDATIONBridge();
 #endif
 
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
-       eError = DeinitRIBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRIBridge");
+       DeinitRIBridge();
 #endif
 
-       eError = DeinitDEVICEMEMHISTORYBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitDEVICEMEMHISTORYBridge");
+       DeinitDEVICEMEMHISTORYBridge();
 
-       eError = DeinitSYNCTRACKINGBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitSYNCTRACKINGBridge");
+       DeinitSYNCTRACKINGBridge();
 
 #if defined(SUPPORT_DMA_TRANSFER)
-       eError = DeinitDMABridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitDMABridge");
+       DeinitDMABridge();
 #endif
 
 #if defined(SUPPORT_RGX)
 
 #if defined(SUPPORT_RGXTQ_BRIDGE)
-       eError = DeinitRGXTQBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXTQBridge");
+       DeinitRGXTQBridge();
 #endif /* defined(SUPPORT_RGXTQ_BRIDGE) */
 
-       eError = DeinitRGXTA3DBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXTA3DBridge");
+       DeinitRGXTA3DBridge();
 
 #if defined(SUPPORT_USC_BREAKPOINT)
-       eError = DeinitRGXBREAKPOINTBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXBREAKPOINTBridge");
+       DeinitRGXBREAKPOINTBridge();
 #endif
 
-       eError = DeinitRGXFWDBGBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXFWDBGBridge");
+       DeinitRGXFWDBGBridge();
 
 #if defined(PDUMP)
-       eError = DeinitRGXPDUMPBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXPDUMPBridge");
+       DeinitRGXPDUMPBridge();
 #endif
 
-       eError = DeinitRGXHWPERFBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXHWPERFBridge");
+       DeinitRGXHWPERFBridge();
 
 #if !defined(EXCLUDE_RGXREGCONFIG_BRIDGE)
-       eError = DeinitRGXREGCONFIGBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXREGCONFIGBridge");
+       DeinitRGXREGCONFIGBridge();
 #endif
 
-       eError = DeinitRGXKICKSYNCBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXKICKSYNCBridge");
+       DeinitRGXKICKSYNCBridge();
 
-       eError = DeinitRGXTIMERQUERYBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXTIMERQUERYBridge");
+       DeinitRGXTIMERQUERYBridge();
 
 #endif /* SUPPORT_RGX */
-
-       return eError;
 }
-
-#if defined(SUPPORT_RGX)
-PVRSRV_ERROR
-DeviceDepBridgeInit(IMG_UINT64 ui64Features)
-{
-       PVRSRV_ERROR eError;
-
-#if defined(RGX_FEATURE_COMPUTE_BIT_MASK)
-       if (ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
-#endif
-       {
-               eError = InitRGXCMPBridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXCMPBridge");
-       }
-
-       if (ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
-       {
-               eError = InitRGXSIGNALSBridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXCMPBridge");
-       }
-
-#if defined(RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
-       if (ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
-#endif
-       {
-               eError = InitRGXTQ2Bridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXTQ2Bridge");
-       }
-
-#if defined(RGX_FEATURE_RAY_TRACING_ARCH_MAX_VALUE_IDX)
-       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH))
-#endif
-       {
-#if defined(SUPPORT_RGXRAY_BRIDGE)
-               eError = InitRGXRAYBridge();
-               PVR_LOG_IF_ERROR(eError, "InitRGXRAYBridge");
-#endif
-       }
-
-       return PVRSRV_OK;
-}
-
-PVRSRV_ERROR
-DeviceDepBridgeDeInit(IMG_UINT64 ui64Features)
-{
-       PVRSRV_ERROR eError;
-
-#if defined(RGX_FEATURE_COMPUTE_BIT_MASK)
-       if (ui64Features & RGX_FEATURE_COMPUTE_BIT_MASK)
-#endif
-       {
-               eError = DeinitRGXCMPBridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXCMPBridge");
-       }
-
-       if (ui64Features & RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
-       {
-               eError = DeinitRGXSIGNALSBridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXSIGNALSBridge");
-       }
-
-#if defined(RGX_FEATURE_COMPUTE_BIT_MASK)
-       if (ui64Features & RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
-#endif
-       {
-               eError = DeinitRGXTQ2Bridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXTQ2Bridge");
-       }
-
-#if defined(RGX_FEATURE_RAY_TRACING_ARCH_MAX_VALUE_IDX)
-       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH))
-#endif
-       {
-#if defined(SUPPORT_RGXRAY_BRIDGE)
-               eError = DeinitRGXRAYBridge();
-               PVR_LOG_RETURN_IF_ERROR(eError, "DeinitRGXRAYBridge");
-#endif
-       }
-
-       return PVRSRV_OK;
-}
-#endif /* SUPPORT_RGX */
index 71b2810..d1fe2b2 100644 (file)
@@ -41,10 +41,16 @@ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
-
+#if defined(__linux__)
+ #include <linux/version.h>
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+  #include <linux/stdarg.h>
+ #else
+  #include <stdarg.h>
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+#else
+ #include <stdarg.h>
+#endif /* __linux__ */
 #include "img_defs.h"
 #include "allocmem.h"
 #include "pvr_debug.h"
index 94920be..42a8a82 100644 (file)
@@ -203,8 +203,6 @@ void BridgeDispatchTableStartOffsetsInit(void)
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXREGCONFIG][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXREGCONFIG_DISPATCH_LAST;
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXKICKSYNC][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_FIRST;
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXKICKSYNC][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXKICKSYNC_DISPATCH_LAST;
-       g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXSIGNALS][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_FIRST;
-       g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXSIGNALS][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXSIGNALS_DISPATCH_LAST;
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTQ2][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXTQ2_DISPATCH_FIRST;
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTQ2][PVR_DISPATCH_OFFSET_LAST_FUNC] = PVRSRV_BRIDGE_RGXTQ2_DISPATCH_LAST;
        g_BridgeDispatchTableStartOffsets[PVRSRV_BRIDGE_RGXTIMERQUERY][PVR_DISPATCH_OFFSET_FIRST_FUNC] = PVRSRV_BRIDGE_RGXTIMERQUERY_DISPATCH_FIRST;
@@ -226,7 +224,7 @@ PVRSRV_ERROR PVRSRVPrintBridgeStats()
                   "Total number of bytes copied via copy_from_user = %u\n"
                   "Total number of bytes copied via copy_to_user = %u\n"
                   "Total number of bytes copied via copy_*_user = %u\n\n"
-                  "%3s: %-60s | %-48s | %10s | %20s | %20s | %20s | %20s \n",
+                  "%3s: %-60s | %-48s | %10s | %20s | %20s | %20s | %20s\n",
                   g_BridgeGlobalStats.ui32IOCTLCount,
                   g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
                   g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
@@ -657,11 +655,32 @@ PVRSRVConnectKM(CONNECTION_DATA *psConnection,
                                __func__, ui32DDKBuild, ui32ClientDDKBuild));
        }
 
+#if defined(PDUMP)
        /* Success so far so is it the PDump client that is connecting? */
        if (ui32Flags & SRV_FLAGS_PDUMPCTRL)
        {
-               PDumpConnectionNotify();
+               if (psDeviceNode->sDevId.ui32InternalID == psSRVData->ui32PDumpBoundDevice)
+               {
+                       PDumpConnectionNotify(psDeviceNode);
+               }
+               else
+               {
+                       eError = PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE;
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PDump requested for device %u but only permitted for device %u",
+                                       __func__, psDeviceNode->sDevId.ui32InternalID, psSRVData->ui32PDumpBoundDevice));
+                       goto chk_exit;
+               }
        }
+       else
+       {
+               /* Warn if the app is connecting to a device PDump won't be able to capture */
+               if (psDeviceNode->sDevId.ui32InternalID != psSRVData->ui32PDumpBoundDevice)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: NB. App running on device %d won't be captured by PDump (must be on device %u)",
+                                       __func__, psDeviceNode->sDevId.ui32InternalID, psSRVData->ui32PDumpBoundDevice));
+               }
+       }
+#endif
 
        PVR_ASSERT(pui8KernelArch != NULL);
 
@@ -903,6 +922,14 @@ PVRSRV_ERROR PVRSRVGetMultiCoreInfoKM(CONNECTION_DATA *psConnection,
        PVRSRV_ERROR eError = PVRSRV_ERROR_NOT_SUPPORTED;
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       if (ui32CapsSize > 0)
+       {
+               /* Clear the buffer to ensure no uninitialised data is returned to UM
+                * if the pfn call below does not write to the whole array, or is null.
+                */
+               memset(pui64Caps, 0x00, (ui32CapsSize * sizeof(IMG_UINT64)));
+       }
+
        if (psDeviceNode->pfnGetMultiCoreInfo != NULL)
        {
                eError = psDeviceNode->pfnGetMultiCoreInfo(psDeviceNode, ui32CapsSize, pui32NumCores, pui64Caps);
@@ -1162,7 +1189,9 @@ PVRSRV_ERROR BridgedDispatchKM(CONNECTION_DATA * psConnection,
        BridgeWrapperFunction pfBridgeHandler;
        IMG_UINT32   ui32DispatchTableEntry, ui32GroupBoundary;
        PVRSRV_ERROR err = PVRSRV_OK;
+#if !defined(INTEGRITY_OS)
        PVRSRV_POOL_TOKEN hBridgeBufferPoolToken = NULL;
+#endif
        IMG_UINT32 ui32Timestamp = OSClockus();
 #if defined(DEBUG_BRIDGE_KM)
        IMG_UINT64      ui64TimeStart;
index 591c767..1bab1af 100644 (file)
@@ -60,14 +60,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv.h"
 #include "pdump_km.h"
 #include "info_page.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
 
 #include "pvrsrv_sync_km.h"
 #include "rgxhwperf.h"
 
 #if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
-#include "validation_soc.h"
+#include "rgxsoctimer.h"
 #endif
 
 #if defined(PVRSRV_NEED_PVR_DPF)
@@ -158,7 +156,7 @@ typedef struct _SYNC_CHECKPOINT_BLOCK_LIST_
        SYNC_CHECKPOINT_BLOCK **papsSyncCheckpointBlock; /*!< Array of sync checkpoint blocks */
 } SYNC_CHECKPOINT_BLOCK_LIST;
 
-typedef struct _SYNC_CHECKPOINT_CONTEXT_CTL_
+struct _SYNC_CHECKPOINT_CONTEXT_CTL_
 {
        SHARED_DEV_CONNECTION                                   psDeviceNode;
        PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN    pfnFenceResolve;
@@ -175,7 +173,7 @@ typedef struct _SYNC_CHECKPOINT_CONTEXT_CTL_
        POS_SPINLOCK                                                    hDeferredCleanupListLock;
 
 #if (SYNC_CHECKPOINT_POOL_SIZE > 0)
-       _SYNC_CHECKPOINT                                                *psSyncCheckpointPool[SYNC_CHECKPOINT_POOL_SIZE];
+       SYNC_CHECKPOINT                                         *psSyncCheckpointPool[SYNC_CHECKPOINT_POOL_SIZE];
        IMG_BOOL                                                                bSyncCheckpointPoolFull;
        IMG_BOOL                                                                bSyncCheckpointPoolValid;
        IMG_UINT32                                                              ui32SyncCheckpointPoolCount;
@@ -183,7 +181,7 @@ typedef struct _SYNC_CHECKPOINT_CONTEXT_CTL_
        IMG_UINT32                                                              ui32SyncCheckpointPoolRp;
        POS_SPINLOCK                                                    hSyncCheckpointPoolLock; /*! Protects access to the checkpoint pool control data. */
 #endif
-} _SYNC_CHECKPOINT_CONTEXT_CTL;
+}; /*_SYNC_CHECKPOINT_CONTEXT_CTL is already typedef-ed in sync_checkpoint_internal.h */
 
 /* this is the max number of sync checkpoint records we will search or dump
  * at any time.
@@ -209,8 +207,8 @@ struct SYNC_CHECKPOINT_RECORD
 static PFN_SYNC_CHECKPOINT_STRUCT *g_psSyncCheckpointPfnStruct = NULL;
 
 #if (SYNC_CHECKPOINT_POOL_SIZE > 0)
-static _SYNC_CHECKPOINT *_GetCheckpointFromPool(_SYNC_CHECKPOINT_CONTEXT *psContext);
-static IMG_BOOL _PutCheckpointInPool(_SYNC_CHECKPOINT *psSyncCheckpoint);
+static SYNC_CHECKPOINT *_GetCheckpointFromPool(_SYNC_CHECKPOINT_CONTEXT *psContext);
+static IMG_BOOL _PutCheckpointInPool(SYNC_CHECKPOINT *psSyncCheckpoint);
 static IMG_UINT32 _CleanCheckpointPool(_SYNC_CHECKPOINT_CONTEXT *psContext);
 #endif
 
@@ -226,7 +224,7 @@ static IMG_UINT32 gui32NumSyncCheckpointContexts = 0;
 
 #if defined(SUPPORT_RGX)
 static inline void RGXSRVHWPerfSyncCheckpointUFOIsSignalled(PVRSRV_RGXDEV_INFO *psDevInfo,
-                               _SYNC_CHECKPOINT *psSyncCheckpointInt, IMG_UINT32 ui32FenceSyncFlags)
+                               SYNC_CHECKPOINT *psSyncCheckpointInt, IMG_UINT32 ui32FenceSyncFlags)
 {
        if (RGXHWPerfHostIsEventEnabled(psDevInfo, RGX_HWPERF_HOST_UFO)
            && !(ui32FenceSyncFlags & PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
@@ -257,7 +255,7 @@ static inline void RGXSRVHWPerfSyncCheckpointUFOIsSignalled(PVRSRV_RGXDEV_INFO *
 }
 
 static inline void RGXSRVHWPerfSyncCheckpointUFOUpdate(PVRSRV_RGXDEV_INFO *psDevInfo,
-                               _SYNC_CHECKPOINT *psSyncCheckpointInt, IMG_UINT32 ui32FenceSyncFlags)
+                               SYNC_CHECKPOINT *psSyncCheckpointInt, IMG_UINT32 ui32FenceSyncFlags)
 {
        if (RGXHWPerfHostIsEventEnabled(psDevInfo, RGX_HWPERF_HOST_UFO)
            && !(ui32FenceSyncFlags & PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
@@ -299,8 +297,8 @@ static void _SyncCheckpointRecordListDeinit(PVRSRV_DEVICE_NODE *psDevNode);
 #if defined(PDUMP)
 static void
 MISRHandler_PdumpDeferredSyncSignalPoster(void *pvData);
-static PVRSRV_ERROR _SyncCheckpointAllocPDump(_SYNC_CHECKPOINT *psSyncCheckpoint);
-static PVRSRV_ERROR _SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, _SYNC_CHECKPOINT *psSyncCheckpoint, IMG_UINT32 ui32Status, IMG_UINT32 ui32FenceSyncFlags);
+static PVRSRV_ERROR _SyncCheckpointAllocPDump(PVRSRV_DEVICE_NODE *psDevNode, SYNC_CHECKPOINT *psSyncCheckpoint);
+static PVRSRV_ERROR _SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, SYNC_CHECKPOINT *psSyncCheckpoint, IMG_UINT32 ui32Status, IMG_UINT32 ui32FenceSyncFlags);
 static PVRSRV_ERROR _SyncCheckpointPDumpTransition(void *pvData, PDUMP_TRANSITION_EVENT eEvent);
 #endif
 
@@ -371,9 +369,6 @@ static PVRSRV_ERROR
 _AllocSyncCheckpointBlock(_SYNC_CHECKPOINT_CONTEXT *psContext,
                           SYNC_CHECKPOINT_BLOCK    **ppsSyncBlock)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_DEVICE_NODE *psDevNode;
        SYNC_CHECKPOINT_BLOCK *psSyncBlk;
        PVRSRV_ERROR eError;
@@ -398,22 +393,12 @@ _AllocSyncCheckpointBlock(_SYNC_CHECKPOINT_CONTEXT *psContext,
        eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
                                          (void **) &psSyncBlk->pui32LinAddr);
        PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail_devmem_acquire);
-       
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psSyncBlk->hMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                       printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                       BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psSyncBlk->pui32LinAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-               }
-#endif
 
        OSAtomicWrite(&psSyncBlk->hRefCount, 1);
 
        OSLockCreate(&psSyncBlk->hLock);
 
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS,
                              "Allocated Sync Checkpoint UFO block (FirmwareVAddr = 0x%08x)",
                              psSyncBlk->ui32FirmwareAddr);
 #if defined(PDUMP)
@@ -543,7 +528,7 @@ _SyncCheckpointBlockUnimport(RA_PERARENA_HANDLE hArena,
        SyncCheckpointContextUnref((PSYNC_CHECKPOINT_CONTEXT)psContext);
 }
 
-static INLINE IMG_UINT32 _SyncCheckpointGetOffset(_SYNC_CHECKPOINT *psSyncInt)
+static INLINE IMG_UINT32 _SyncCheckpointGetOffset(SYNC_CHECKPOINT *psSyncInt)
 {
        IMG_UINT64 ui64Temp;
 
@@ -589,7 +574,7 @@ SyncCheckpointResolveFence(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_UINT32 i;
 #if defined(PDUMP)
-       _SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
+       SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
 #endif
 
        if (unlikely(!g_psSyncCheckpointPfnStruct || !g_psSyncCheckpointPfnStruct->pfnFenceResolve))
@@ -623,7 +608,7 @@ SyncCheckpointResolveFence(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
        {
                for (i = 0; i < *pui32NumSyncCheckpoints; i++)
                {
-                       psSyncCheckpoint = (_SYNC_CHECKPOINT *)(*papsSyncCheckpoints)[i];
+                       psSyncCheckpoint = (SYNC_CHECKPOINT *)(*papsSyncCheckpoints)[i];
                        psSyncCheckpoint->ui32PDumpFlags = ui32PDumpFlags;
                }
        }
@@ -701,6 +686,7 @@ SyncCheckpointCreateFence(PVRSRV_DEVICE_NODE *psDevNode,
        else
        {
                eError = g_psSyncCheckpointPfnStruct->pfnFenceCreate(
+                                         psDevNode,
                                          pszFenceName,
                                          hTimeline,
                                          psSyncCheckpointContext,
@@ -739,7 +725,7 @@ SyncCheckpointCreateFence(PVRSRV_DEVICE_NODE *psDevNode,
 #if defined(PDUMP)
                if (eError == PVRSRV_OK)
                {
-                       _SYNC_CHECKPOINT *psSyncCheckpoint = (_SYNC_CHECKPOINT*)(*psNewSyncCheckpoint);
+                       SYNC_CHECKPOINT *psSyncCheckpoint = (SYNC_CHECKPOINT*)(*psNewSyncCheckpoint);
                        if (psSyncCheckpoint)
                        {
                                psSyncCheckpoint->ui32PDumpFlags = ui32PDumpFlags;
@@ -1009,7 +995,7 @@ fail_alloc:
 
 /* Poisons and frees the checkpoint
  * Decrements context refcount. */
-static void _FreeSyncCheckpoint(_SYNC_CHECKPOINT *psSyncCheckpoint)
+static void _FreeSyncCheckpoint(SYNC_CHECKPOINT *psSyncCheckpoint)
 {
        _SYNC_CHECKPOINT_CONTEXT *psContext = psSyncCheckpoint->psSyncCheckpointBlock->psContext;
 
@@ -1088,7 +1074,7 @@ PVRSRV_ERROR SyncCheckpointContextDestroy(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpo
 
                        dllist_foreach_node(&psDevNode->sSyncCheckpointSyncsList, psNode, psNext)
                        {
-                               _SYNC_CHECKPOINT *psSyncCheckpoint = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+                               SYNC_CHECKPOINT *psSyncCheckpoint = IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sListNode);
                                bool bDeferredFree = dllist_node_is_in_list(&psSyncCheckpoint->sDeferredFreeListNode);
 
                                /* Line below avoids build error in release builds (where PVR_DPF is not defined) */
@@ -1146,7 +1132,7 @@ SyncCheckpointAlloc(PSYNC_CHECKPOINT_CONTEXT psSyncContext,
                     const IMG_CHAR *pszCheckpointName,
                     PSYNC_CHECKPOINT *ppsSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psNewSyncCheckpoint = NULL;
+       SYNC_CHECKPOINT *psNewSyncCheckpoint = NULL;
        _SYNC_CHECKPOINT_CONTEXT *psSyncContextInt = (_SYNC_CHECKPOINT_CONTEXT*)psSyncContext;
        PVRSRV_DEVICE_NODE *psDevNode;
        PVRSRV_ERROR eError;
@@ -1250,7 +1236,7 @@ SyncCheckpointAlloc(PSYNC_CHECKPOINT_CONTEXT psSyncContext,
        /* Flushing deferred fence signals to pdump */
        MISRHandler_PdumpDeferredSyncSignalPoster(psDevNode);
 
-       _SyncCheckpointAllocPDump(psNewSyncCheckpoint);
+       _SyncCheckpointAllocPDump(psDevNode, psNewSyncCheckpoint);
 #endif
 
        RGXSRV_HWPERF_ALLOC_SYNC_CP(psDevNode, psNewSyncCheckpoint->hTimeline,
@@ -1319,7 +1305,7 @@ fail_alloc:
        return eError;
 }
 
-static void SyncCheckpointUnref(_SYNC_CHECKPOINT *psSyncCheckpointInt)
+static void SyncCheckpointUnref(SYNC_CHECKPOINT *psSyncCheckpointInt)
 {
        _SYNC_CHECKPOINT_CONTEXT *psContext;
        PVRSRV_DEVICE_NODE *psDevNode;
@@ -1438,7 +1424,7 @@ static void SyncCheckpointUnref(_SYNC_CHECKPOINT *psSyncCheckpointInt)
 
 void SyncCheckpointFree(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_RETURN_VOID_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1457,7 +1443,7 @@ void SyncCheckpointFree(PSYNC_CHECKPOINT psSyncCheckpoint)
 void
 SyncCheckpointSignal(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSyncFlags)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1495,7 +1481,7 @@ SyncCheckpointSignal(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSync
 void
 SyncCheckpointSignalNoHW(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1531,7 +1517,7 @@ SyncCheckpointSignalNoHW(PSYNC_CHECKPOINT psSyncCheckpoint)
 void
 SyncCheckpointError(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSyncFlags)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1569,7 +1555,7 @@ SyncCheckpointError(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSyncF
 IMG_BOOL SyncCheckpointIsSignalled(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSyncFlags)
 {
        IMG_BOOL bRet = IMG_FALSE;
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1598,7 +1584,7 @@ IMG_BOOL
 SyncCheckpointIsErrored(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceSyncFlags)
 {
        IMG_BOOL bRet = IMG_FALSE;
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid");
 
@@ -1625,7 +1611,7 @@ SyncCheckpointIsErrored(PSYNC_CHECKPOINT psSyncCheckpoint, IMG_UINT32 ui32FenceS
 const IMG_CHAR *
 SyncCheckpointGetStateString(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_RETURN_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", "Null");
 
@@ -1648,7 +1634,7 @@ PVRSRV_ERROR
 SyncCheckpointTakeRef(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
        PVRSRV_ERROR eRet = PVRSRV_OK;
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(psSyncCheckpoint, "psSyncCheckpoint");
 
@@ -1669,7 +1655,7 @@ PVRSRV_ERROR
 SyncCheckpointDropRef(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
        PVRSRV_ERROR eRet = PVRSRV_OK;
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_RETURN_IF_INVALID_PARAM(psSyncCheckpoint, "psSyncCheckpoint");
 
@@ -1689,7 +1675,7 @@ SyncCheckpointDropRef(PSYNC_CHECKPOINT psSyncCheckpoint)
 void
 SyncCheckpointCCBEnqueued(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_RETURN_VOID_IF_FALSE(psSyncCheckpoint != NULL, "psSyncCheckpoint");
 
@@ -1712,7 +1698,7 @@ SyncCheckpointCCBEnqueued(PSYNC_CHECKPOINT psSyncCheckpoint)
 PRGXFWIF_UFO_ADDR*
 SyncCheckpointGetRGXFWIFUFOAddr(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
 
        PVR_LOG_GOTO_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", invalid_chkpt);
 
@@ -1739,7 +1725,7 @@ invalid_chkpt:
 IMG_UINT32
 SyncCheckpointGetFirmwareAddr(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        IMG_UINT32 ui32Ret = 0;
 
        PVR_LOG_GOTO_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", invalid_chkpt);
@@ -1767,7 +1753,7 @@ invalid_chkpt:
 IMG_UINT32
 SyncCheckpointGetId(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        IMG_UINT32 ui32Ret = 0;
 
        PVR_LOG_GOTO_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", invalid_chkpt);
@@ -1801,7 +1787,7 @@ invalid_chkpt:
 PVRSRV_TIMELINE
 SyncCheckpointGetTimeline(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        PVRSRV_TIMELINE i32Ret = PVRSRV_NO_TIMELINE;
 
        PVR_LOG_GOTO_IF_FALSE((psSyncCheckpoint != NULL), "psSyncCheckpoint invalid", invalid_chkpt);
@@ -1820,7 +1806,7 @@ invalid_chkpt:
 IMG_UINT32
 SyncCheckpointGetEnqueuedCount(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        PVR_LOG_RETURN_IF_FALSE(psSyncCheckpoint != NULL, "psSyncCheckpoint invalid", 0);
 
        return OSAtomicRead(&psSyncCheckpointInt->hEnqueuedCCBCount);
@@ -1829,7 +1815,7 @@ SyncCheckpointGetEnqueuedCount(PSYNC_CHECKPOINT psSyncCheckpoint)
 IMG_UINT32
 SyncCheckpointGetReferenceCount(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        PVR_LOG_RETURN_IF_FALSE(psSyncCheckpoint != NULL, "psSyncCheckpoint invalid", 0);
 
        return OSAtomicRead(&psSyncCheckpointInt->hRefCount);
@@ -1838,7 +1824,7 @@ SyncCheckpointGetReferenceCount(PSYNC_CHECKPOINT psSyncCheckpoint)
 IMG_PID
 SyncCheckpointGetCreator(PSYNC_CHECKPOINT psSyncCheckpoint)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt = (_SYNC_CHECKPOINT*)psSyncCheckpoint;
+       SYNC_CHECKPOINT *psSyncCheckpointInt = (SYNC_CHECKPOINT*)psSyncCheckpoint;
        PVR_LOG_RETURN_IF_FALSE(psSyncCheckpoint != NULL, "psSyncCheckpoint invalid", 0);
 
        return psSyncCheckpointInt->uiProcess;
@@ -1847,7 +1833,7 @@ SyncCheckpointGetCreator(PSYNC_CHECKPOINT psSyncCheckpoint)
 IMG_UINT32 SyncCheckpointStateFromUFO(PPVRSRV_DEVICE_NODE psDevNode,
                                 IMG_UINT32 ui32FwAddr)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt;
+       SYNC_CHECKPOINT *psSyncCheckpointInt;
        PDLLIST_NODE psNode, psNext;
        IMG_UINT32 ui32State = 0;
        OS_SPINLOCK_FLAGS uiFlags;
@@ -1855,7 +1841,7 @@ IMG_UINT32 SyncCheckpointStateFromUFO(PPVRSRV_DEVICE_NODE psDevNode,
        OSSpinLockAcquire(psDevNode->hSyncCheckpointListLock, uiFlags);
        dllist_foreach_node(&psDevNode->sSyncCheckpointSyncsList, psNode, psNext)
        {
-               psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+               psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sListNode);
                if (ui32FwAddr == SyncCheckpointGetFirmwareAddr((PSYNC_CHECKPOINT)psSyncCheckpointInt))
                {
                        ui32State = psSyncCheckpointInt->psSyncCheckpointFwObj->ui32State;
@@ -1869,7 +1855,7 @@ IMG_UINT32 SyncCheckpointStateFromUFO(PPVRSRV_DEVICE_NODE psDevNode,
 void SyncCheckpointErrorFromUFO(PPVRSRV_DEVICE_NODE psDevNode,
                                 IMG_UINT32 ui32FwAddr)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpointInt;
+       SYNC_CHECKPOINT *psSyncCheckpointInt;
        PDLLIST_NODE psNode, psNext;
        OS_SPINLOCK_FLAGS uiFlags;
 
@@ -1883,7 +1869,7 @@ void SyncCheckpointErrorFromUFO(PPVRSRV_DEVICE_NODE psDevNode,
        OSSpinLockAcquire(psDevNode->hSyncCheckpointListLock, uiFlags);
        dllist_foreach_node(&psDevNode->sSyncCheckpointSyncsList, psNode, psNext)
        {
-               psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+               psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sListNode);
                if (ui32FwAddr == SyncCheckpointGetFirmwareAddr((PSYNC_CHECKPOINT)psSyncCheckpointInt))
                {
 #if (ENABLE_SYNC_CHECKPOINT_UFO_DEBUG == 1)
@@ -1910,14 +1896,14 @@ void SyncCheckpointRollbackFromUFO(PPVRSRV_DEVICE_NODE psDevNode, IMG_UINT32 ui3
 #endif
 #if !defined(NO_HARDWARE)
        {
-               _SYNC_CHECKPOINT *psSyncCheckpointInt = NULL;
+               SYNC_CHECKPOINT *psSyncCheckpointInt = NULL;
                PDLLIST_NODE psNode = NULL, psNext = NULL;
                OS_SPINLOCK_FLAGS uiFlags;
 
                OSSpinLockAcquire(psDevNode->hSyncCheckpointListLock, uiFlags);
                dllist_foreach_node(&psDevNode->sSyncCheckpointSyncsList, psNode, psNext)
                {
-                       psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+                       psSyncCheckpointInt = IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sListNode);
                        if (ui32FwAddr == SyncCheckpointGetFirmwareAddr((PSYNC_CHECKPOINT)psSyncCheckpointInt))
                        {
 #if ((ENABLE_SYNC_CHECKPOINT_UFO_DEBUG == 1)) || (ENABLE_SYNC_CHECKPOINT_ENQ_AND_SIGNAL_DEBUG == 1)
@@ -1941,7 +1927,7 @@ static void _SyncCheckpointState(PDLLIST_NODE psNode,
                                        DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        void *pvDumpDebugFile)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpoint = IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sListNode);
+       SYNC_CHECKPOINT *psSyncCheckpoint = IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sListNode);
 
        if (psSyncCheckpoint->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_ACTIVE)
        {
@@ -1992,11 +1978,11 @@ SyncCheckpointInit(PPVRSRV_DEVICE_NODE psDevNode)
 
        dllist_init(&psDevNode->sSyncCheckpointSyncsList);
 
-       eError = PVRSRVRegisterDbgRequestNotify(&psDevNode->hSyncCheckpointNotify,
-                                                                               psDevNode,
-                                                                               _SyncCheckpointDebugRequest,
-                                                                               DEBUG_REQUEST_SYNCCHECKPOINT,
-                                                                               (PVRSRV_DBGREQ_HANDLE)psDevNode);
+       eError = PVRSRVRegisterDeviceDbgRequestNotify(&psDevNode->hSyncCheckpointNotify,
+                                                         psDevNode,
+                                                         _SyncCheckpointDebugRequest,
+                                                         DEBUG_REQUEST_SYNCCHECKPOINT,
+                                                         (PVRSRV_DBGREQ_HANDLE)psDevNode);
        PVR_GOTO_IF_ERROR(eError, e0);
 
        if (GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED)
@@ -2121,7 +2107,7 @@ void SyncCheckpointDeinit(PPVRSRV_DEVICE_NODE psDevNode)
        }
 #endif
 
-       PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncCheckpointNotify);
+       PVRSRVUnregisterDeviceDbgRequestNotify(psDevNode->hSyncCheckpointNotify);
        psDevNode->hSyncCheckpointNotify = NULL;
        OSSpinLockDestroy(psDevNode->hSyncCheckpointListLock);
        psDevNode->hSyncCheckpointListLock = NULL;
@@ -2302,7 +2288,7 @@ static void _SyncCheckpointRecordPrint(struct SYNC_CHECKPOINT_RECORD *psSyncChec
                                        DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        void *pvDumpDebugFile)
 {
-       _SYNC_CHECKPOINT *psSyncCheckpoint = (_SYNC_CHECKPOINT *)psSyncCheckpointRec->pSyncCheckpt;
+       SYNC_CHECKPOINT *psSyncCheckpoint = (SYNC_CHECKPOINT *)psSyncCheckpointRec->pSyncCheckpt;
        SYNC_CHECKPOINT_BLOCK *psSyncCheckpointBlock = psSyncCheckpointRec->psSyncCheckpointBlock;
        IMG_UINT64 ui64DeltaS;
        IMG_UINT32 ui32DeltaF;
@@ -2413,11 +2399,11 @@ static PVRSRV_ERROR _SyncCheckpointRecordListInit(PVRSRV_DEVICE_NODE *psDevNode)
        psDevNode->ui32SyncCheckpointRecordCount = 0;
        psDevNode->ui32SyncCheckpointRecordCountHighWatermark = 0;
 
-       eError = PVRSRVRegisterDbgRequestNotify(&psDevNode->hSyncCheckpointRecordNotify,
-                                               psDevNode,
-                                               _SyncCheckpointRecordRequest,
-                                               DEBUG_REQUEST_SYNCCHECKPOINT,
-                                               (PVRSRV_DBGREQ_HANDLE)psDevNode);
+       eError = PVRSRVRegisterDeviceDbgRequestNotify(&psDevNode->hSyncCheckpointRecordNotify,
+                                                     psDevNode,
+                                                     _SyncCheckpointRecordRequest,
+                                                     DEBUG_REQUEST_SYNCCHECKPOINT,
+                                                     (PVRSRV_DBGREQ_HANDLE)psDevNode);
        PVR_GOTO_IF_ERROR(eError, fail_dbg_register);
 
        return PVRSRV_OK;
@@ -2455,7 +2441,7 @@ static void _SyncCheckpointRecordListDeinit(PVRSRV_DEVICE_NODE *psDevNode)
 
        if (psDevNode->hSyncCheckpointRecordNotify)
        {
-               PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncCheckpointRecordNotify);
+               PVRSRVUnregisterDeviceDbgRequestNotify(psDevNode->hSyncCheckpointRecordNotify);
        }
        OSLockDestroy(psDevNode->hSyncCheckpointRecordLock);
 }
@@ -2463,9 +2449,9 @@ static void _SyncCheckpointRecordListDeinit(PVRSRV_DEVICE_NODE *psDevNode)
 #if defined(PDUMP)
 
 static PVRSRV_ERROR
-_SyncCheckpointAllocPDump(_SYNC_CHECKPOINT *psSyncCheckpoint)
+_SyncCheckpointAllocPDump(PVRSRV_DEVICE_NODE *psDevNode, SYNC_CHECKPOINT *psSyncCheckpoint)
 {
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS,
                              "Allocated Sync Checkpoint %s (ID:%d, TL:%d, FirmwareVAddr = 0x%08x)",
                              psSyncCheckpoint->azName,
                              psSyncCheckpoint->ui32UID, psSyncCheckpoint->hTimeline,
@@ -2480,7 +2466,7 @@ _SyncCheckpointAllocPDump(_SYNC_CHECKPOINT *psSyncCheckpoint)
 }
 
 static PVRSRV_ERROR
-_SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, _SYNC_CHECKPOINT *psSyncCheckpoint, IMG_UINT32 ui32Status, IMG_UINT32 ui32FenceSyncFlags)
+_SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, SYNC_CHECKPOINT *psSyncCheckpoint, IMG_UINT32 ui32Status, IMG_UINT32 ui32FenceSyncFlags)
 {
        IMG_BOOL bSleepAllowed = (ui32FenceSyncFlags & PVRSRV_FENCE_FLAG_CTX_ATOMIC) ? IMG_FALSE : IMG_TRUE;
        PVRSRV_RGXDEV_INFO *psDevInfo;
@@ -2494,7 +2480,7 @@ _SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, _SYNC_CHECKPOINT *psSy
        {
                if (ui32Status == PVRSRV_SYNC_CHECKPOINT_ERRORED)
                {
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS,
                                        "Errored Sync Checkpoint %s (ID:%d, TL:%d, FirmwareVAddr = 0x%08x)",
                                        psSyncCheckpoint->azName,
                                        psSyncCheckpoint->ui32UID, psSyncCheckpoint->hTimeline,
@@ -2503,7 +2489,7 @@ _SyncCheckpointUpdatePDump(PPVRSRV_DEVICE_NODE psDevNode, _SYNC_CHECKPOINT *psSy
                }
                else
                {
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+                       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS,
                                        "Signalled Sync Checkpoint %s (ID:%d, TL:%d, FirmwareVAddr = 0x%08x)",
                                        psSyncCheckpoint->azName,
                                        psSyncCheckpoint->ui32UID, psSyncCheckpoint->hTimeline,
@@ -2594,7 +2580,7 @@ PVRSRV_ERROR PVRSRVSyncCheckpointSignalledPDumpPolKM(PVRSRV_FENCE hFence)
 {
        PVRSRV_ERROR eError;
        PSYNC_CHECKPOINT *apsCheckpoints = NULL;
-       _SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
+       SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
        IMG_UINT32 i, uiNumCheckpoints = 0;
 #if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER) && defined(NO_HARDWARE) && defined(PDUMP)
        PVRSRV_RGXDEV_INFO *psDevInfo;
@@ -2614,16 +2600,17 @@ PVRSRV_ERROR PVRSRVSyncCheckpointSignalledPDumpPolKM(PVRSRV_FENCE hFence)
        if (uiNumCheckpoints)
        {
                /* Flushing deferred fence signals to pdump */
-               psSyncCheckpoint = (_SYNC_CHECKPOINT *)apsCheckpoints[0];
+               psSyncCheckpoint = (SYNC_CHECKPOINT *)apsCheckpoints[0];
                MISRHandler_PdumpDeferredSyncSignalPoster(psSyncCheckpoint->psSyncCheckpointBlock->psDevNode);
        }
 
        for (i=0; i < uiNumCheckpoints; i++)
        {
-               psSyncCheckpoint = (_SYNC_CHECKPOINT *)apsCheckpoints[i];
+               psSyncCheckpoint = (SYNC_CHECKPOINT *)apsCheckpoints[i];
                if (psSyncCheckpoint->psSyncCheckpointFwObj->ui32State == PVRSRV_SYNC_CHECKPOINT_SIGNALLED)
                {
-                       PDUMPCOMMENTWITHFLAGS(psSyncCheckpoint->ui32PDumpFlags,
+                       PDUMPCOMMENTWITHFLAGS(psSyncCheckpoint->psSyncCheckpointBlock->psDevNode,
+                                                       psSyncCheckpoint->ui32PDumpFlags,
                                                        "Wait for Fence %s (ID:%d)",
                                                        psSyncCheckpoint->azName,
                                                        psSyncCheckpoint->ui32UID);
@@ -2642,11 +2629,11 @@ PVRSRV_ERROR PVRSRVSyncCheckpointSignalledPDumpPolKM(PVRSRV_FENCE hFence)
        /* Sampling of USC timers can only be done after synchronisation for a 3D kick is over */
        if (uiNumCheckpoints)
        {
-               psSyncCheckpoint = (_SYNC_CHECKPOINT *)apsCheckpoints[0];
+               psSyncCheckpoint = (SYNC_CHECKPOINT *)apsCheckpoints[0];
                psDevInfo = psSyncCheckpoint->psSyncCheckpointBlock->psDevNode->pvDevice;
                if (psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER)
                {
-                       PVRSRVValidateSOCUSCTimer(psDevInfo, PDUMP_CONT, 0, 0, NULL);
+                       RGXValidateSOCUSCTimer(psDevInfo, PDUMP_CONT, 0, 0, NULL);
                }
        }
 #endif
@@ -2721,8 +2708,8 @@ static void _CheckDeferredCleanupList(_SYNC_CHECKPOINT_CONTEXT *psContext)
 
        dllist_foreach_node(&psCtxCtl->sDeferredCleanupListHead, psNode, psNext)
        {
-               _SYNC_CHECKPOINT *psSyncCheckpointInt =
-                               IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sDeferredFreeListNode);
+               SYNC_CHECKPOINT *psSyncCheckpointInt =
+                               IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sDeferredFreeListNode);
 
                if (psSyncCheckpointInt->psSyncCheckpointFwObj->ui32FwRefCount ==
                                (IMG_UINT32)(OSAtomicRead(&psSyncCheckpointInt->hEnqueuedCCBCount)))
@@ -2758,8 +2745,8 @@ static void _CheckDeferredCleanupList(_SYNC_CHECKPOINT_CONTEXT *psContext)
        OSSpinLockRelease(psCtxCtl->hDeferredCleanupListLock, uiFlags);
 
        dllist_foreach_node(&sCleanupList, psNode, psNext) {
-               _SYNC_CHECKPOINT *psSyncCheckpointInt =
-                               IMG_CONTAINER_OF(psNode, _SYNC_CHECKPOINT, sDeferredFreeListNode);
+               SYNC_CHECKPOINT *psSyncCheckpointInt =
+                               IMG_CONTAINER_OF(psNode, SYNC_CHECKPOINT, sDeferredFreeListNode);
 
                /* Remove the sync checkpoint from the global list */
                OSSpinLockAcquire(psDevNode->hSyncCheckpointListLock, uiFlags);
@@ -2803,10 +2790,10 @@ static void _CheckDeferredCleanupList(_SYNC_CHECKPOINT_CONTEXT *psContext)
 }
 
 #if (SYNC_CHECKPOINT_POOL_SIZE > 0)
-static _SYNC_CHECKPOINT *_GetCheckpointFromPool(_SYNC_CHECKPOINT_CONTEXT *psContext)
+static SYNC_CHECKPOINT *_GetCheckpointFromPool(_SYNC_CHECKPOINT_CONTEXT *psContext)
 {
        _SYNC_CHECKPOINT_CONTEXT_CTL *const psCtxCtl = psContext->psContextCtl;
-       _SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
+       SYNC_CHECKPOINT *psSyncCheckpoint = NULL;
        OS_SPINLOCK_FLAGS uiFlags;
 
        /* Acquire sync checkpoint pool lock */
@@ -2843,7 +2830,7 @@ static _SYNC_CHECKPOINT *_GetCheckpointFromPool(_SYNC_CHECKPOINT_CONTEXT *psCont
        return psSyncCheckpoint;
 }
 
-static IMG_BOOL _PutCheckpointInPool(_SYNC_CHECKPOINT *psSyncCheckpoint)
+static IMG_BOOL _PutCheckpointInPool(SYNC_CHECKPOINT *psSyncCheckpoint)
 {
        _SYNC_CHECKPOINT_CONTEXT *psContext = psSyncCheckpoint->psSyncCheckpointBlock->psContext;
        _SYNC_CHECKPOINT_CONTEXT_CTL *const psCtxCtl = psContext->psContextCtl;
@@ -2887,7 +2874,7 @@ static IMG_BOOL _PutCheckpointInPool(_SYNC_CHECKPOINT *psSyncCheckpoint)
 static IMG_UINT32 _CleanCheckpointPool(_SYNC_CHECKPOINT_CONTEXT *psContext)
 {
        _SYNC_CHECKPOINT_CONTEXT_CTL *const psCtxCtl = psContext->psContextCtl;
-       _SYNC_CHECKPOINT *psCheckpoint = NULL;
+       SYNC_CHECKPOINT *psCheckpoint = NULL;
        DECLARE_DLLIST(sCleanupList);
        DLLIST_NODE *psThis, *psNext;
        OS_SPINLOCK_FLAGS uiFlags;
@@ -2944,7 +2931,7 @@ static IMG_UINT32 _CleanCheckpointPool(_SYNC_CHECKPOINT_CONTEXT *psContext)
 
        dllist_foreach_node(&sCleanupList, psThis, psNext)
        {
-               psCheckpoint = IMG_CONTAINER_OF(psThis, _SYNC_CHECKPOINT, sListNode);
+               psCheckpoint = IMG_CONTAINER_OF(psThis, SYNC_CHECKPOINT, sListNode);
 
 #if (ENABLE_SYNC_CHECKPOINT_POOL_DEBUG == 1)
                if (psCheckpoint->ui32ValidationCheck != SYNC_CHECKPOINT_PATTERN_IN_POOL)
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/common/sync_fallback_server.c b/drivers/gpu/drm/img/img-rogue/services/server/common/sync_fallback_server.c
new file mode 100644 (file)
index 0000000..c1916e2
--- /dev/null
@@ -0,0 +1,3138 @@
+/*************************************************************************/ /*!
+@File           sync_fallback_server.c
+@Title          Fallback implementation of server fence sync interface.
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    The server implementation of software fallback synchronisation.
+@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(DEBUG)
+#define PVR_DPF_FUNCTION_TRACE_ON 1
+#endif
+
+#include "pvr_debug.h"
+#include "img_types.h"
+#include "img_defs.h"
+#include "pvrsrv_error.h"
+#include "pvrsrv_sync_km.h"
+#include "pvrsrv_sync_server.h"
+#include "sync_fallback_server.h"
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_external.h"
+#include "sync_checkpoint_internal.h"
+#include "osfunc.h"
+#include "lock.h"
+#include "handle.h"
+#include "pvrsrv.h"
+#include "hash.h"
+#include "rgxhwperf.h"
+#include "pdump_km.h"
+#include "allocmem.h"
+
+#if defined(PVR_TESTING_UTILS)
+#include "tutils_km.h"
+#endif
+
+#include "ossecure_export.h"
+
+/* Refcounting debug.
+ * Define SYNC_FB_REF_DEBUG to print out a reference count log. */
+// #define SYNC_FB_REF_DEBUG 1
+
+#if defined(SYNC_FB_REF_DEBUG)
+#define PRINT_REF(type, opchr, pRef, ptr, name, info, num) \
+       PVR_LOG(("        %s REF(%c) -> %d - %6s: %-5u - %-30s (0x%p)", type, opchr, pRef, info, num, name, ptr))
+#else
+#define PRINT_REF(type, opchr, pRef, ptr, name, info, num)
+#endif
+
+#define REF_SET(type, pRef, val, ptr, name, info, num) OSAtomicWrite(pRef, val); PRINT_REF(type, '=', val, ptr, name, info, num)
+#define REF_INC(type, pRef,      ptr, name, info, num) OSAtomicIncrement(pRef); PRINT_REF(type, '+', OSAtomicRead(pRef), ptr, name, info, num)
+#define REF_DEC(type, pRef,      ptr, name, info, num) OSAtomicDecrement(pRef); PRINT_REF(type, '-', OSAtomicRead(pRef), ptr, name, info, num)
+
+/* Timelines */
+#define TL_REF_SET(pRef, val, ptr) REF_SET("TL", pRef, val, ptr, ptr->pszName, "UID", (IMG_UINT64) ptr->iUID)
+#define TL_REF_INC(pRef, ptr)      REF_INC("TL", pRef,      ptr, ptr->pszName, "UID", (IMG_UINT64) ptr->iUID)
+#define TL_REF_DEC(pRef, ptr)      REF_DEC("TL", pRef,      ptr, ptr->pszName, "UID", (IMG_UINT64) ptr->iUID)
+
+/* Fences */
+#define FENCE_REF_SET(pRef, val, ptr) REF_SET("FE", pRef, val, ptr, ptr->pszName, "#Syncs", ptr->uiNumSyncs)
+#define FENCE_REF_INC(pRef, ptr)      REF_INC("FE", pRef,      ptr, ptr->pszName, "#Syncs", ptr->uiNumSyncs)
+#define FENCE_REF_DEC(pRef, ptr)      REF_DEC("FE", pRef,      ptr, ptr->pszName, "#Syncs", ptr->uiNumSyncs)
+
+/* SyncPt */
+#define PT_REF_SET(pRef, val, ptr) REF_SET("PT", pRef, val, ptr, ptr->psTl->pszName, "SeqNum" ,ptr->uiSeqNum)
+#define PT_REF_INC(pRef, ptr)      REF_INC("PT", pRef,      ptr, ptr->psTl->pszName, "SeqNum" ,ptr->uiSeqNum)
+#define PT_REF_DEC(pRef, ptr)      REF_DEC("PT", pRef,      ptr, ptr->psTl->pszName, "SeqNum" ,ptr->uiSeqNum)
+
+
+/* Simple prints for error and warning */
+#define ERR(msg, ...) PVR_DPF((PVR_DBG_ERROR, \
+                          "%s: " msg, \
+                          __func__, \
+                          ##__VA_ARGS__));
+
+#define WRN(msg, ...) PVR_DPF((PVR_DBG_WARNING, \
+                          "%s: " msg, \
+                          __func__, \
+                          ##__VA_ARGS__));
+
+// #define SYNC_FB_DEBUG 1
+#if defined(SYNC_FB_DEBUG)
+#define DBG(...) PVR_LOG(__VA_ARGS__)
+#else
+#define DBG(...)
+#endif
+
+/* Functions for timelines */
+typedef IMG_BOOL (*PFN_SYNC_PT_HAS_SIGNALLED)(PVRSRV_SYNC_PT *psSyncPt);
+typedef void (*PFN_SYNC_FREE) (IMG_HANDLE hAttachedSync);
+
+
+/* The states a SyncPt can be in */
+typedef enum
+{
+       PVRSRV_SYNC_NOT_SIGNALLED,     /*!< sync pt has not yet signalled */
+       PVRSRV_SYNC_SIGNALLED,         /*!< sync pt has signalled */
+       PVRSRV_SYNC_ERRORED            /*!< sync pt has errored*/
+} PVRSRV_SYNC_STATE;
+
+typedef enum
+{
+       PVRSRV_SYNC_HANDLE_UNKNOWN,
+       PVRSRV_SYNC_HANDLE_PVR,
+       PVRSRV_SYNC_HANDLE_SW
+} PVRSRV_SYNC_HANDLE_TYPE;
+
+typedef struct _PVRSRV_SYNC_SIGNAL_CB_
+{
+       DLLIST_NODE sCallbackNode;
+       IMG_HANDLE  hAttachedSync;
+       IMG_HANDLE  hPrivData;
+       PVRSRV_ERROR (*pfnSignal)(IMG_HANDLE hAttachedSync,
+                                 PVRSRV_SYNC_STATE eState);
+       PFN_SYNC_FREE pfnSyncFree;
+
+} PVRSRV_SYNC_SIGNAL_CB;
+
+struct _PVRSRV_SYNC_PT_
+{
+       /* The timeline this sync pt is associated with */
+       PVRSRV_TIMELINE_SERVER  *psTl;
+       IMG_UINT32                              uiSeqNum;
+       /* Refcount */
+       ATOMIC_T                                iRef;
+       /* Timeline list. Take TL lock! */
+       DLLIST_NODE                             sTlSyncList;
+       /* Timeline active list. Take TL lock! */
+       DLLIST_NODE                             sTlSyncActiveList;
+
+       /* List of callbacks to signal attached syncs.
+        *
+        * THE FIRST ITEM OF THIS LIST DEFINES THE FLAVOUR OF THE SYNC PT
+        * AND MUST BE CREATED TOGETHER WITH THE SYNC PT!
+        * Usually this is done when creating a fence.
+        * E.g. if PVR has been asked to create a fence we would
+        * create a sync pt for it with an attached sync checkpoint.
+        *
+        * In case someone waits for this sync pt who is not able
+        * to access the first item, a new foreign sync
+        * needs to be attached that can be read by the waiter.
+        * This might be the case if a second device is involved that cannot
+        * access sync checkpoints of another device or a device that needs
+        * to wait for a different sync type that it is not able to read
+        * e.g. a SW sync */
+       DLLIST_NODE                             sSignalCallbacks;
+       /* Can have a PVRSRV_SYNC_STATE */
+       ATOMIC_T                                iStatus;
+       /* PID of the sync pt creator, used for cleanup-unblocking */
+       IMG_UINT32                              uiPID;
+};
+
+/* Definition representing an attached SW sync pt.
+ * This is the counterpart to the SYNC_CHECKPOINTS for syncs that get
+ * signalled by the CPU. */
+typedef struct _PVRSRV_SYNC_PT_SW_
+{
+        IMG_BOOL bSignalled;
+} PVRSRV_SYNC_PT_SW;
+
+/*! Possible states for a PVRSRV_FENCE */
+typedef enum
+{
+    PVRSRV_FENCE_NOT_SIGNALLED,             /*!< fence has not yet signalled (not all components have signalled) */
+    PVRSRV_FENCE_SIGNALLED                  /*!< fence has signalled (all components have signalled/errored) */
+} PVRSRV_FENCE_STATE;
+
+struct _PVRSRV_FENCE_SERVER_
+{
+       IMG_UINT32                      uiNumSyncs;
+       PVRSRV_SYNC_PT          **apsFenceSyncList;
+       ATOMIC_T                        iRef;
+       /* Only written to when waiter checks if fence is met */
+       ATOMIC_T                        iStatus;
+       IMG_INT64                       iUID;
+       IMG_CHAR                        pszName[SYNC_FB_FENCE_MAX_LENGTH];
+       PVRSRV_DEVICE_NODE      *psDevNode;
+       DLLIST_NODE                     sFenceListNode;
+};
+
+struct _PVRSRV_FENCE_EXPORT_
+{
+       PVRSRV_FENCE_SERVER *psFence;
+};
+
+typedef struct _PVRSRV_TIMELINE_OPS_
+{
+       /* Supposed to be called when someone queries the TL
+        * to update its active generic syncs */
+       PFN_SYNC_PT_HAS_SIGNALLED pfnSyncPtHasSignalled;
+} PVRSRV_TIMELINE_OPS;
+
+struct _PVRSRV_TIMELINE_SERVER_
+{
+       /* Never take the fence lock after this one */
+       POS_LOCK                        hTlLock;
+       /* Timeline list. Contains all sync pts of the timeline that
+        * were not destroyed. Signalled or unsignalled. Take TL lock! */
+       DLLIST_NODE                     sSyncList;
+       /* Timeline active list. Contains all sync pts of the timeline
+        * that were not signalled yet.
+        * Before removing node, check if it's still in list. Take TL lock! */
+       DLLIST_NODE                     sSyncActiveList;
+       IMG_CHAR                        pszName[SYNC_FB_TIMELINE_MAX_LENGTH];
+       ATOMIC_T                        iRef;
+       PVRSRV_TIMELINE_OPS sTlOps;
+       DLLIST_NODE                     sTlList;
+       /* This ID helps to order the sync pts in a fence when merging */
+       IMG_INT64                       iUID;
+       /* The sequence number of the last sync pt created */
+       ATOMIC_T                        iSeqNum;
+       /* The sequence number of the latest signalled sync pt */
+       ATOMIC_T                        iLastSignalledSeqNum;
+       /* The PID of the process which created this timeline */
+       IMG_PID                         uiPID;
+};
+
+typedef struct _SYNC_FB_CONTEXT_DEVICE_LIST_
+{
+       DLLIST_NODE sDeviceListNode;
+       IMG_HANDLE hDBGNotify;
+       PVRSRV_DEVICE_NODE *psDevice;
+} SYNC_FB_CONTEXT_DEVICE_LIST;
+
+typedef struct _SYNC_FB_CONTEXT_
+{
+       IMG_HANDLE hSyncEventObject;
+       IMG_HANDLE hCMDNotify;
+       DLLIST_NODE sDeviceList;
+       DLLIST_NODE sTlList;
+       POS_LOCK hFbContextLock;
+       DLLIST_NODE sFenceList; /* protected by hFbContextLock */
+       HASH_TABLE *sCheckpointHashTable; /* protected by hFbContextLock */
+       PFN_SYNC_CHECKPOINT_STRUCT sSyncCheckpointReg;
+} SYNC_FB_CONTEXT;
+
+/* GLOBALS */
+static SYNC_FB_CONTEXT gsSyncFbContext;
+
+/* Declarations */
+static void _SyncFbTimelineAcquire(PVRSRV_TIMELINE_SERVER *psTl);
+static void _SyncFbFenceAcquire(PVRSRV_FENCE_SERVER *psFence);
+static PVRSRV_ERROR _SyncFbSyncPtSignalAttached(PVRSRV_SYNC_PT *psSyncPt,
+                                        PVRSRV_SYNC_STATE eSignal);
+static PVRSRV_ERROR SyncFbFenceRollbackPVR(PVRSRV_FENCE iFence, void *pvFenceData);
+static PVRSRV_ERROR _SyncFbSyncPtSignalPVR(IMG_HANDLE hSync,
+                                           PVRSRV_SYNC_STATE eState);
+static PVRSRV_ERROR _SyncFbSyncPtSignalSW(IMG_HANDLE hSync,
+                                          PVRSRV_SYNC_STATE eState);
+static IMG_BOOL _SyncFbFenceSyncsHaveSignalled(PVRSRV_FENCE_SERVER *psFence);
+static IMG_BOOL _SyncFbSyncPtHasSignalled(PVRSRV_SYNC_PT *psSyncPt);
+static IMG_BOOL _SyncFbSyncPtHasSignalledPVR(PVRSRV_SYNC_PT *psSyncPt);
+static IMG_BOOL _SyncFbSyncPtHasSignalledSW(PVRSRV_SYNC_PT *psSyncPt);
+static IMG_BOOL _SyncFbFenceAddPt(PVRSRV_FENCE_SERVER *psFence,
+                                  IMG_UINT32 *i,
+                                  PVRSRV_SYNC_PT *psSyncPt);
+static PVRSRV_ERROR _SyncFbSWTimelineFenceCreate(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                 PVRSRV_TIMELINE_SERVER *psTl,
+                                                 IMG_UINT32 uiFenceNameSize,
+                                                 const IMG_CHAR *pszFenceName,
+                                                 PVRSRV_FENCE_SERVER **ppsOutputFence,
+                                                 IMG_UINT64 *pui64SyncPtIdx);
+static PVRSRV_ERROR _SyncSWTimelineAdvanceSigErr(PVRSRV_TIMELINE_SERVER *psTl,
+                                                 PVRSRV_SYNC_STATE eState,
+                                                 IMG_UINT64 *pui64SyncPtIdx);
+static void _SyncSWTimelineCheckForUnsignalledPts(PVRSRV_TIMELINE_SERVER *psTl);
+
+
+/*****************************************************************************/
+/*                                                                           */
+/*                         GENERIC FUNCTIONS                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+
+/* Add a fence to the global fence list */
+static inline void _SyncFbFenceListAdd(PVRSRV_FENCE_SERVER *psFence)
+{
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_add_to_tail(&gsSyncFbContext.sFenceList, &psFence->sFenceListNode);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+}
+
+/* Remove a fence from the global fence list */
+static inline void _SyncFbFenceListDel(PVRSRV_FENCE_SERVER *psFence)
+{
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_remove_node(&psFence->sFenceListNode);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+}
+
+/* Add a timeline to the global timeline list */
+static inline void _SyncFbFTimelineListAdd(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_add_to_tail(&gsSyncFbContext.sTlList, &psTl->sTlList);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+}
+
+/* Remove a timeline from the global timeline list */
+static inline void _SyncFbTimelineListDel(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_remove_node(&psTl->sTlList);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+}
+
+/* Signal the sync event object to wake up waiters */
+static PVRSRV_ERROR _SyncFbSignalEO(void)
+{
+       PVRSRV_ERROR eError;
+       PVR_DPF_ENTERED;
+
+       PVR_ASSERT(gsSyncFbContext.hSyncEventObject != NULL);
+
+       eError = OSEventObjectSignal(gsSyncFbContext.hSyncEventObject);
+
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* Retrieve the process handle base for the calling PID to look up sync objects */
+static PVRSRV_ERROR _SyncFbGetProcHandleBase(PVRSRV_HANDLE_BASE **ppsHandleBase)
+{
+       *ppsHandleBase = PVRSRVRetrieveProcessHandleBase();
+
+       if (*ppsHandleBase == NULL)
+       {
+               ERR("Failed to retrieve process handle base");
+               return PVRSRV_ERROR_UNABLE_TO_RETRIEVE_HASH_VALUE;
+       }
+
+       return PVRSRV_OK;
+}
+
+/* Look up a handle in the process handle base of the calling PID */
+static PVRSRV_ERROR _SyncFbLookupProcHandle(IMG_HANDLE hHandle,
+                                            PVRSRV_HANDLE_TYPE eType,
+                                            IMG_BOOL bRefHandle,
+                                            void **ppvData,
+                                            PVRSRV_HANDLE_BASE **ppsBase)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_HANDLE_BASE *psHandleBase;
+
+       eError = _SyncFbGetProcHandleBase(&psHandleBase);
+
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       DBG(("%s: Handle Base: %p", __func__, psHandleBase));
+
+       eError = PVRSRVLookupHandle(psHandleBase,
+                                   ppvData,
+                                   hHandle,
+                                   eType,
+                                   bRefHandle);
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       *ppsBase = psHandleBase;
+
+       return PVRSRV_OK;
+
+e1:
+       return eError;
+}
+
+/* Destroy a handle in case a resource has not been registered with
+ * the resource manager */
+static PVRSRV_ERROR _SyncFbDestroyHandle(IMG_HANDLE hHandle,
+                                         PVRSRV_HANDLE_TYPE eType)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_HANDLE_BASE *psHandleBase;
+
+       eError = _SyncFbGetProcHandleBase(&psHandleBase);
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       eError = PVRSRVDestroyHandle(psHandleBase, hHandle, eType);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVDestroyHandle", e1);
+
+       return PVRSRV_OK;
+
+e1:
+       return eError;
+}
+
+/* Currently unused */
+/*
+static PVRSRV_ERROR _SyncFbFindProcHandle(void *pvData,
+                                          PVRSRV_HANDLE_TYPE eType,
+                                          IMG_HANDLE *phHandle,
+                                          PVRSRV_HANDLE_BASE **ppsBase)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_HANDLE_BASE *psHandleBase;
+
+       PVR_DPF_ENTERED;
+
+       eError = _SyncFbGetProcHandleBase(&psHandleBase);
+
+       PVR_GOTO_IF_ERROR(eError, eExit);
+
+       eError = PVRSRVFindHandle(psHandleBase,
+                                 phHandle,
+                                 pvData,
+                                                         eType);
+       PVR_GOTO_IF_ERROR(eError, eExit);
+
+       *ppsBase = psHandleBase;
+
+       PVR_DPF_RETURN_OK;
+
+eExit:
+       PVR_DPF_RETURN_RC(eError);
+}
+*/
+
+/* Returns the type of a sync point determined by its registered
+ * signalling callback. Type can be e.g. a PVR sync point containing
+ * sync checkpoints or a software sync point*/
+static PVRSRV_SYNC_HANDLE_TYPE _SyncFbSyncPtHandleType(PVRSRV_SYNC_SIGNAL_CB *psCb)
+{
+       if (psCb == NULL)
+               return PVRSRV_SYNC_HANDLE_UNKNOWN;
+
+       if (psCb->pfnSignal == &_SyncFbSyncPtSignalPVR)
+               return PVRSRV_SYNC_HANDLE_PVR;
+
+       if (psCb->pfnSignal == &_SyncFbSyncPtSignalSW)
+               return PVRSRV_SYNC_HANDLE_SW;
+
+       return PVRSRV_SYNC_HANDLE_UNKNOWN;
+}
+
+static PVRSRV_SYNC_HANDLE_TYPE _SyncFbTimelineHandleType(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       if (psTl == NULL)
+               return PVRSRV_SYNC_HANDLE_UNKNOWN;
+
+       if (psTl->sTlOps.pfnSyncPtHasSignalled == &_SyncFbSyncPtHasSignalledPVR)
+               return PVRSRV_SYNC_HANDLE_PVR;
+
+       if (psTl->sTlOps.pfnSyncPtHasSignalled == &_SyncFbSyncPtHasSignalledSW)
+               return PVRSRV_SYNC_HANDLE_SW;
+
+       return PVRSRV_SYNC_HANDLE_UNKNOWN;
+}
+
+/* Print info about a sync point to the debug dump log */
+static void _SyncFbDebugRequestPrintSyncPt(PVRSRV_SYNC_PT *psSyncPt,
+                                           IMG_BOOL bPrintTl,
+                                           DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                           void *pvDumpDebugFile)
+{
+       PDLLIST_NODE psCBNode, psNextCBNode;
+       PVRSRV_SYNC_SIGNAL_CB *psCb;
+
+       if (bPrintTl)
+       {
+               PVR_DUMPDEBUG_LOG(" - SyncPt: SeqNum: %u, Refs: %d, Timeline: %-9s <%#"IMG_UINT64_FMTSPECx">, %-9s - <0x%p>",
+                                                 psSyncPt->uiSeqNum,
+                                                 OSAtomicRead(&psSyncPt->iRef),
+                                                 psSyncPt->psTl->pszName,
+                                                 psSyncPt->psTl->iUID,
+                                                 OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_SIGNALLED ? "Signalled" :
+                                                       OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_ERRORED ? "Errored" : "Active",
+                                                 psSyncPt);
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG(" - SyncPt: SeqNum: %u, Refs: %d, %-9s - <0x%p>",
+                                                 psSyncPt->uiSeqNum,
+                                                 OSAtomicRead(&psSyncPt->iRef),
+                                                 OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_SIGNALLED ? "Signalled" :
+                                                       OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_ERRORED ? "Errored" : "Active",
+                                                 psSyncPt);
+       }
+
+       /* ... all attached syncs to that sync point*/
+       dllist_foreach_node(&psSyncPt->sSignalCallbacks,
+                           psCBNode,
+                           psNextCBNode)
+       {
+               psCb = IMG_CONTAINER_OF(psCBNode,
+                                       PVRSRV_SYNC_SIGNAL_CB,
+                                       sCallbackNode);
+
+               switch (_SyncFbSyncPtHandleType(psCb))
+               {
+                       case PVRSRV_SYNC_HANDLE_PVR:
+                       {
+                               PSYNC_CHECKPOINT pCP = psCb->hAttachedSync;
+                               PVR_DUMPDEBUG_LOG("    - CbType: PVR-Checkpoint, ID: %u, FWAddr: %#08x, Enq: %d, Ref: %d, %-9s - <0x%p>",
+                                                 SyncCheckpointGetId(pCP),
+                                                 SyncCheckpointGetFirmwareAddr(pCP),
+                                                 SyncCheckpointGetEnqueuedCount(pCP),
+                                                 SyncCheckpointGetReferenceCount(pCP),
+                                                 SyncCheckpointGetStateString(pCP),
+                                                 pCP);
+                               break;
+                       }
+                       case PVRSRV_SYNC_HANDLE_SW:
+                       {
+                               PVRSRV_SYNC_PT_SW *psSWPt = psCb->hAttachedSync;
+                               PVR_DUMPDEBUG_LOG("    - CbType: SW-Syncpoint, %-9s - <0x%p>",
+                                                 psSWPt->bSignalled ? "Signalled" : "Active",
+                                                 psSWPt);
+                               break;
+                       }
+                       case PVRSRV_SYNC_HANDLE_UNKNOWN:
+                       default:
+                               PVR_DUMPDEBUG_LOG("    - CbType: Unknown - <0x%p>",
+                                                 psCb->hAttachedSync);
+               }
+       }
+}
+
+/* Function registered with the debug dump mechanism. Prints out all timelines
+ * with pending syncs. */
+static void _SyncFbDebugRequest(IMG_HANDLE hDebugRequestHandle,
+                                IMG_UINT32 ui32VerbLevel,
+                                DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                void *pvDumpDebugFile)
+{
+       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_MEDIUM))
+       {
+               IMG_UINT32 i;
+
+               PDLLIST_NODE psTlNode, psNextTlNode;
+               PVRSRV_TIMELINE_SERVER *psTl;
+
+               PDLLIST_NODE psFenceNode, psNextFenceNode;
+               PVRSRV_FENCE_SERVER *psFence;
+
+               PDLLIST_NODE psPtNode, psNextPtNode;
+               PVRSRV_SYNC_PT *psSyncPt;
+
+               OSLockAcquire(gsSyncFbContext.hFbContextLock);
+
+               PVR_DUMPDEBUG_LOG("------[ Fallback Fence Sync: timelines ]------");
+
+               /* Iterate over all timelines */
+               dllist_foreach_node(&gsSyncFbContext.sTlList, psTlNode, psNextTlNode)
+               {
+
+                       psTl = IMG_CONTAINER_OF(psTlNode,
+                                               PVRSRV_TIMELINE_SERVER,
+                                               sTlList);
+
+                       OSLockAcquire(psTl->hTlLock);
+
+                       PVR_DUMPDEBUG_LOG("Timeline: %s, SeqNum: %d/%d - <%#"IMG_UINT64_FMTSPECx">",
+                                         psTl->pszName,
+                                         OSAtomicRead(&psTl->iLastSignalledSeqNum),
+                                         OSAtomicRead(&psTl->iSeqNum),
+                                         psTl->iUID);
+
+                       /* ... all active sync points in the timeline */
+                       dllist_foreach_node(&psTl->sSyncActiveList, psPtNode, psNextPtNode)
+                       {
+
+                               psSyncPt = IMG_CONTAINER_OF(psPtNode,
+                                                           PVRSRV_SYNC_PT,
+                                                           sTlSyncActiveList);
+
+                               _SyncFbDebugRequestPrintSyncPt(psSyncPt,
+                                                              IMG_FALSE,
+                                                              pfnDumpDebugPrintf,
+                                                              pvDumpDebugFile);
+
+                       }
+                       OSLockRelease(psTl->hTlLock);
+               }
+
+               PVR_DUMPDEBUG_LOG("------[ Fallback Fence Sync: fences ]------");
+
+               /* Iterate over all fences */
+               dllist_foreach_node(&gsSyncFbContext.sFenceList,
+                                                       psFenceNode,
+                                                       psNextFenceNode)
+               {
+                       psFence = IMG_CONTAINER_OF(psFenceNode,
+                                                  PVRSRV_FENCE_SERVER,
+                                                  sFenceListNode);
+
+                       PVR_DUMPDEBUG_LOG("Fence: %s, %-9s - <%#"IMG_UINT64_FMTSPECx">",
+                                         psFence->pszName,
+                                         _SyncFbFenceSyncsHaveSignalled(psFence) ?
+                                             "Signalled" : "Active",
+                                              psFence->iUID);
+
+                       /* ... all sync points in the fence */
+                       for (i = 0; i < psFence->uiNumSyncs; i++)
+                       {
+                               _SyncFbDebugRequestPrintSyncPt(psFence->apsFenceSyncList[i],
+                                               IMG_TRUE,
+                                                              pfnDumpDebugPrintf,
+                                                              pvDumpDebugFile);
+                       }
+               }
+
+               OSLockRelease(gsSyncFbContext.hFbContextLock);
+       }
+
+}
+
+/* Notify callback that is called as part of the RGX MISR e.g. after FW
+ * signalled the host that work completed. */
+static void _SyncFbTimelineUpdate_NotifyCMD(void *psSyncFbContext)
+{
+       PVRSRV_TIMELINE_SERVER *psTl;
+       PVRSRV_SYNC_PT *psSyncPt;
+       PDLLIST_NODE psTlList = &gsSyncFbContext.sTlList;
+       PDLLIST_NODE psCurrentTl, psNextTl;
+       PDLLIST_NODE psCurrentPt, psNextPt;
+       IMG_BOOL bSignalled = IMG_FALSE, bSignal = IMG_FALSE;
+
+       PVR_DPF_ENTERED;
+
+       /* Outer loop over all timelines */
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_foreach_node(psTlList, psCurrentTl, psNextTl)
+       {
+               psTl = IMG_CONTAINER_OF(psCurrentTl,
+                                       PVRSRV_TIMELINE_SERVER,
+                                       sTlList);
+
+               /* Inner loop over all SyncPts in the timeline.
+                * Check & Update all active SyncPts */
+               OSLockAcquire(psTl->hTlLock);
+               dllist_foreach_node(&psTl->sSyncActiveList, psCurrentPt, psNextPt)
+               {
+                       psSyncPt = IMG_CONTAINER_OF(psCurrentPt,
+                                                   PVRSRV_SYNC_PT,
+                                                   sTlSyncActiveList);
+
+                       /* If the SyncPt has been signalled we have to
+                        * update all attached syncs */
+                       bSignalled = psTl->sTlOps.pfnSyncPtHasSignalled(psSyncPt);
+                       if (bSignalled)
+                       {
+                               /* Wake up waiters after releasing the locks */
+                               bSignal = IMG_TRUE;
+
+                               /* Remove the SyncPt from the active list of the timeline. */
+                               dllist_remove_node(psCurrentPt);
+                       }
+                       else
+                       {
+                               /* No need to check further points on this timeline because
+                                * this sync pt will be signalled first */
+                               break;
+                       }
+
+               }/* End inner loop */
+               OSLockRelease(psTl->hTlLock);
+
+       } /* End outer loop */
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       if (bSignal)
+       {
+               PVR_LOG_IF_ERROR(_SyncFbSignalEO(), "_SyncFbSignalEO");
+       }
+
+       PVR_DPF_RETURN;
+}
+
+static IMG_UINT32
+_SyncCheckpointFWAddrHash(size_t uKeySize, void *pKey, IMG_UINT32 uHashTabLen)
+{
+       IMG_UINT32 *p = (IMG_UINT32 *)pKey;
+       IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINT32);
+       IMG_UINT32 ui;
+       IMG_UINT32 uHashKey = 0;
+
+       PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+       for (ui = 0; ui < uKeyLen; ui++)
+       {
+               IMG_UINT32 uHashPart = *p++;
+
+               uHashPart += (uHashPart << 12);
+               uHashPart ^= (uHashPart >> 22);
+               uHashPart += (uHashPart << 4);
+               uHashPart ^= (uHashPart >> 9);
+               uHashPart += (uHashPart << 10);
+               uHashPart ^= (uHashPart >> 2);
+               uHashPart += (uHashPart << 7);
+               uHashPart ^= (uHashPart >> 12);
+
+               uHashKey += uHashPart;
+       }
+
+       return uHashKey;
+}
+
+static IMG_BOOL
+_SyncCheckpointFWAddrCompare(size_t uKeySize, void *pKey1, void *pKey2)
+{
+       IMG_UINT32 *p1 = (IMG_UINT32 *)pKey1;
+       IMG_UINT32 *p2 = (IMG_UINT32 *)pKey2;
+       IMG_UINT32 uKeyLen = uKeySize / sizeof(IMG_UINT32);
+       IMG_UINT32 ui;
+
+       for (ui = 0; ui < uKeyLen; ui++)
+       {
+               if (*p1++ != *p2++)
+                       return IMG_FALSE;
+       }
+
+       return IMG_TRUE;
+}
+
+#if defined(PDUMP)
+static PVRSRV_ERROR SyncFbFenceGetCheckpoints(PVRSRV_FENCE hFence, IMG_UINT32 *puiNumCheckpoints,
+                                               PSYNC_CHECKPOINT **papsCheckpoints)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_SERVER *psFence;
+       PVRSRV_HANDLE_BASE *psHBase;
+       PSYNC_CHECKPOINT *apsCheckpoints;
+       PSYNC_CHECKPOINT psCheckpoint;
+       PVRSRV_SYNC_SIGNAL_CB *psSyncCB;
+       PVRSRV_SYNC_PT *psSyncPt;
+       PDLLIST_NODE psNode;
+       IMG_UINT32 i, uiNumCheckpoints = 0;
+
+       if (hFence == PVRSRV_NO_FENCE)
+       {
+               *puiNumCheckpoints = 0;
+               eError = PVRSRV_OK;
+               goto e0;
+       }
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE) (uintptr_t) hFence,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                        IMG_TRUE,
+                                        (void**)&psFence,
+                                        &psHBase);
+       PVR_GOTO_IF_ERROR(eError, e0);
+
+       apsCheckpoints = OSAllocMem(sizeof(*apsCheckpoints) * psFence->uiNumSyncs);
+       PVR_LOG_GOTO_IF_NOMEM(apsCheckpoints, eError, e1);
+
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+
+       /* Increase refcount to make sure fence is not destroyed while waiting */
+       _SyncFbFenceAcquire(psFence);
+
+       /* Go through all syncs and add them to the list */
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               psSyncPt = psFence->apsFenceSyncList[i];
+
+               psNode = dllist_get_next_node(&psSyncPt->sSignalCallbacks);
+               psSyncCB = IMG_CONTAINER_OF(psNode, PVRSRV_SYNC_SIGNAL_CB, sCallbackNode);
+
+               if (_SyncFbSyncPtHandleType(psSyncCB) == PVRSRV_SYNC_HANDLE_PVR)
+               {
+                       psCheckpoint = (PSYNC_CHECKPOINT) psSyncCB->hAttachedSync;
+                       apsCheckpoints[uiNumCheckpoints++] = psCheckpoint;
+               }
+       }
+
+       SyncFbFenceRelease(psFence);
+
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       *puiNumCheckpoints = uiNumCheckpoints;
+       *papsCheckpoints = apsCheckpoints;
+
+e1:
+       PVRSRVReleaseHandle(psHBase,
+                           (IMG_HANDLE) (uintptr_t) hFence,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+e0:
+       return eError;
+}
+#endif
+
+PVRSRV_ERROR SyncFbRegisterSyncFunctions(void)
+{
+       /* Initialise struct and register with sync_checkpoint.c */
+       gsSyncFbContext.sSyncCheckpointReg.pfnFenceResolve = &SyncFbFenceResolvePVR;
+       gsSyncFbContext.sSyncCheckpointReg.pfnFenceCreate = &SyncFbFenceCreatePVR;
+       gsSyncFbContext.sSyncCheckpointReg.pfnFenceDataRollback = &SyncFbFenceRollbackPVR;
+       gsSyncFbContext.sSyncCheckpointReg.pfnFenceFinalise = NULL; /* no fence finalise function required */
+       gsSyncFbContext.sSyncCheckpointReg.pfnNoHWUpdateTimelines = &_SyncFbTimelineUpdate_NotifyCMD;
+       gsSyncFbContext.sSyncCheckpointReg.pfnFreeCheckpointListMem = OSFreeMem;
+       gsSyncFbContext.sSyncCheckpointReg.pfnDumpInfoOnStalledUFOs = &SyncFbDumpInfoOnStalledUFOs;
+       OSStringLCopy(gsSyncFbContext.sSyncCheckpointReg.pszImplName, "SyncFb", SYNC_CHECKPOINT_IMPL_MAX_STRLEN);
+#if defined(PDUMP)
+       gsSyncFbContext.sSyncCheckpointReg.pfnSyncFenceGetCheckpoints = &SyncFbFenceGetCheckpoints;
+#endif
+
+       return SyncCheckpointRegisterFunctions(&gsSyncFbContext.sSyncCheckpointReg);
+}
+
+PVRSRV_ERROR SyncFbRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       SYNC_FB_CONTEXT_DEVICE_LIST *psNewDeviceEntry;
+
+       PVR_DPF_ENTERED;
+
+       /* Initialise the sync fallback context */
+       if (gsSyncFbContext.hSyncEventObject == NULL)
+       {
+               eError = OSEventObjectCreate("Sync event object",
+                                            &gsSyncFbContext.hSyncEventObject);
+               PVR_GOTO_IF_ERROR(eError, e1);
+
+               dllist_init(&gsSyncFbContext.sTlList);
+               dllist_init(&gsSyncFbContext.sFenceList);
+               dllist_init(&gsSyncFbContext.sDeviceList);
+               gsSyncFbContext.sCheckpointHashTable = HASH_Create_Extended(64, sizeof(IMG_UINT32), _SyncCheckpointFWAddrHash, _SyncCheckpointFWAddrCompare);
+
+               eError = OSLockCreate(&gsSyncFbContext.hFbContextLock);
+               PVR_GOTO_IF_ERROR(eError, e2);
+
+               eError = PVRSRVRegisterCmdCompleteNotify(&gsSyncFbContext.hCMDNotify,
+                                                        &_SyncFbTimelineUpdate_NotifyCMD,
+                                                        &gsSyncFbContext);
+               PVR_GOTO_IF_ERROR(eError, e3);
+       }
+
+       psNewDeviceEntry = OSAllocMem(sizeof(*psNewDeviceEntry));
+       PVR_GOTO_IF_NOMEM(psNewDeviceEntry, eError, e4);
+
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_add_to_tail(&gsSyncFbContext.sDeviceList, &psNewDeviceEntry->sDeviceListNode);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       psNewDeviceEntry->psDevice = psDeviceNode;
+
+       eError = PVRSRVRegisterDeviceDbgRequestNotify(&psNewDeviceEntry->hDBGNotify,
+                                                     psDeviceNode,
+                                                     _SyncFbDebugRequest,
+                                                     DEBUG_REQUEST_FALLBACKSYNC,
+                                                     NULL);
+       PVR_GOTO_IF_ERROR(eError, e5);
+
+       PVR_DPF_RETURN_RC(eError);
+
+
+e5:
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       dllist_remove_node(&psNewDeviceEntry->sDeviceListNode);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+       OSFreeMem(psNewDeviceEntry);
+e4:
+       PVRSRVUnregisterCmdCompleteNotify(gsSyncFbContext.hCMDNotify);
+e3:
+       OSLockDestroy(gsSyncFbContext.hFbContextLock);
+e2:
+       OSEventObjectDestroy(gsSyncFbContext.hSyncEventObject);
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR SyncFbDeregisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       SYNC_FB_CONTEXT_DEVICE_LIST *psDeviceEntry;
+       PDLLIST_NODE psNode, psNext;
+
+       PVR_DPF_ENTERED;
+
+       /* Return if Init was never called */
+       if (gsSyncFbContext.hSyncEventObject == NULL)
+               goto e1;
+
+       /* Check device list for the given device and remove it */
+       dllist_foreach_node(&gsSyncFbContext.sDeviceList, psNode, psNext)
+       {
+               psDeviceEntry = IMG_CONTAINER_OF(psNode,
+                                                SYNC_FB_CONTEXT_DEVICE_LIST,
+                                                sDeviceListNode);
+
+               if (psDeviceEntry->psDevice == psDeviceNode)
+               {
+                       PVRSRVUnregisterDeviceDbgRequestNotify(psDeviceEntry->hDBGNotify);
+
+                       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+                       dllist_remove_node(psNode);
+                       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+                       OSFreeMem(psDeviceEntry);
+                       break;
+               }
+       }
+
+       /* If there are still devices registered with us don't deinit module */
+       if (!dllist_is_empty(&gsSyncFbContext.sDeviceList))
+       {
+               goto e1;
+       }
+
+       PVRSRVUnregisterCmdCompleteNotify(gsSyncFbContext.hCMDNotify);
+
+
+       eError = OSEventObjectDestroy(gsSyncFbContext.hSyncEventObject);
+       PVR_LOG_IF_ERROR(eError, "OSEventObjectDestroy");
+
+       gsSyncFbContext.hSyncEventObject = NULL;
+
+       OSLockDestroy(gsSyncFbContext.hFbContextLock);
+
+e1:
+       return eError;
+}
+
+/* HOLD TL LOCK!
+ * Creates a new sync point on a timeline */
+static PVRSRV_ERROR _SyncFbSyncPtCreate(PVRSRV_SYNC_PT **ppsSyncPt,
+                                       PVRSRV_TIMELINE_SERVER *psTl,
+                                       IMG_UINT32 uiSeqNumber)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_SYNC_PT *psNewSyncPt;
+
+       PVR_DPF_ENTERED;
+
+       psNewSyncPt = OSAllocMem(sizeof(*psNewSyncPt));
+       PVR_LOG_GOTO_IF_NOMEM(psNewSyncPt, eError, e1);
+
+       psNewSyncPt->psTl = psTl;
+       OSAtomicWrite(&psNewSyncPt->iStatus, PVRSRV_SYNC_NOT_SIGNALLED);
+
+       psNewSyncPt->uiSeqNum = uiSeqNumber;
+       psNewSyncPt->uiPID = OSGetCurrentClientProcessIDKM();
+       PT_REF_SET(&psNewSyncPt->iRef, 1,psNewSyncPt);
+
+       dllist_init(&psNewSyncPt->sTlSyncList);
+       dllist_init(&psNewSyncPt->sTlSyncActiveList);
+       dllist_init(&psNewSyncPt->sSignalCallbacks);
+
+       /* Increment Tl ref due to new checkpoint*/
+       _SyncFbTimelineAcquire(psTl);
+
+       dllist_add_to_tail(&psTl->sSyncList, &psNewSyncPt->sTlSyncList);
+       dllist_add_to_tail(&psTl->sSyncActiveList, &psNewSyncPt->sTlSyncActiveList);
+
+       *ppsSyncPt = psNewSyncPt;
+
+       PVR_DPF_RETURN_OK;
+
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* Increment sync point refcount */
+static void _SyncFbSyncPtAcquire(PVRSRV_SYNC_PT *psSyncPt)
+{
+       PT_REF_INC(&psSyncPt->iRef, psSyncPt);
+}
+
+/* Release and maybe destroy sync point if refcount is 0 */
+static PVRSRV_ERROR _SyncFbSyncPtRelease(PVRSRV_SYNC_PT *psSyncPt,
+                                         IMG_BOOL bError)
+{
+       PVRSRV_ERROR eError;
+       PDLLIST_NODE psNode, psNext;
+       PVRSRV_SYNC_SIGNAL_CB *psSyncCB;
+       IMG_INT iRef;
+
+       PVR_DPF_ENTERED1(psSyncPt);
+
+       iRef = PT_REF_DEC(&psSyncPt->iRef, psSyncPt);
+       if (iRef != 0)
+       {
+               eError = PVRSRV_OK;
+               goto e1;
+       }
+
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       /* Remove all checkpoints from the ufo lookup table.*/
+       dllist_foreach_node(&psSyncPt->sSignalCallbacks, psNode, psNext)
+       {
+               psSyncCB = IMG_CONTAINER_OF(psNode,
+                                           PVRSRV_SYNC_SIGNAL_CB,
+                                           sCallbackNode);
+
+               if (_SyncFbSyncPtHandleType(psSyncCB) == PVRSRV_SYNC_HANDLE_PVR)
+               {
+                       IMG_UINT32 ui32FwAddr = SyncCheckpointGetFirmwareAddr((PSYNC_CHECKPOINT) psSyncCB->hAttachedSync);
+
+                       DBG(("%s: Removing key <%#08x>", __func__, ui32FwAddr));
+                       HASH_Remove_Extended(gsSyncFbContext.sCheckpointHashTable, &ui32FwAddr);
+               }
+       }
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       OSLockAcquire(psSyncPt->psTl->hTlLock);
+       if (dllist_node_is_in_list(&psSyncPt->sTlSyncActiveList))
+               dllist_remove_node(&psSyncPt->sTlSyncActiveList);
+
+       dllist_remove_node(&psSyncPt->sTlSyncList);
+
+       if (bError)
+       {
+               _SyncFbSyncPtSignalAttached(psSyncPt, PVRSRV_SYNC_ERRORED);
+       }
+       OSLockRelease(psSyncPt->psTl->hTlLock);
+
+       /* Remove all attached nodes and signal them.*/
+       while (!dllist_is_empty(&psSyncPt->sSignalCallbacks))
+       {
+               psNode = dllist_get_next_node(&psSyncPt->sSignalCallbacks);
+               psSyncCB = IMG_CONTAINER_OF(psNode,
+                                           PVRSRV_SYNC_SIGNAL_CB,
+                                           sCallbackNode);
+
+               psSyncCB->pfnSyncFree(psSyncCB->hAttachedSync);
+               dllist_remove_node(&psSyncCB->sCallbackNode);
+               OSFreeMem(psSyncCB);
+       }
+
+       eError = SyncFbTimelineRelease(psSyncPt->psTl);
+       PVR_LOG_IF_ERROR(eError, "SyncFbTimelineRelease");
+
+       OSFreeMem(psSyncPt);
+
+       PVR_DPF_RETURN_OK;
+
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* HOLD TL LOCK!
+ * Mark all attached syncs of a sync point with the state eSignal */
+static PVRSRV_ERROR _SyncFbSyncPtSignalAttached(PVRSRV_SYNC_PT *psSyncPt,
+                                                PVRSRV_SYNC_STATE eSignal)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK, eRet;
+       PDLLIST_NODE psCurrentCB, psNextCB;
+       PVRSRV_SYNC_SIGNAL_CB *psCB;
+
+       PVR_DPF_ENTERED1(psSyncPt);
+
+       if (dllist_is_empty(&psSyncPt->sSignalCallbacks))
+       {
+               ERR("Sync pt has no attached syncs. Make sure to attach one "
+                   "when creating a new sync pt to define its flavour");
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto e1;
+       }
+
+       dllist_foreach_node(&psSyncPt->sSignalCallbacks, psCurrentCB, psNextCB)
+       {
+               psCB = IMG_CONTAINER_OF(psCurrentCB,
+                                       PVRSRV_SYNC_SIGNAL_CB,
+                                       sCallbackNode);
+               eRet = psCB->pfnSignal(psCB->hAttachedSync, eSignal);
+               if (eRet != PVRSRV_OK)
+               {
+                       ERR("Failed to signal an attached sync, system might block!");
+                       eError = eRet;
+                       /* Don't jump to exit but try to signal remaining syncs */
+               }
+       }
+
+e1:
+       PVR_DPF_RETURN_RC1(eError, psSyncPt);
+}
+
+/* HOLD TL LOCK!
+ * Mark all a sync point with the state eSignal */
+static PVRSRV_ERROR _SyncFbSyncPtSignal(PVRSRV_SYNC_PT *psSyncPt, PVRSRV_SYNC_STATE eSignal)
+{
+       PVR_DPF_ENTERED1(psSyncPt);
+
+       OSAtomicWrite(&psSyncPt->iStatus, eSignal);
+
+       if (psSyncPt->uiSeqNum >
+           OSAtomicRead(&psSyncPt->psTl->iLastSignalledSeqNum))
+       {
+               OSAtomicWrite(&psSyncPt->psTl->iLastSignalledSeqNum,
+                             psSyncPt->uiSeqNum);
+       }
+
+       PVR_DPF_RETURN_OK;
+}
+
+/* Check whether all syncs in a fence were signalled */
+static IMG_BOOL _SyncFbFenceSyncsHaveSignalled(PVRSRV_FENCE_SERVER *psFence)
+{
+       IMG_UINT32 i;
+
+       PVR_DPF_ENTERED1(psFence);
+
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               if (OSAtomicRead(&psFence->apsFenceSyncList[i]->iStatus) ==
+                       PVRSRV_SYNC_NOT_SIGNALLED)
+               {
+                       PVR_DPF_RETURN_RC1(IMG_FALSE, psFence);
+               }
+       }
+
+       OSAtomicWrite(&psFence->iStatus,
+                     PVRSRV_FENCE_SIGNALLED);
+
+       PVR_DPF_RETURN_RC1(IMG_TRUE, psFence);
+}
+
+/* Increment timeline refcount */
+static void _SyncFbTimelineAcquire(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       TL_REF_INC(&psTl->iRef, psTl);
+}
+
+PVRSRV_ERROR SyncFbTimelineRelease(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       IMG_INT iRef;
+
+       PVR_DPF_ENTERED1(psTl);
+
+       iRef = TL_REF_DEC(&psTl->iRef, psTl);
+       if (iRef != 0)
+       {
+               PVR_DPF_RETURN_OK;
+       }
+
+       if (_SyncFbTimelineHandleType(psTl) == PVRSRV_SYNC_HANDLE_SW)
+       {
+               _SyncSWTimelineCheckForUnsignalledPts(psTl);
+       }
+
+       _SyncFbTimelineListDel(psTl);
+
+       OSLockDestroy(psTl->hTlLock);
+
+#if defined(DEBUG)
+       psTl->sTlOps.pfnSyncPtHasSignalled = NULL;
+       psTl->hTlLock = NULL;
+#endif
+
+       OSFreeMem(psTl);
+
+       PVR_DPF_RETURN_OK;
+}
+
+/* Increment fence refcount */
+static void _SyncFbFenceAcquire(PVRSRV_FENCE_SERVER *psFence)
+{
+       FENCE_REF_INC(&psFence->iRef, psFence);
+}
+
+PVRSRV_ERROR SyncFbFenceRelease(PVRSRV_FENCE_SERVER *psFence)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK, eRet;
+       IMG_INT iRef;
+       IMG_UINT32 i;
+       IMG_BOOL bError = IMG_FALSE;
+       IMG_BOOL bCleanup = IMG_FALSE;
+
+       PVR_DPF_ENTERED1(psFence);
+
+       /* If cleanup thread, force cleanup of SW fences, otherwise
+        * simply decrement psFence->iRef
+        */
+       if (OSGetCurrentClientProcessIDKM() == PVRSRVGetPVRSRVData()->cleanupThreadPid)
+       {
+               IMG_UINT32 uiSyncPt;
+
+               /* Force erroring of any SW sync pts this fence may contain */
+               for (uiSyncPt=0; uiSyncPt < psFence->uiNumSyncs; uiSyncPt++)
+               {
+                       PVRSRV_SYNC_PT *psSyncPt = psFence->apsFenceSyncList[uiSyncPt];
+
+                       /* If this is a SW sync point from a timeline which was created
+                        * by the process being cleaned-up, then error it
+                        */
+                       if ((_SyncFbTimelineHandleType(psSyncPt->psTl) == PVRSRV_SYNC_HANDLE_SW) &&
+                           (PVRSRVGetPurgeConnectionPid() == psSyncPt->psTl->uiPID))
+                       {
+                               OSLockAcquire(psSyncPt->psTl->hTlLock);
+                               _SyncFbSyncPtSignalAttached(psSyncPt, PVRSRV_SYNC_ERRORED);
+                               OSLockRelease(psSyncPt->psTl->hTlLock);
+                       }
+               }
+       }
+
+       iRef = FENCE_REF_DEC(&psFence->iRef, psFence);
+       if (iRef != 0)
+       {
+               goto e1;
+       }
+
+       PDUMPCOMMENTWITHFLAGS(psFence->psDevNode, 0,
+                             "Destroy Fence %s (ID:%"IMG_UINT64_FMTSPEC")",
+                             psFence->pszName,
+                             psFence->iUID);
+
+       if (OSGetCurrentClientProcessIDKM() ==
+                       PVRSRVGetPVRSRVData()->cleanupThreadPid)
+       {
+               bCleanup = IMG_TRUE;
+       }
+
+       _SyncFbFenceListDel(psFence);
+
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               PVRSRV_SYNC_PT *psSyncPt = psFence->apsFenceSyncList[i];
+
+               if (bCleanup &&
+                               _SyncFbTimelineHandleType(psSyncPt->psTl) == PVRSRV_SYNC_HANDLE_SW)
+               {
+                       bError = IMG_TRUE;
+               }
+
+               eRet = _SyncFbSyncPtRelease(psSyncPt,
+                                           bError);
+               if (eRet != PVRSRV_OK)
+               {
+                       ERR("Error when releasing SyncPt, this might leak memory")
+                       eError = eRet;
+                       /* Try to continue and release the other sync pts, return error */
+               }
+       }
+
+#if defined(DEBUG)
+       {
+               for (i = 0; i < psFence->uiNumSyncs; i++)
+               {
+                       psFence->apsFenceSyncList[i] = NULL;
+               }
+               psFence->uiNumSyncs = 0;
+       }
+#endif
+
+       OSFreeMem(psFence->apsFenceSyncList);
+       OSFreeMem(psFence);
+
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR SyncFbFenceDup(PVRSRV_FENCE_SERVER *psInFence,
+                            PVRSRV_FENCE_SERVER **ppsOutFence)
+{
+       PVR_DPF_ENTERED1(psInFence);
+
+       FENCE_REF_INC(&psInFence->iRef, psInFence);
+
+       PDUMPCOMMENTWITHFLAGS(psInFence->psDevNode, 0,
+                             "Dup Fence %s (ID:%"IMG_UINT64_FMTSPEC").",
+                             psInFence->pszName,
+                             psInFence->iUID);
+
+       *ppsOutFence = psInFence;
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, *ppsOutFence);
+}
+
+static IMG_BOOL _SyncFbSyncPtHasSignalled(PVRSRV_SYNC_PT *psSyncPt)
+{
+       return psSyncPt->psTl->sTlOps.pfnSyncPtHasSignalled(psSyncPt);
+}
+
+static IMG_BOOL _SyncFbFenceAddPt(PVRSRV_FENCE_SERVER *psFence,
+                                  IMG_UINT32 *i,
+                                  PVRSRV_SYNC_PT *psSyncPt)
+{
+       /*
+        * If the fence is signalled there is no need to add it to the fence.
+        * One exception is PDUMP drivers where we need to make sure we
+        * set up proper synchronisation in the pdump stream.
+        */
+#if !defined(PDUMP)
+       if (_SyncFbSyncPtHasSignalled(psSyncPt)) return IMG_FALSE;
+#endif
+       _SyncFbSyncPtAcquire(psSyncPt);
+       psFence->apsFenceSyncList[*i] = psSyncPt;
+       (*i)++;
+       return IMG_TRUE;
+}
+
+PVRSRV_ERROR SyncFbFenceMerge(PVRSRV_FENCE_SERVER *psInFence1,
+                              PVRSRV_FENCE_SERVER *psInFence2,
+                              IMG_UINT32 uiFenceNameSize,
+                              const IMG_CHAR *pszFenceName,
+                              PVRSRV_FENCE_SERVER **ppsOutFence)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_FENCE_SERVER *psNewFence;
+       IMG_UINT32 i, i1, i2;
+       IMG_UINT32 uiFenceSyncListSize;
+
+       PVR_DPF_ENTERED;
+
+       psNewFence = OSAllocMem(sizeof(*psNewFence));
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence, eError, e1);
+
+       psNewFence->psDevNode = psInFence1->psDevNode;
+
+       uiFenceSyncListSize = sizeof(*(psNewFence->apsFenceSyncList)) *
+                       (psInFence1->uiNumSyncs + psInFence2->uiNumSyncs);
+
+       psNewFence->apsFenceSyncList = OSAllocMem(uiFenceSyncListSize);
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence->apsFenceSyncList, eError, e2);
+
+       if (uiFenceNameSize == 1)
+       {
+               OSSNPrintf(psNewFence->pszName,
+                          SYNC_FB_FENCE_MAX_LENGTH,
+                          "Fence-Merged");
+       }
+       else
+       {
+               if (pszFenceName)
+               {
+                       OSStringLCopy(psNewFence->pszName,
+                                                 pszFenceName,
+                                                 SYNC_FB_FENCE_MAX_LENGTH);
+               }
+               else
+               {
+                       psNewFence->pszName[0] = '\0';
+               }
+       }
+
+       /* Add sync pts from input fence 1 & 2
+        * - no duplicates in one timeline
+        * - sync pts in one fence are ordered by timeline UID
+        *
+        * */
+       for (i = 0, i1 = 0, i2 = 0;
+            i1 < psInFence1->uiNumSyncs && i2 < psInFence2->uiNumSyncs;)
+       {
+               PVRSRV_SYNC_PT *psSyncPt1 = psInFence1->apsFenceSyncList[i1];
+               PVRSRV_SYNC_PT *psSyncPt2 = psInFence2->apsFenceSyncList[i2];
+
+               /* Adding sync pts in order of their timeline UID, smaller ID first */
+               if (psSyncPt1->psTl->iUID <
+            psSyncPt2->psTl->iUID)
+               {
+                       _SyncFbFenceAddPt(psNewFence, &i, psSyncPt1);
+                       i1++;
+               }
+               else if (psSyncPt1->psTl->iUID >
+                        psSyncPt2->psTl->iUID)
+               {
+                       _SyncFbFenceAddPt(psNewFence, &i, psSyncPt2);
+                       i2++;
+               }
+               /* In case the timeline UID is the same just add the point that is
+                * later on that timeline. */
+               else
+               {
+                       /* --> Some C magic to find out if 'a' is a point later in the
+                        * timeline than 'b', wrap around is taken into account:
+                        *                      (a - b <= ((IMG_INT)(~0U>>1)) ) */
+                       if ( psSyncPt1->uiSeqNum - psSyncPt2->uiSeqNum <=
+                           ((IMG_INT)(~0U>>1)) )
+                       {
+                               _SyncFbFenceAddPt(psNewFence, &i, psSyncPt1);
+                       }
+                       else
+                       {
+                               _SyncFbFenceAddPt(psNewFence, &i, psSyncPt2);
+                       }
+
+                       i1++;
+                       i2++;
+               }
+       }
+
+       /* Add the remaining syncs pts to the fence. At this point we only enter
+        * either the first or the second loop because one fence has
+        * more sync pts than the other.
+        */
+       for (; i1 < psInFence1->uiNumSyncs; i1++)
+       {
+               _SyncFbFenceAddPt(psNewFence, &i, psInFence1->apsFenceSyncList[i1]);
+       }
+
+       for (; i2 < psInFence2->uiNumSyncs; i2++)
+       {
+               _SyncFbFenceAddPt(psNewFence, &i, psInFence2->apsFenceSyncList[i2]);
+       }
+
+       /* Fill remaining fields */
+       psNewFence->uiNumSyncs = i;
+       psNewFence->iUID = (IMG_INT64)(uintptr_t) psNewFence;
+       FENCE_REF_SET(&psNewFence->iRef, 1, psNewFence);
+
+       OSAtomicWrite(&psNewFence->iStatus, PVRSRV_SYNC_NOT_SIGNALLED);
+
+       _SyncFbFenceListAdd(psNewFence);
+
+       PDUMPCOMMENTWITHFLAGS(psInFence1->psDevNode, 0,
+                             "Merge Fence1 %s (ID:%"IMG_UINT64_FMTSPEC"), Fence2 %s (ID:%"IMG_UINT64_FMTSPEC") "
+                             "to Fence %s (ID:%"IMG_UINT64_FMTSPEC")",
+                             psInFence1->pszName,
+                             psInFence1->iUID,
+                             psInFence2->pszName,
+                             psInFence2->iUID,
+                             psNewFence->pszName,
+                             psNewFence->iUID);
+
+       *ppsOutFence = psNewFence;
+
+       PVR_DPF_RETURN_RC1(eError, *ppsOutFence);
+
+e2:
+       OSFreeMem(psNewFence);
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+
+PVRSRV_ERROR SyncFbFenceWait(PVRSRV_FENCE_SERVER *psFence,
+                             IMG_UINT32 ui32TimeoutInMs)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_HANDLE hOSEvent;
+       IMG_UINT32 t1 = 0, t2 = 0;
+
+       PVR_DPF_ENTERED1(psFence);
+
+       /* Increase refcount to make sure fence is not destroyed while waiting */
+       _SyncFbFenceAcquire(psFence);
+
+       if (OSAtomicRead(&psFence->iStatus) == PVRSRV_FENCE_NOT_SIGNALLED)
+       {
+               PVRSRV_ERROR eErrorClose;
+
+               /* If the status of the fence is not signalled it could mean that
+                * there are actually syncs still pending or that we have not
+                * checked yet whether the syncs were met, therefore do the
+                * check now and return in case they are. If they are not, go
+                * to sleep and wait. */
+
+               if (_SyncFbFenceSyncsHaveSignalled(psFence))
+               {
+                       goto e1;
+               }
+               else if (ui32TimeoutInMs == 0)
+               {
+                       eError = PVRSRV_ERROR_TIMEOUT;
+                       goto e1;
+               }
+
+               eError = OSEventObjectOpen(gsSyncFbContext.hSyncEventObject,
+                                          &hOSEvent);
+               PVR_GOTO_IF_ERROR(eError, e1);
+
+               while (!_SyncFbFenceSyncsHaveSignalled(psFence) && ui32TimeoutInMs)
+               {
+                       t1 = OSClockms();
+                       /* Wait for EO to be signalled */
+                       eError = OSEventObjectWaitTimeout(hOSEvent,
+                                                         ui32TimeoutInMs * 1000);
+                       t2 = OSClockms();
+
+                       if (eError != PVRSRV_OK && eError != PVRSRV_ERROR_TIMEOUT)
+                       {
+                               break;
+                       }
+
+
+                       /* Reduce timeout by the time we have just waited */
+                       if (ui32TimeoutInMs < (t2-t1))
+                       {
+                               ui32TimeoutInMs = 0;
+                       }
+                       else
+                       {
+                               ui32TimeoutInMs -= (t2-t1);
+                       }
+               }
+
+               eErrorClose = OSEventObjectClose(hOSEvent);
+               if (eErrorClose != PVRSRV_OK)
+               {
+                       ERR("Unable to close Event Object");
+
+                       /* Do not overwrite previous error
+                        * if it was something else than PVRSRV_OK */
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eErrorClose;
+                       }
+               }
+       }
+e1:
+
+       SyncFbFenceRelease(psFence);
+
+       PVR_DPF_RETURN_RC1(eError, psFence);
+}
+
+PVRSRV_ERROR SyncFbFenceDump(PVRSRV_FENCE_SERVER *psFence,
+                             IMG_UINT32 uiLine,
+                             IMG_UINT32 uiFileNameLength,
+                             const IMG_CHAR *pszFile,
+                             IMG_UINT32 uiModuleLength,
+                             const IMG_CHAR *pszModule,
+                             IMG_UINT32 uiDescLength,
+                             const IMG_CHAR *pszDesc)
+{
+
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 i;
+
+
+       PVR_DPF_ENTERED1(psFence);
+
+       PVR_LOG(("  Fence dump request from:"));
+#if defined(DEBUG)
+       PVR_LOG(("    %s (%s:%u)", pszModule, pszFile, uiLine));
+#else
+       PVR_LOG(("    %s (location only available in debug build)", pszModule));
+#endif
+       PVR_LOG(("  Desc: %s", pszDesc));
+       PVR_LOG(("---------------- FENCE ----------------"));
+       PVR_LOG(("%s (UID: %"IMG_UINT64_FMTSPEC")", psFence->pszName, psFence->iUID));
+
+       PVR_LOG(("  Signalled: %s",
+               _SyncFbFenceSyncsHaveSignalled(psFence)?"Yes":"No"));
+       PVR_LOG(("  Ref: %d", OSAtomicRead(&psFence->iRef) ));
+
+       PVR_LOG(("  Sync Points:"));
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               PVRSRV_SYNC_PT *psSP = psFence->apsFenceSyncList[i];
+               PVR_LOG(("    Point %u)", i));
+               PVR_LOG(("      On timeline:     %s (UID: %"IMG_UINT64_FMTSPEC")",
+                        psSP->psTl->pszName, psSP->psTl->iUID));
+               PVR_LOG(("      Sequence number: %u", psSP->uiSeqNum));
+               PVR_LOG(("      Signalled:       %s",
+                       psSP->psTl->sTlOps.pfnSyncPtHasSignalled(psSP)? "Yes":"No"));
+               PVR_LOG(("      Ref:             %d", OSAtomicRead(&psSP->iRef)));
+       }
+       PVR_LOG(("----------------------------------------"));
+
+       PVR_DPF_RETURN_RC1(eError, psFence);
+}
+
+static PVRSRV_ERROR _SyncFbTimelineCreate(PFN_SYNC_PT_HAS_SIGNALLED pfnHasPtSignalled,
+                                          IMG_UINT32 uiTimelineNameSize,
+                                          const IMG_CHAR *pszTimelineName,
+                                          PVRSRV_TIMELINE_SERVER **ppsTimeline)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_TIMELINE_SERVER *psNewTl;
+
+       PVR_DPF_ENTERED;
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(ppsTimeline, eError, e1);
+
+       psNewTl = OSAllocMem(sizeof(*psNewTl));
+       PVR_LOG_GOTO_IF_NOMEM(psNewTl, eError, e2);
+
+       eError = OSLockCreate(&psNewTl->hTlLock);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate", e3);
+
+       if (uiTimelineNameSize == 1)
+       {
+               OSSNPrintf(psNewTl->pszName,
+                          SYNC_FB_TIMELINE_MAX_LENGTH,
+                          "TL-%s-%d",
+                          OSGetCurrentClientProcessNameKM(),
+                          OSGetCurrentClientProcessIDKM());
+       }
+       else
+       {
+               if (pszTimelineName)
+               {
+                       OSStringLCopy((IMG_CHAR*) psNewTl->pszName,
+                                     pszTimelineName,
+                                     SYNC_FB_TIMELINE_MAX_LENGTH);
+               }
+               else
+               {
+                       psNewTl->pszName[0] = '\0';
+               }
+       }
+
+       dllist_init(&psNewTl->sSyncList);
+       dllist_init(&psNewTl->sSyncActiveList);
+       dllist_init(&psNewTl->sTlList);
+
+       _SyncFbFTimelineListAdd(psNewTl);
+
+       psNewTl->sTlOps.pfnSyncPtHasSignalled = pfnHasPtSignalled;
+       psNewTl->iUID = (IMG_INT64)(uintptr_t) psNewTl; /* Not unique throughout the driver lifetime */
+       OSAtomicWrite(&psNewTl->iSeqNum, 0);
+       OSAtomicWrite(&psNewTl->iLastSignalledSeqNum, 0);
+       psNewTl->uiPID = OSGetCurrentClientProcessIDKM();
+
+       /* Set initial refcount value */
+       TL_REF_SET(&psNewTl->iRef, 1, psNewTl);
+
+       *ppsTimeline = psNewTl;
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, psNewTl);
+
+e3:
+       OSFreeMem(psNewTl);
+e2:
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*                         PVR SPECIFIC FUNCTIONS                            */
+/*                                                                           */
+/*****************************************************************************/
+
+/* Free a PVR sync point with its sync checkpoint */
+static void _SyncFbSyncPtFreePVR(IMG_HANDLE hSync)
+{
+       PVR_DPF_ENTERED1(hSync);
+
+       SyncCheckpointFree((PSYNC_CHECKPOINT) hSync);
+
+       PVR_DPF_RETURN;
+}
+
+
+/* Mark a sync checkpoint with the given state.
+ * MAKE SURE TO WAKE UP FW AFTER CALLING THIS */
+static PVRSRV_ERROR _SyncFbSyncPtSignalPVR(IMG_HANDLE hSync,
+                                           PVRSRV_SYNC_STATE eState)
+{
+       PSYNC_CHECKPOINT psSyncCheck = (PSYNC_CHECKPOINT) hSync;
+
+       PVR_DPF_ENTERED1(hSync);
+
+       if (!SyncCheckpointIsSignalled(psSyncCheck, PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
+       {
+               switch (eState)
+               {
+                       case PVRSRV_SYNC_SIGNALLED:
+                               SyncCheckpointSignal(psSyncCheck, PVRSRV_FENCE_FLAG_NONE);
+                               break;
+                       case PVRSRV_SYNC_ERRORED:
+                               SyncCheckpointError(psSyncCheck, PVRSRV_FENCE_FLAG_NONE);
+                               break;
+                       default:
+                               ERR("Passed unknown sync state, "
+                                               "please use a valid one for signalling.");
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, hSync);
+}
+
+/* Check whether the native sync of the SyncPt has signalled.
+ *
+ * HOLD TL LOCK!
+ */
+static IMG_BOOL _SyncFbSyncPtHasSignalledPVR(PVRSRV_SYNC_PT *psSyncPt)
+{
+       PDLLIST_NODE psCBNode;
+       PVRSRV_SYNC_SIGNAL_CB *psCB;
+       PSYNC_CHECKPOINT psSyncCheck;
+       IMG_BOOL bRet = IMG_FALSE;
+
+       PVR_DPF_ENTERED1(psSyncPt);
+
+       /* If the SyncPt is not signalled yet,
+        * check whether the first attached sync has.
+        *
+        * Change SyncPt state to signalled or errored if yes.
+        * Also notify other attached syncs.
+        */
+       if (OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_NOT_SIGNALLED)
+       {
+               /* List must have at least the device sync attached if we are called */
+               PVR_ASSERT(!dllist_is_empty(&psSyncPt->sSignalCallbacks));
+
+               /* Retrieve the first sync checkpoint of that sync pt */
+               psCBNode = dllist_get_next_node(&psSyncPt->sSignalCallbacks);
+               psCB = IMG_CONTAINER_OF(psCBNode, PVRSRV_SYNC_SIGNAL_CB, sCallbackNode);
+               psSyncCheck = (PSYNC_CHECKPOINT) psCB->hAttachedSync;
+
+               if (SyncCheckpointIsSignalled(psSyncCheck, PVRSRV_FENCE_FLAG_SUPPRESS_HWP_PKT))
+               {
+                       _SyncFbSyncPtSignal(psSyncPt, PVRSRV_SYNC_SIGNALLED);
+
+                       /* Signal all other attached syncs */
+                       PVR_LOG_IF_ERROR(_SyncFbSyncPtSignalAttached(psSyncPt, PVRSRV_SYNC_SIGNALLED),
+                                        "_SyncFbSyncPtSignalAttached");
+
+                       bRet = IMG_TRUE;
+               }
+
+               PVR_DPF_RETURN_RC1(bRet, psSyncPt);
+       }
+       else
+       {
+               PVR_DPF_RETURN_RC1(IMG_TRUE, psSyncPt);
+       }
+}
+
+PVRSRV_ERROR SyncFbTimelineCreatePVR(IMG_UINT32 uiTimelineNameSize,
+                                     const IMG_CHAR *pszTimelineName,
+                                     PVRSRV_TIMELINE_SERVER **ppsTimeline)
+{
+       return _SyncFbTimelineCreate(&_SyncFbSyncPtHasSignalledPVR,
+                                    uiTimelineNameSize,
+                                    pszTimelineName,
+                                    ppsTimeline);
+}
+
+PVRSRV_ERROR SyncFbFenceCreatePVR(PPVRSRV_DEVICE_NODE psDeviceNode,
+                                  const IMG_CHAR *pszName,
+                                  PVRSRV_TIMELINE iTl,
+                                  PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
+                                  PVRSRV_FENCE *piOutFence,
+                                  IMG_UINT64 *puiFenceUID,
+                                  void **ppvFenceFinaliseData,
+                                  PSYNC_CHECKPOINT *ppsOutCheckpoint,
+                                  void **ppvTimelineUpdateSync,
+                                  IMG_UINT32 *puiTimelineUpdateValue)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_SERVER *psNewFence;
+       PVRSRV_SYNC_PT *psNewSyncPt = NULL;
+       PVRSRV_SYNC_SIGNAL_CB *psNewSyncSignalCB;
+       PVRSRV_HANDLE_BASE      *psHandleBase;
+       PVRSRV_TIMELINE_SERVER *psTl;
+       IMG_HANDLE hOutFence;
+       IMG_UINT32 ui32FwAddr;
+
+       PVR_UNREFERENCED_PARAMETER(ppvTimelineUpdateSync);
+       PVR_UNREFERENCED_PARAMETER(puiTimelineUpdateValue);
+
+       PVR_DPF_ENTERED;
+
+       /* The fallback implementation does not need to finalise
+        * the fence, so set the ppvFenceFinaliseData to NULL
+        * (if provided)
+        */
+       if (ppvFenceFinaliseData != NULL )
+       {
+               *ppvFenceFinaliseData = NULL;
+       }
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(pszName, eError, e0);
+       PVR_LOG_GOTO_IF_INVALID_PARAM(piOutFence, eError, e0);
+       PVR_LOG_GOTO_IF_INVALID_PARAM(ppsOutCheckpoint, eError, e0);
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE) (uintptr_t) iTl,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                        IMG_TRUE,
+                                        (void**) &psTl,
+                                        &psHandleBase);
+       PVR_GOTO_IF_ERROR(eError, e0);
+
+       if (unlikely(_SyncFbTimelineHandleType(psTl) != PVRSRV_SYNC_HANDLE_PVR))
+       {
+               PVR_LOG_GOTO_WITH_ERROR("_SyncFbTimelineHandleType", eError, PVRSRV_ERROR_INVALID_PARAMS, e1);
+       }
+
+       /* Allocate:
+        *              Fence
+        *              Sync Signal CB
+        *              SyncPt List
+        *              Sync Checkpoint
+        *              SyncPt
+        *              Handle
+        *      Setup
+        */
+       psNewFence = OSAllocMem(sizeof(*psNewFence));
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence, eError, e2);
+
+       psNewSyncSignalCB = OSAllocMem(sizeof(*psNewSyncSignalCB));
+       PVR_LOG_GOTO_IF_NOMEM(psNewSyncSignalCB, eError, e3);
+
+       psNewFence->apsFenceSyncList = OSAllocMem(sizeof(*(psNewFence->apsFenceSyncList)));
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence->apsFenceSyncList, eError, e4);
+
+       psNewFence->psDevNode = psDeviceNode;
+
+       /* Lock down TL until new point is fully created and inserted */
+       OSLockAcquire(psTl->hTlLock);
+
+       eError = _SyncFbSyncPtCreate(&psNewSyncPt,
+                                    psTl,
+                                    OSAtomicIncrement(&psTl->iSeqNum));
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               OSLockRelease(psTl->hTlLock);
+               ERR("Cannot allocate SyncPt.");
+               goto e5;
+       }
+
+       eError = SyncCheckpointAlloc(psSyncCheckpointContext,
+                                    iTl,
+                                    PVRSRV_NO_FENCE,
+                                    pszName,
+                                    ppsOutCheckpoint);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               OSLockRelease(psTl->hTlLock);
+               ERR("Cannot allocate SyncCheckpoint.");
+               goto e6;
+       }
+
+       ui32FwAddr = SyncCheckpointGetFirmwareAddr(*ppsOutCheckpoint);
+
+       /* Init Sync Signal CB */
+       psNewSyncSignalCB->hAttachedSync = (IMG_HANDLE) *ppsOutCheckpoint;
+       psNewSyncSignalCB->pfnSignal = &_SyncFbSyncPtSignalPVR;
+       psNewSyncSignalCB->pfnSyncFree = &_SyncFbSyncPtFreePVR;
+       psNewSyncSignalCB->hPrivData = (IMG_HANDLE) psSyncCheckpointContext;
+
+       dllist_add_to_tail(&psNewSyncPt->sSignalCallbacks,
+                          &psNewSyncSignalCB->sCallbackNode);
+
+       OSLockRelease(psTl->hTlLock);
+
+       DBG(("%s: Inserting key <%p> = %p", __func__, *ppsOutCheckpoint, psNewSyncPt));
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+       HASH_Insert_Extended(gsSyncFbContext.sCheckpointHashTable, (void *)&ui32FwAddr, (uintptr_t) psNewSyncPt);
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       /* Init Fence */
+       OSStringLCopy(psNewFence->pszName,
+                     pszName,
+                     SYNC_FB_FENCE_MAX_LENGTH);
+
+       psNewFence->apsFenceSyncList[0] = psNewSyncPt;
+       psNewFence->uiNumSyncs = 1;
+       FENCE_REF_SET(&psNewFence->iRef, 1, psNewFence);
+       OSAtomicWrite(&psNewFence->iStatus, PVRSRV_SYNC_NOT_SIGNALLED);
+       psNewFence->iUID = (IMG_INT64)(uintptr_t) psNewFence; /* Not unique throughout the driver lifetime */
+
+       eError = PVRSRVAllocHandle(psHandleBase,
+                                  &hOutFence,
+                                  (void*) psNewFence,
+                                  PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                  PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                  (PFN_HANDLE_RELEASE) &SyncFbFenceRelease);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVAllocHandle", e7);
+
+       _SyncFbFenceListAdd(psNewFence);
+
+       PDUMPCOMMENTWITHFLAGS(psNewFence->psDevNode, 0,
+                             "Allocated PVR Fence %s (ID:%"IMG_UINT64_FMTSPEC") with Checkpoint (ID:%d) "
+                             "on Timeline %s (ID:%"IMG_UINT64_FMTSPEC")",
+                             psNewFence->pszName,
+                             psNewFence->iUID,
+                             SyncCheckpointGetId(psNewSyncSignalCB->hAttachedSync),
+                             psTl->pszName,
+                             psTl->iUID);
+
+       PVRSRVReleaseHandle(psHandleBase,
+                           (IMG_HANDLE) (uintptr_t) iTl,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+
+       *puiFenceUID = psNewFence->iUID;
+       *piOutFence = (PVRSRV_FENCE) (uintptr_t) hOutFence;
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, psNewFence);
+
+e7:
+       SyncCheckpointFree(*ppsOutCheckpoint);
+e6:
+       _SyncFbSyncPtRelease(psNewSyncPt, IMG_FALSE);
+e5:
+       OSFreeMem(psNewFence->apsFenceSyncList);
+e4:
+       OSFreeMem(psNewSyncSignalCB);
+e3:
+       OSFreeMem(psNewFence);
+e2:
+e1:
+       PVRSRVReleaseHandle(psHandleBase,
+                           (IMG_HANDLE) (uintptr_t) iTl,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+e0:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* Resolve caller has to free the sync checkpoints and free the
+ * array that holds the pointers. */
+PVRSRV_ERROR SyncFbFenceResolvePVR(PSYNC_CHECKPOINT_CONTEXT psContext,
+                                   PVRSRV_FENCE iFence,
+                                   IMG_UINT32 *puiNumCheckpoints,
+                                   PSYNC_CHECKPOINT **papsCheckpoints,
+                                   IMG_UINT64 *pui64FenceUID)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_SERVER *psFence;
+       PVRSRV_HANDLE_BASE *psHBase;
+       PSYNC_CHECKPOINT *apsCheckpoints;
+       PSYNC_CHECKPOINT psCheckpoint;
+       PVRSRV_SYNC_SIGNAL_CB *psSyncCB, *psNewSyncCB;
+       PVRSRV_SYNC_PT *psSyncPt;
+       PDLLIST_NODE psNode;
+       IMG_UINT32 i, uiNumCheckpoints = 0;
+
+       PVR_DPF_ENTERED;
+
+       if (iFence == PVRSRV_NO_FENCE)
+       {
+               *puiNumCheckpoints = 0;
+               eError = PVRSRV_OK;
+               goto e0;
+       }
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE) (uintptr_t) iFence,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                        IMG_TRUE,
+                                        (void**)&psFence,
+                                        &psHBase);
+       PVR_GOTO_IF_ERROR(eError, e0);
+
+       apsCheckpoints = OSAllocMem(sizeof(*apsCheckpoints) * psFence->uiNumSyncs);
+       PVR_LOG_GOTO_IF_NOMEM(apsCheckpoints, eError, e1);
+
+       /* Go through all syncs and add them to the list */
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               psNewSyncCB = NULL;
+               psSyncPt = psFence->apsFenceSyncList[i];
+
+               /* Don't skip signalled fences on PDUMP to make sure we set up proper
+                  synchronisation in the pdump stream. */
+#if !defined(PDUMP)
+               if (_SyncFbSyncPtHasSignalled(psSyncPt))
+               {
+                       continue;
+               }
+#endif
+
+               OSLockAcquire(gsSyncFbContext.hFbContextLock);
+               OSLockAcquire(psSyncPt->psTl->hTlLock);
+               psNode = dllist_get_next_node(&psSyncPt->sSignalCallbacks);
+               psSyncCB = IMG_CONTAINER_OF(psNode, PVRSRV_SYNC_SIGNAL_CB, sCallbackNode);
+
+               /* If we have a sync checkpoint AND
+                * it uses the same context as the given one,
+                * just add the checkpoint to the resolve list.*/
+               if ((_SyncFbSyncPtHandleType(psSyncCB) == PVRSRV_SYNC_HANDLE_PVR) &&
+                   (psContext == (PSYNC_CHECKPOINT_CONTEXT) psSyncCB->hPrivData))
+               {
+                       psCheckpoint = (PSYNC_CHECKPOINT) psSyncCB->hAttachedSync;
+               }
+               /* Else create a new sync checkpoint in the given context */
+               else
+               {
+                       IMG_UINT32 ui32FwAddr;
+
+                       eError = SyncCheckpointAlloc(psContext,
+                                                    SYNC_CHECKPOINT_FOREIGN_CHECKPOINT,
+                                                    iFence,
+                                                    psFence->pszName,
+                                                    &psCheckpoint);
+                       if (eError != PVRSRV_OK)
+                       {
+                               OSLockRelease(psSyncPt->psTl->hTlLock);
+                               OSLockRelease(gsSyncFbContext.hFbContextLock);
+                               goto e2;
+                       }
+
+                       psNewSyncCB = OSAllocMem(sizeof(*psNewSyncCB));
+                       if (psNewSyncCB == NULL)
+                       {
+                               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               OSLockRelease(psSyncPt->psTl->hTlLock);
+                               OSLockRelease(gsSyncFbContext.hFbContextLock);
+                               goto e3;
+                       }
+
+                       psNewSyncCB->hAttachedSync = (IMG_HANDLE) psCheckpoint;
+                       psNewSyncCB->hPrivData = (IMG_HANDLE) psContext;
+                       psNewSyncCB->pfnSignal = &_SyncFbSyncPtSignalPVR;
+                       psNewSyncCB->pfnSyncFree = &_SyncFbSyncPtFreePVR;
+                       dllist_add_to_tail(&psFence->apsFenceSyncList[i]->sSignalCallbacks,
+                                          &psNewSyncCB->sCallbackNode);
+
+                       /* Insert the checkpoint into the firmware address lookup table,
+                        * in case this checkpoint gets errored by the host driver. */
+                       ui32FwAddr = SyncCheckpointGetFirmwareAddr(psCheckpoint);
+
+                       DBG(("%s: Inserting key (fwAddr0x%x)<%p> = %p", __func__, ui32FwAddr, psCheckpoint, psSyncPt));
+                       HASH_Insert_Extended(gsSyncFbContext.sCheckpointHashTable, (void *)&ui32FwAddr, (uintptr_t) psSyncPt);
+
+                       /* If the existing sync pt has already been signalled, then signal
+                        * this new sync too */
+                       if (_SyncFbSyncPtHasSignalled(psFence->apsFenceSyncList[i]))
+                       {
+                               _SyncFbSyncPtSignalPVR(psNewSyncCB->hAttachedSync, PVRSRV_SYNC_SIGNALLED);
+                       }
+               }
+               OSLockRelease(psSyncPt->psTl->hTlLock);
+               OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+               /* Take a reference, resolve caller is responsible
+                * to drop it after use */
+               eError = SyncCheckpointTakeRef(psCheckpoint);
+               PVR_GOTO_IF_ERROR(eError, e4);
+
+               apsCheckpoints[uiNumCheckpoints++] = psCheckpoint;
+       }
+
+       *pui64FenceUID = psFence->iUID;
+       *puiNumCheckpoints = uiNumCheckpoints;
+       *papsCheckpoints = apsCheckpoints;
+
+       PVRSRVReleaseHandle(psHBase,
+                           (IMG_HANDLE) (uintptr_t) iFence,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+
+       PVR_DPF_RETURN_OK;
+
+e4:
+       if (psNewSyncCB)
+               OSFreeMem(psNewSyncCB);
+e3:
+       SyncCheckpointFree(psCheckpoint);
+e2:
+       for (; i > 0; i--)
+       {
+               SyncCheckpointDropRef(apsCheckpoints[i-1]);
+               SyncCheckpointFree(apsCheckpoints[i-1]);
+       }
+
+       OSFreeMem(apsCheckpoints);
+e1:
+       PVRSRVReleaseHandle(psHBase,
+                           (IMG_HANDLE) (uintptr_t) iFence,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+e0:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* In case something went wrong after FenceCreate we can roll back (destroy)
+ * the fence in the server */
+static PVRSRV_ERROR SyncFbFenceRollbackPVR(PVRSRV_FENCE iFence, void *pvFenceData)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_DPF_ENTERED;
+       PVR_UNREFERENCED_PARAMETER(pvFenceData);
+
+       PVR_GOTO_IF_INVALID_PARAM(iFence != PVRSRV_NO_FENCE, eError, e1);
+
+       eError = _SyncFbDestroyHandle((IMG_HANDLE) (uintptr_t) iFence,
+                                     PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER);
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       PVR_DPF_RETURN_OK;
+
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* Dump debug info on syncs relating to any of the FWAddrs in the
+ * given array. This is called when rgx_ccb.c determines we have a
+ * stalled CCB, so this debug will aid in debugging which sync(s)
+ * have failed to signal.
+ */
+IMG_UINT32 SyncFbDumpInfoOnStalledUFOs(IMG_UINT32 nr_ufos, IMG_UINT32 *vaddrs)
+{
+       IMG_UINT32 ui32NumFallbackUfos = 0;
+       PDLLIST_NODE psFenceNode, psNextFenceNode;
+       PVRSRV_FENCE_SERVER *psFence;
+       IMG_UINT32 *pui32NextFWAddr = vaddrs;
+       IMG_UINT32 ui32CurrentUfo;
+
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+
+       for (ui32CurrentUfo=0; ui32CurrentUfo<nr_ufos; ui32CurrentUfo++)
+       {
+               if (pui32NextFWAddr)
+               {
+                       /* Iterate over all fences */
+                       dllist_foreach_node(&gsSyncFbContext.sFenceList,
+                                                               psFenceNode,
+                                                               psNextFenceNode)
+                       {
+                               IMG_UINT32 i;
+                               IMG_BOOL bFenceDumped = IMG_FALSE;
+                               IMG_UINT32                        ui32SyncPtBitmask = 0;
+                               IMG_UINT32                        ui32SyncCheckpointFWAddr = 0;
+                               PVRSRV_SYNC_PT            *psSyncPt = NULL;
+
+                               psFence = IMG_CONTAINER_OF(psFenceNode,
+                                                                                  PVRSRV_FENCE_SERVER,
+                                                                                  sFenceListNode);
+
+                               /* ... all sync points in the fence */
+                               for (i = 0; i < psFence->uiNumSyncs; i++)
+                               {
+                                       PDLLIST_NODE psCBNode, psNextCBNode;
+
+                                       psSyncPt = psFence->apsFenceSyncList[i];
+
+                                       dllist_foreach_node(&psSyncPt->sSignalCallbacks,
+                                                                               psCBNode,
+                                                                               psNextCBNode)
+                                       {
+                                               PVRSRV_SYNC_SIGNAL_CB *psCb = IMG_CONTAINER_OF(psCBNode,
+                                                                                              PVRSRV_SYNC_SIGNAL_CB,
+                                                                                              sCallbackNode);
+
+                                               switch (_SyncFbSyncPtHandleType(psCb))
+                                               {
+                                                       case PVRSRV_SYNC_HANDLE_PVR:
+                                                       {
+                                                               ui32SyncCheckpointFWAddr = SyncCheckpointGetFirmwareAddr(psCb->hAttachedSync);
+                                                               ui32SyncPtBitmask |= 1;
+                                                               break;
+                                                       }
+                                                       case PVRSRV_SYNC_HANDLE_SW:
+                                                       {
+                                                               ui32SyncPtBitmask |= 2;
+                                                               break;
+                                                       }
+                                                       default:
+                                                               break;
+                                               }
+                                       }
+                               }
+
+                               if ((ui32SyncPtBitmask == 0x3) &&
+                                       (ui32SyncCheckpointFWAddr == *pui32NextFWAddr))
+                               {
+                                       /* Print fence info (if not already done so) */
+                                       if (!bFenceDumped)
+                                       {
+                                               PVR_LOG(("Fence: %s, ID: %"IMG_UINT64_FMTSPEC", %s - (0x%p)",
+                                                                 psFence->pszName,
+                                                                 psFence->iUID,
+                                                                 _SyncFbFenceSyncsHaveSignalled(psFence) ?
+                                                                                 "Signalled" : "Pending  ",
+                                                                 psFence));
+                                               bFenceDumped = IMG_TRUE;
+                                       }
+                                       _SyncFbDebugRequestPrintSyncPt(psSyncPt,
+                                                                      IMG_TRUE,
+                                                                                                  NULL,
+                                                                                                  NULL);
+                                       ui32NumFallbackUfos++;
+                               }
+                       }
+                       pui32NextFWAddr++;
+               }
+       }
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       return ui32NumFallbackUfos;
+}
+
+static inline PVRSRV_SYNC_STATE _SyncFbCheckpointToSyncState(PVRSRV_SYNC_CHECKPOINT_STATE eState)
+{
+       switch (eState)
+       {
+               case PVRSRV_SYNC_CHECKPOINT_SIGNALLED:
+                       return PVRSRV_SYNC_SIGNALLED;
+               case PVRSRV_SYNC_CHECKPOINT_ERRORED:
+                       return PVRSRV_SYNC_ERRORED;
+               case PVRSRV_SYNC_CHECKPOINT_ACTIVE:
+                       return PVRSRV_SYNC_NOT_SIGNALLED;
+               default:
+                       PVR_ASSERT("Unknown sync checkpoint state");
+                       return PVRSRV_SYNC_ERRORED;
+       }
+}
+
+IMG_BOOL SyncFbCheckpointHasSignalled(IMG_UINT32 ui32FwAddr, IMG_UINT32 ui32Value)
+{
+       PVRSRV_SYNC_PT *psSyncPt;
+       PVRSRV_SYNC_STATE eSignal;
+       PVRSRV_SYNC_SIGNAL_CB *psCB;
+       PDLLIST_NODE psCurrentCB, psNextCB;
+
+       PVR_DPF_ENTERED1(ui32FwAddr);
+
+       OSLockAcquire(gsSyncFbContext.hFbContextLock);
+
+       DBG(("%s: Looking up key (fwAddr=0x%x)", __func__, ui32FwAddr));
+       psSyncPt = (PVRSRV_SYNC_PT *) HASH_Retrieve_Extended(gsSyncFbContext.sCheckpointHashTable, (void *) &ui32FwAddr);
+       DBG(("%s: Found sync pt <%p>", __func__, psSyncPt));
+
+       if (!psSyncPt)
+       {
+               /* Sync Fallback does not know about this UFO, skip processing it. */
+               goto err_release;
+       }
+
+       eSignal = _SyncFbCheckpointToSyncState(ui32Value);
+       _SyncFbSyncPtSignal(psSyncPt, eSignal);
+
+       /*
+        * Signal all attachments except for the one representing the signalled
+        * checkpoint.
+        */
+
+       if (dllist_is_empty(&psSyncPt->sSignalCallbacks))
+       {
+               ERR("Sync pt has no attached syncs. Make sure to attach one "
+                   "when creating a new sync pt to define its flavour");
+       }
+
+       dllist_foreach_node(&psSyncPt->sSignalCallbacks, psCurrentCB, psNextCB)
+       {
+               psCB = IMG_CONTAINER_OF(psCurrentCB,
+                                       PVRSRV_SYNC_SIGNAL_CB,
+                                       sCallbackNode);
+
+               if (_SyncFbSyncPtHandleType(psCB) == PVRSRV_SYNC_HANDLE_PVR &&
+                   SyncCheckpointGetFirmwareAddr(psCB->hAttachedSync) == ui32FwAddr)
+               {
+                       continue;
+               }
+
+               if (psCB->pfnSignal(psCB->hAttachedSync, eSignal) != PVRSRV_OK)
+               {
+                       ERR("Failed to signal an attached sync, system might block!");
+                       /* Don't jump to exit but try to signal remaining syncs */
+               }
+       }
+
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+
+       PVR_DPF_RETURN_RC(IMG_TRUE);
+
+err_release:
+       OSLockRelease(gsSyncFbContext.hFbContextLock);
+       PVR_DPF_RETURN_RC(IMG_FALSE);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*                         SW SPECIFIC FUNCTIONS                            */
+/*                                                                           */
+/*****************************************************************************/
+
+/* Free a SW sync point with its sync checkpoint */
+static void _SyncFbSyncPtFreeSW(IMG_HANDLE hSync)
+{
+       PVR_DPF_ENTERED1(hSync);
+
+       OSFreeMem(hSync);
+
+       PVR_DPF_RETURN;
+}
+
+static IMG_BOOL _SyncFbSyncPtHasSignalledSW(PVRSRV_SYNC_PT *psSyncPt)
+{
+       PDLLIST_NODE psCBNode;
+       PVRSRV_SYNC_SIGNAL_CB *psCB;
+       PVRSRV_SYNC_PT_SW *psSWSyncPt;
+       IMG_BOOL bRet = IMG_FALSE;
+
+       PVR_DPF_ENTERED1(psSyncPt);
+
+       /* If the SyncPt has not been signalled yet,
+        * check whether the first attached sync has.
+        *
+        * Change SyncPt state to signalled or errored if yes.
+        * Also notify other attached syncs.
+        */
+       if (OSAtomicRead(&psSyncPt->iStatus) == PVRSRV_SYNC_NOT_SIGNALLED)
+       {
+               /* List must have at least the device sync attached if we are called */
+               PVR_ASSERT(!dllist_is_empty(&psSyncPt->sSignalCallbacks));
+
+               /* Retrieve the first sync checkpoint of that sync pt */
+               psCBNode = dllist_get_next_node(&psSyncPt->sSignalCallbacks);
+               psCB = IMG_CONTAINER_OF(psCBNode, PVRSRV_SYNC_SIGNAL_CB, sCallbackNode);
+               psSWSyncPt = (PVRSRV_SYNC_PT_SW*) psCB->hAttachedSync;
+
+               if (psSWSyncPt->bSignalled)
+               {
+                       _SyncFbSyncPtSignal(psSyncPt, PVRSRV_SYNC_SIGNALLED);
+
+                       /* Signal all other attached syncs */
+                       PVR_LOG_IF_ERROR(_SyncFbSyncPtSignalAttached(psSyncPt, PVRSRV_SYNC_SIGNALLED),
+                                        "_SyncFbSyncPtSignalAttached");
+
+                       bRet = IMG_TRUE;
+               }
+
+               PVR_DPF_RETURN_RC1(bRet, psSyncPt);
+       }
+       else
+       {
+               PVR_DPF_RETURN_RC1(IMG_TRUE, psSyncPt);
+       }
+}
+
+/* Mark an attached sw sync pt with the given state.
+ * MAKE SURE TO WAKE UP FW AFTER CALLING THIS (if enqueued)*/
+static PVRSRV_ERROR _SyncFbSyncPtSignalSW(IMG_HANDLE hSync,
+                                          PVRSRV_SYNC_STATE eState)
+{
+       PVRSRV_SYNC_PT_SW *psSWSyncPt = (PVRSRV_SYNC_PT_SW*) hSync;
+
+       PVR_DPF_ENTERED1(hSync);
+
+       if (!psSWSyncPt->bSignalled)
+       {
+               switch (eState)
+               {
+                       case PVRSRV_SYNC_SIGNALLED:
+                       case PVRSRV_SYNC_ERRORED:
+                               psSWSyncPt->bSignalled = IMG_TRUE;
+                               break;
+                       default:
+                               ERR("Passed unknown sync state (%d), "
+                                               "please use a valid one for signalling.",
+                                               eState);
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, hSync);
+}
+
+PVRSRV_ERROR SyncFbTimelineCreateSW(IMG_UINT32 uiTimelineNameSize,
+                                    const IMG_CHAR *pszTimelineName,
+                                    PVRSRV_TIMELINE_SERVER **ppsTimeline)
+{
+       return _SyncFbTimelineCreate(&_SyncFbSyncPtHasSignalledSW,
+                                    uiTimelineNameSize,
+                                    pszTimelineName,
+                                    ppsTimeline);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*                       SOFTWARE_TIMELINE FUNCTIONS                         */
+/*                                                                           */
+/*****************************************************************************/
+static PVRSRV_ERROR _SyncFbSWTimelineFenceCreate(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                          PVRSRV_TIMELINE_SERVER *psTl,
+                                          IMG_UINT32 uiFenceNameSize,
+                                          const IMG_CHAR *pszFenceName,
+                                          PVRSRV_FENCE_SERVER **ppsOutputFence,
+                                          IMG_UINT64 *pui64SyncPtIdx)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_FENCE_SERVER *psNewFence;
+       PVRSRV_SYNC_PT *psNewSyncPt = NULL;
+       PVRSRV_SYNC_PT_SW *psNewSWSyncPt;
+       PVRSRV_SYNC_SIGNAL_CB *psNewSyncSignalCB;
+       IMG_INT iNextSeqNum;
+
+       if (_SyncFbTimelineHandleType(psTl) != PVRSRV_SYNC_HANDLE_SW)
+       {
+               ERR("Passed timeline is not a SW timeline.");
+               eError = PVRSRV_ERROR_NOT_SW_TIMELINE;
+               goto e1;
+       }
+
+       /* Allocate:
+        *              Fence
+        *              Sync Signal CB
+        *              SyncPt List
+        *              SW Sync
+        *              SyncPt
+        *              Handle
+        *      Setup
+        */
+       psNewFence = OSAllocMem(sizeof(*psNewFence));
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence, eError, e1);
+
+       psNewFence->psDevNode = psDeviceNode;
+
+       psNewSyncSignalCB = OSAllocMem(sizeof(*psNewSyncSignalCB));
+       PVR_LOG_GOTO_IF_NOMEM(psNewSyncSignalCB, eError, e2);
+
+       psNewFence->apsFenceSyncList = OSAllocMem(sizeof(*(psNewFence->apsFenceSyncList)));
+       PVR_LOG_GOTO_IF_NOMEM(psNewFence->apsFenceSyncList, eError, e3);
+
+       psNewSWSyncPt = OSAllocMem(sizeof(*psNewSWSyncPt));
+       PVR_LOG_GOTO_IF_NOMEM(psNewSWSyncPt, eError, e4);
+
+       /* Lock down TL until new point is fully created and inserted */
+       OSLockAcquire(psTl->hTlLock);
+
+       /* Sample our next sync pt value - we won't actually increment
+        * iSeqNum for this SW timeline until we know the fence has been
+        * successfully created.
+        */
+       iNextSeqNum = OSAtomicRead(&psTl->iSeqNum) + 1;
+
+       eError = _SyncFbSyncPtCreate(&psNewSyncPt, psTl, iNextSeqNum);
+       if (eError != PVRSRV_OK)
+       {
+               OSLockRelease(psTl->hTlLock);
+               goto e5;
+       }
+
+       if (OSAtomicRead(&psTl->iLastSignalledSeqNum) < psNewSyncPt->uiSeqNum)
+       {
+               psNewSWSyncPt->bSignalled = IMG_FALSE;
+       }
+       else
+       {
+               psNewSWSyncPt->bSignalled = IMG_TRUE;
+               OSAtomicWrite(&psNewSyncPt->iStatus, PVRSRV_SYNC_SIGNALLED);
+       }
+
+       /* Init Sync Signal CB */
+       psNewSyncSignalCB->hAttachedSync = (IMG_HANDLE) psNewSWSyncPt;
+       psNewSyncSignalCB->pfnSignal = &_SyncFbSyncPtSignalSW;
+       psNewSyncSignalCB->pfnSyncFree = &_SyncFbSyncPtFreeSW;
+       psNewSyncSignalCB->hPrivData = NULL;
+
+       dllist_add_to_tail(&psNewSyncPt->sSignalCallbacks,
+                                          &psNewSyncSignalCB->sCallbackNode);
+
+       /* Now that the fence has been created, increment iSeqNum */
+       OSAtomicIncrement(&psTl->iSeqNum);
+
+       OSLockRelease(psTl->hTlLock);
+
+       if (pszFenceName)
+       {
+               /* Init Fence */
+               OSStringLCopy(psNewFence->pszName,
+                             pszFenceName,
+                             SYNC_FB_FENCE_MAX_LENGTH);
+       }
+       else
+       {
+               psNewFence->pszName[0] = '\0';
+       }
+
+       psNewFence->apsFenceSyncList[0] = psNewSyncPt;
+       psNewFence->uiNumSyncs = 1;
+       FENCE_REF_SET(&psNewFence->iRef, 1, psNewFence);
+       OSAtomicWrite(&psNewFence->iStatus, PVRSRV_FENCE_NOT_SIGNALLED);
+       psNewFence->iUID = (IMG_INT64)(uintptr_t) psNewFence;
+
+       _SyncFbFenceListAdd(psNewFence);
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                 "Allocated SW Fence %s (ID:%"IMG_UINT64_FMTSPEC") with sequence number %u "
+                                                 "on Timeline %s (ID:%"IMG_UINT64_FMTSPEC")",
+                                                 psNewFence->pszName,
+                                                 psNewFence->iUID,
+                                                 psNewSyncPt->uiSeqNum,
+                                                 psTl->pszName,
+                                                 psTl->iUID);
+
+       *ppsOutputFence = psNewFence;
+       if (pui64SyncPtIdx != NULL)
+       {
+               *pui64SyncPtIdx = psNewSyncPt->uiSeqNum;
+       }
+
+       PVR_DPF_RETURN_RC1(PVRSRV_OK, psNewFence);
+
+e5:
+       OSFreeMem(psNewSWSyncPt);
+e4:
+       OSFreeMem(psNewFence->apsFenceSyncList);
+e3:
+       OSFreeMem(psNewSyncSignalCB);
+e2:
+       OSFreeMem(psNewFence);
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/* Kernel mode function (SyncFb implementation) to create fence on a SW timeline */
+PVRSRV_ERROR SyncFbSWTimelineFenceCreateKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           PVRSRV_TIMELINE iSWTimeline,
+                                           const IMG_CHAR *pszFenceName,
+                                           PVRSRV_FENCE *piOutputFence,
+                                           IMG_UINT64 *pui64SyncPtIdx)
+{
+
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_SERVER *psNewFence;
+       PVRSRV_HANDLE_BASE      *psHandleBase;
+       PVRSRV_TIMELINE_SERVER *psTl;
+       IMG_HANDLE hOutFence;
+
+       PVR_DPF_ENTERED;
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(piOutputFence, eError, e0);
+
+       /* Lookup up the ST Timeline (and take a reference on it while
+        * we are creating the new sync pt and fence)
+        */
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE) (uintptr_t) iSWTimeline,
+                                                                        PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                                                        IMG_TRUE,
+                                                                        (void**) &psTl,
+                                                                        &psHandleBase);
+       PVR_GOTO_IF_ERROR(eError, e0);
+
+       eError = _SyncFbSWTimelineFenceCreate(psDeviceNode, psTl,
+                                             OSStringLength(pszFenceName),
+                                             pszFenceName,
+                                             &psNewFence,
+                                             pui64SyncPtIdx);
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       eError = PVRSRVAllocHandle(psHandleBase,
+                                                          &hOutFence,
+                                                          (void*) psNewFence,
+                                                          PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                                          PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+                                                          (PFN_HANDLE_RELEASE) &SyncFbFenceRelease);
+       PVR_GOTO_IF_ERROR(eError, e2);
+
+       /* Drop the reference we took on the timeline earlier */
+       PVRSRVReleaseHandle(psHandleBase,
+                           (IMG_HANDLE) (uintptr_t) iSWTimeline,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+
+       *piOutputFence = (PVRSRV_FENCE) (uintptr_t) hOutFence;
+
+       return PVRSRV_OK;
+
+e2:
+       /* Release the fence we created, as we failed to
+        * allocate a handle for it */
+       SyncFbFenceRelease(psNewFence);
+
+e1:
+       /* Drop the reference we took on the timeline earlier */
+       PVRSRVReleaseHandle(psHandleBase,
+                           (IMG_HANDLE) (uintptr_t) iSWTimeline,
+                           PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER);
+e0:
+       PVR_DPF_RETURN_RC(eError);
+
+}
+
+/* Client (bridge) interface to the SyncSWTimelineFenceCreateKM() function */
+PVRSRV_ERROR SyncFbFenceCreateSW(CONNECTION_DATA *psConnection,
+                                 PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 PVRSRV_TIMELINE_SERVER *psTimeline,
+                                 IMG_UINT32 uiFenceNameSize,
+                                 const IMG_CHAR *pszFenceName,
+                                 PVRSRV_FENCE_SERVER **ppsOutputFence,
+                                 IMG_UINT64 *pui64SyncPtIdx)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       eError =  _SyncFbSWTimelineFenceCreate(psDeviceNode,
+                                              psTimeline,
+                                              0,
+                                              pszFenceName,
+                                              ppsOutputFence,
+                                              pui64SyncPtIdx);
+
+       return eError;
+}
+
+static PVRSRV_ERROR _SyncSWTimelineAdvanceSigErr(PVRSRV_TIMELINE_SERVER *psTl,
+                                                 PVRSRV_SYNC_STATE eState,
+                                                 IMG_UINT64 *pui64SyncPtIdx)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PDLLIST_NODE psPtNode, psNextNode;
+       PVRSRV_SYNC_PT *psSyncPt;
+       IMG_INT32 uiTlSeqNum;
+
+       PVR_DPF_ENTERED1(psTl);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(psTl, eError, errExit);
+
+       if (_SyncFbTimelineHandleType(psTl) != PVRSRV_SYNC_HANDLE_SW)
+       {
+               ERR("Passed timeline is not a SW timeline.");
+               eError = PVRSRV_ERROR_NOT_SW_TIMELINE;
+               goto errExit;
+       }
+
+       OSLockAcquire(psTl->hTlLock);
+
+       /* Don't allow incrementing of SW timeline beyond its last created pt */
+       if (OSAtomicRead(&psTl->iLastSignalledSeqNum) == OSAtomicRead(&psTl->iSeqNum))
+       {
+               DBG(("%s: !! TL<%p> (%d->%d/%d) !!", __func__, (void*)psTl, OSAtomicRead(&psTl->iLastSignalledSeqNum), OSAtomicRead(&psTl->iLastSignalledSeqNum)+1, OSAtomicRead(&psTl->iSeqNum)));
+               WRN("Attempt to advance SW timeline beyond last created point.");
+               eError = PVRSRV_ERROR_SW_TIMELINE_AT_LATEST_POINT;
+               goto errUnlockAndExit;
+       }
+
+       uiTlSeqNum = OSAtomicIncrement(&psTl->iLastSignalledSeqNum);
+
+       /* Go through list of active sync pts and
+        * signal the points that are met now */
+       dllist_foreach_node(&psTl->sSyncActiveList, psPtNode, psNextNode)
+       {
+               psSyncPt = IMG_CONTAINER_OF(psPtNode,
+                                           PVRSRV_SYNC_PT,
+                                           sTlSyncActiveList);
+               if (psSyncPt->uiSeqNum <= uiTlSeqNum)
+               {
+                       _SyncFbSyncPtSignal(psSyncPt, eState);
+
+                       /* Signal all other attached syncs */
+                       PVR_LOG_IF_ERROR(_SyncFbSyncPtSignalAttached(psSyncPt, eState),
+                                        "_SyncFbSyncPtSignalAttached");
+
+                       dllist_remove_node(psPtNode);
+               }
+       }
+
+       OSLockRelease(psTl->hTlLock);
+
+       if (pui64SyncPtIdx != NULL)
+       {
+               *pui64SyncPtIdx = uiTlSeqNum;
+       }
+
+       /* A completed SW operation may un-block the GPU */
+       PVRSRVCheckStatus(NULL);
+
+       eError = _SyncFbSignalEO();
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbSignalEO", errExit);
+
+       PVR_DPF_RETURN_OK;
+
+errUnlockAndExit:
+       OSLockRelease(psTl->hTlLock);
+errExit:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+static void _SyncSWTimelineCheckForUnsignalledPts(PVRSRV_TIMELINE_SERVER *psTl)
+{
+       IMG_UINT32 ui32TlSeqNum = OSAtomicRead(&psTl->iSeqNum);
+       IMG_UINT32 ui32TlLastSigSeqNum = OSAtomicRead(&psTl->iLastSignalledSeqNum);
+
+       while (ui32TlLastSigSeqNum < ui32TlSeqNum)
+       {
+               ui32TlLastSigSeqNum++;
+               PVR_DPF((PVR_DBG_WARNING,"%s: Found unsignalled SW timeline <%p> '%s' sync pt (%d/%d)",__func__, psTl, psTl->pszName, ui32TlLastSigSeqNum, ui32TlSeqNum));
+               _SyncSWTimelineAdvanceSigErr(psTl, PVRSRV_SYNC_ERRORED, NULL);
+       }
+}
+
+/* kernel mode function to advance a SW timeline */
+PVRSRV_ERROR SyncFbSWTimelineAdvanceKM(void *pvSWTimelineObj, IMG_UINT64 *pui64SyncPtIdx)
+{
+       return _SyncSWTimelineAdvanceSigErr(pvSWTimelineObj,
+                                           PVRSRV_SYNC_SIGNALLED,
+                                           pui64SyncPtIdx);
+}
+
+/* Client (bridge) interface to the SyncSWTimelineAdvanceKM() function */
+PVRSRV_ERROR SyncFbTimelineAdvanceSW(PVRSRV_TIMELINE_SERVER *psTimeline,
+                                     IMG_UINT64 *pui64SyncPtIdx)
+{
+       return _SyncSWTimelineAdvanceSigErr(psTimeline,
+                                           PVRSRV_SYNC_SIGNALLED,
+                                           pui64SyncPtIdx);
+}
+
+PVRSRV_ERROR SyncFbFenceReleaseKM(void *pvFenceObj)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_DPF_ENTERED1(pvFenceObj);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(pvFenceObj, eError, e0);
+
+       eError = SyncFbFenceRelease((PVRSRV_FENCE_SERVER*) pvFenceObj);
+
+e0:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR SyncFbSWGetTimelineObj(PVRSRV_TIMELINE iSWTimeline,
+                                    void **ppvSWTimelineObj)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_HANDLE_BASE *psHB;
+
+       PVR_DPF_ENTERED1(iSWTimeline);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(iSWTimeline != PVRSRV_NO_TIMELINE, eError, err_out);
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE)(uintptr_t) iSWTimeline,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                        IMG_FALSE,
+                                        ppvSWTimelineObj,
+                                        &psHB);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbLookupProcHandle", err_out);
+
+       _SyncFbTimelineAcquire((PVRSRV_TIMELINE_SERVER*) *ppvSWTimelineObj);
+
+err_out:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+
+PVRSRV_ERROR SyncFbGetFenceObj(PVRSRV_FENCE iFence,
+                               void **ppvFenceObj)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_HANDLE_BASE *psHB;
+
+       PVR_DPF_ENTERED1(iFence);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(iFence != PVRSRV_NO_FENCE, eError, err_out);
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE)(uintptr_t) iFence,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_FENCE_SERVER,
+                                        IMG_FALSE,
+                                        ppvFenceObj,
+                                        &psHB);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbLookupProcHandle", err_out);
+
+       _SyncFbFenceAcquire((PVRSRV_FENCE_SERVER*) *ppvFenceObj);
+
+err_out:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR SyncFbDumpFenceKM(void *pvSWFenceObj,
+                                  DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                  void *pvDumpDebugFile)
+{
+       PVRSRV_FENCE_SERVER *psFence = (PVRSRV_FENCE_SERVER *) pvSWFenceObj;
+       IMG_UINT32 i;
+
+       PVR_DUMPDEBUG_LOG("Fence: %s, %-9s - <%#"IMG_UINT64_FMTSPECx">",
+                         psFence->pszName,
+                         _SyncFbFenceSyncsHaveSignalled(psFence) ?
+                             "Signalled" : "Active",
+                         psFence->iUID);
+
+       /* ... all sync points in the fence */
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               _SyncFbDebugRequestPrintSyncPt(psFence->apsFenceSyncList[i],
+                                              IMG_TRUE,
+                                              pfnDumpDebugPrintf,
+                                              pvDumpDebugFile);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SyncFbSWDumpTimelineKM(void *pvSWTimelineObj,
+                                    DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                    void *pvDumpDebugFile)
+{
+       PVRSRV_TIMELINE_SERVER *psTl = (PVRSRV_TIMELINE_SERVER *) pvSWTimelineObj;
+
+       OSLockAcquire(psTl->hTlLock);
+
+       PVR_DUMPDEBUG_LOG("TL: %s, SeqNum: %d/%d - <%#"IMG_UINT64_FMTSPECx">",
+                         psTl->pszName,
+                         OSAtomicRead(&psTl->iLastSignalledSeqNum),
+                         OSAtomicRead(&psTl->iSeqNum),
+                         psTl->iUID);
+
+       OSLockRelease(psTl->hTlLock);
+
+       return PVRSRV_OK;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*                       IMPORT/EXPORT FUNCTIONS                             */
+/*                                                                           */
+/*****************************************************************************/
+
+static PVRSRV_ERROR _SyncFbFenceExport(PVRSRV_FENCE_SERVER *psFence,
+                                       PVRSRV_FENCE_EXPORT **ppsExport)
+{
+       PVRSRV_FENCE_EXPORT *psExport;
+       PVRSRV_ERROR eError;
+
+       psExport = OSAllocMem(sizeof(*psExport));
+       PVR_LOG_GOTO_IF_NOMEM(psExport, eError, err_out);
+
+       _SyncFbFenceAcquire(psFence);
+
+       psExport->psFence = psFence;
+       *ppsExport = psExport;
+
+       eError = PVRSRV_OK;
+err_out:
+       return eError;
+}
+
+static PVRSRV_ERROR _SyncFbFenceExportDestroy(PVRSRV_FENCE_EXPORT *psExport)
+{
+       PVRSRV_ERROR eError;
+
+       eError = SyncFbFenceRelease(psExport->psFence);
+       PVR_LOG_IF_ERROR(eError, "SyncFbFenceRelease");
+
+       OSFreeMem(psExport);
+
+       return eError;
+}
+
+static PVRSRV_ERROR _SyncFbFenceImport(PVRSRV_FENCE_EXPORT *psImport,
+                                       PVRSRV_FENCE_SERVER **psFenceOut)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_SERVER *psFence;
+
+       psFence = psImport->psFence;
+       _SyncFbFenceAcquire(psFence);
+
+       *psFenceOut = psFence;
+
+       eError = PVRSRV_OK;
+       return eError;
+}
+
+#if defined(SUPPORT_INSECURE_EXPORT)
+PVRSRV_ERROR SyncFbFenceExportInsecure(PVRSRV_FENCE_SERVER *psFence,
+                                       PVRSRV_FENCE_EXPORT **ppsExport)
+{
+       return _SyncFbFenceExport(psFence, ppsExport);
+}
+
+PVRSRV_ERROR SyncFbFenceExportDestroyInsecure(PVRSRV_FENCE_EXPORT *psExport)
+{
+       return _SyncFbFenceExportDestroy(psExport);
+}
+
+PVRSRV_ERROR SyncFbFenceImportInsecure(CONNECTION_DATA *psConnection,
+                                       PVRSRV_DEVICE_NODE *psDevice,
+                                       PVRSRV_FENCE_EXPORT *psImport,
+                                       PVRSRV_FENCE_SERVER **psFenceOut)
+{
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVR_UNREFERENCED_PARAMETER(psDevice);
+
+       return _SyncFbFenceImport(psImport, psFenceOut);
+}
+#endif /* defined(SUPPORT_INSECURE_EXPORT) */
+
+PVRSRV_ERROR SyncFbFenceExportDestroySecure(PVRSRV_FENCE_EXPORT *psExport)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_DPF_ENTERED1(psExport);
+
+       eError = _SyncFbFenceExportDestroy(psExport);
+
+       PVR_DPF_RETURN_RC(eError);
+}
+
+static PVRSRV_ERROR _SyncFbReleaseSecureExport(void *pvExport)
+{
+       return SyncFbFenceExportDestroySecure(pvExport);
+}
+
+PVRSRV_ERROR SyncFbFenceExportSecure(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE * psDevNode,
+                                     PVRSRV_FENCE_SERVER *psFence,
+                                     IMG_SECURE_TYPE *phSecure,
+                                     PVRSRV_FENCE_EXPORT **ppsExport,
+                                     CONNECTION_DATA **ppsSecureConnection)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_EXPORT *psExport;
+
+       PVR_DPF_ENTERED1(psFence);
+
+       PVR_UNREFERENCED_PARAMETER(ppsSecureConnection);
+
+       eError = _SyncFbFenceExport(psFence, &psExport);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbFenceExport", err_out);
+
+       /* Transform it into a secure export */
+       eError = OSSecureExport("fallback_fence",
+                               _SyncFbReleaseSecureExport,
+                               (void *) psExport,
+                               phSecure);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSSecureExport", err_export);
+
+       *ppsExport = psExport;
+       PVR_DPF_RETURN_OK;
+err_export:
+       _SyncFbFenceExportDestroy(psExport);
+err_out:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR SyncFbFenceImportSecure(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDevice,
+                                     IMG_SECURE_TYPE hSecure,
+                                     PVRSRV_FENCE_SERVER **ppsFence)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_FENCE_EXPORT *psImport;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVR_UNREFERENCED_PARAMETER(psDevice);
+
+       PVR_DPF_ENTERED1(hSecure);
+
+       eError = OSSecureImport(hSecure, (void **) &psImport);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSSecureImport", err_out);
+
+       eError = _SyncFbFenceImport(psImport, ppsFence);
+
+       PVR_DPF_RETURN_OK;
+err_out:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*                            TESTING FUNCTIONS                              */
+/*                                                                           */
+/*****************************************************************************/
+#if defined(PVR_TESTING_UTILS)
+
+static void _GetCheckContext(PVRSRV_DEVICE_NODE *psDevNode,
+                             PSYNC_CHECKPOINT_CONTEXT *ppsSyncCheckpointContext)
+{
+       *ppsSyncCheckpointContext = psDevNode->hSyncCheckpointContext;
+}
+
+PVRSRV_ERROR TestIOCTLSyncFbFenceSignalPVR(CONNECTION_DATA *psConnection,
+                                           PVRSRV_DEVICE_NODE *psDevNode,
+                                           void *psFenceIn)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_SYNC_PT *psSyncPt;
+       IMG_UINT32 i;
+       PVRSRV_FENCE_SERVER *psFence = psFenceIn;
+
+       PVR_DPF_ENTERED;
+
+       for (i = 0; i < psFence->uiNumSyncs; i++)
+       {
+               psSyncPt = psFence->apsFenceSyncList[i];
+               OSAtomicWrite(&psSyncPt->iStatus, PVRSRV_SYNC_SIGNALLED);
+
+               OSLockAcquire(psSyncPt->psTl->hTlLock);
+               eError = _SyncFbSyncPtSignalAttached(psSyncPt, PVRSRV_SYNC_SIGNALLED);
+               PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbSyncPtSignalAttached", eSignal);
+
+               OSLockRelease(psSyncPt->psTl->hTlLock);
+       }
+
+       eError = _SyncFbSignalEO();
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbSignalEO", eExit);
+
+       PVR_DPF_RETURN_OK;
+
+eSignal:
+       OSLockRelease(psSyncPt->psTl->hTlLock);
+eExit:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+
+PVRSRV_ERROR TestIOCTLSyncFbFenceCreatePVR(CONNECTION_DATA *psConnection,
+                                           PVRSRV_DEVICE_NODE *psDevNode,
+                                           IMG_UINT32 uiNameLength,
+                                           const IMG_CHAR *pszName,
+                                           PVRSRV_TIMELINE iTL,
+                                           PVRSRV_FENCE *piOutFence)
+{
+       PSYNC_CHECKPOINT_CONTEXT psContext = NULL;
+       PSYNC_CHECKPOINT psCheckpoint;
+       PVRSRV_FENCE iFence;
+       PVRSRV_ERROR eError;
+       IMG_UINT64 uiFenceUID;
+
+       PVR_DPF_ENTERED;
+
+       if (iTL == PVRSRV_NO_TIMELINE)
+       {
+               WRN("Supplied invalid timeline, returning invalid fence!");
+               *piOutFence = PVRSRV_NO_FENCE;
+
+               eError = PVRSRV_OK;
+               goto e1;
+       }
+
+       _GetCheckContext(psDevNode,
+                        &psContext);
+
+       eError = SyncFbFenceCreatePVR(psDevNode,
+                                     pszName,
+                                     iTL,
+                                     psContext,
+                                     &iFence,
+                                     &uiFenceUID,
+                                     NULL,
+                                     &psCheckpoint,
+                                     NULL,
+                                     NULL);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SyncFbFenceCreatePVR", e1);
+
+       *piOutFence = iFence;
+
+       PVR_DPF_RETURN_OK;
+
+e1:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR TestIOCTLSyncFbFenceResolvePVR(CONNECTION_DATA *psConnection,
+                                            PVRSRV_DEVICE_NODE *psDevNode,
+                                            PVRSRV_FENCE iFence)
+{
+       PSYNC_CHECKPOINT_CONTEXT psContext = NULL;
+       PVRSRV_ERROR eError;
+       PSYNC_CHECKPOINT *apsChecks = NULL;
+       IMG_UINT32 uiNumChecks, i;
+       IMG_UINT64 uiFenceUID;
+
+       PVR_DPF_ENTERED;
+
+       _GetCheckContext(psDevNode,
+                        &psContext);
+
+       eError = SyncFbFenceResolvePVR(psContext,
+                                      iFence,
+                                      &uiNumChecks,
+                                      &apsChecks,
+                                      &uiFenceUID);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SyncFbFenceResolvePVR", eExit);
+
+       /* Close Checkpoints */
+       for (i = 0; i < uiNumChecks; i++)
+       {
+               SyncCheckpointFree(apsChecks[i]);
+       }
+
+       OSFreeMem(apsChecks);
+
+       PVR_DPF_RETURN_OK;
+
+eExit:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR TestIOCTLSyncFbSWTimelineAdvance(CONNECTION_DATA * psConnection,
+                                              PVRSRV_DEVICE_NODE *psDevNode,
+                                              PVRSRV_TIMELINE iSWTl)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_TIMELINE_SERVER *psSWTl;
+       PVRSRV_HANDLE_BASE *psHB;
+       SYNC_TIMELINE_OBJ sSWTimelineObj;
+
+       PVR_DPF_ENTERED;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       eError = _SyncFbLookupProcHandle((IMG_HANDLE) (uintptr_t) iSWTl,
+                                        PVRSRV_HANDLE_TYPE_PVRSRV_TIMELINE_SERVER,
+                                        IMG_FALSE,
+                                        (void**) &psSWTl,
+                                        &psHB);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_SyncFbLookupProcHandle", e0);
+
+       sSWTimelineObj.pvTlObj = psSWTl;
+       sSWTimelineObj.hTimeline = iSWTl;
+
+       eError = SyncSWTimelineAdvanceKM(psDevNode, &sSWTimelineObj);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SyncSWTimelineAdvanceKM", e0);
+
+       PVR_DPF_RETURN_OK;
+
+e0:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+PVRSRV_ERROR TestIOCTLSyncFbSWFenceCreate(CONNECTION_DATA * psConnection,
+                                          PVRSRV_DEVICE_NODE *psDevNode,
+                                          PVRSRV_TIMELINE iTl,
+                                          IMG_UINT32 uiFenceNameLength,
+                                          const IMG_CHAR *pszFenceName,
+                                          PVRSRV_FENCE *piFence)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_DPF_ENTERED;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       eError = SyncSWTimelineFenceCreateKM(psDevNode,
+                                            iTl,
+                                            pszFenceName,
+                                            piFence);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SyncSWTimelineFenceCreateKM", e0);
+
+       PVR_DPF_RETURN_OK;
+
+e0:
+       PVR_DPF_RETURN_RC(eError);
+}
+
+#endif /* PVR_TESTING_UTILS */
index a29436a..7398f44 100644 (file)
@@ -58,9 +58,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "htbuffer.h"
 #include "rgxhwperf.h"
 #include "info_page.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #include "sync_checkpoint_internal.h"
 #include "sync_checkpoint.h"
@@ -75,10 +72,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "ossecure_export.h"
 #endif
 
-#if defined(SUPPORT_EXTRA_METASP_DEBUG)
-#include "rgxdebug.h"
-#endif
-
 /* Set this to enable debug relating to the construction and maintenance of the sync address list */
 #define SYNC_ADDR_LIST_DEBUG 0
 
@@ -780,9 +773,6 @@ PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
                                                                IMG_UINT32 *puiSyncPrimBlockSize,
                                                                PMR        **ppsSyncPMR)
 {
-#ifdef CACHE_TEST
-       DEVMEM_MEMDESC *pxmdsc = NULL;
-#endif
        SYNC_PRIMITIVE_BLOCK *psNewSyncBlk;
        PVRSRV_ERROR eError;
 
@@ -791,7 +781,7 @@ PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
 
        psNewSyncBlk->psDevNode = psDevNode;
 
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Allocate UFO block");
+       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS, "Allocate UFO block");
 
        eError = psDevNode->pfnAllocUFOBlock(psDevNode,
                                                                                 &psNewSyncBlk->psMemDesc,
@@ -804,15 +794,6 @@ PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
        eError = DevmemAcquireCpuVirtAddr(psNewSyncBlk->psMemDesc,
                                                                          (void **) &psNewSyncBlk->pui32LinAddr);
        PVR_GOTO_IF_ERROR(eError, e2);
-#ifdef CACHE_TEST
-       pxmdsc = (DEVMEM_MEMDESC *)psNewSyncBlk->psMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psNewSyncBlk->pui32LinAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
 
        eError = DevmemLocalGetImportHandle(psNewSyncBlk->psMemDesc, (void **) ppsSyncPMR);
 
@@ -826,7 +807,7 @@ PVRSRVAllocSyncPrimitiveBlockKM(CONNECTION_DATA *psConnection,
        *ppsSyncBlk = psNewSyncBlk;
        *puiSyncPrimBlockSize = psNewSyncBlk->ui32BlockSize;
 
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevNode, PDUMP_FLAGS_CONTINUOUS,
                                                  "Allocated UFO block (FirmwareVAddr = 0x%08x)",
                                                  *puiSyncPrimVAddr);
 
@@ -975,7 +956,7 @@ void SyncUnregisterConnection(SYNC_CONNECTION_DATA *psSyncConnectionData)
        _SyncConnectionUnref(psSyncConnectionData);
 }
 
-void SyncConnectionPDumpSyncBlocks(void *hSyncPrivData, PDUMP_TRANSITION_EVENT eEvent)
+void SyncConnectionPDumpSyncBlocks(PVRSRV_DEVICE_NODE *psDevNode, void *hSyncPrivData, PDUMP_TRANSITION_EVENT eEvent)
 {
        if ((eEvent == PDUMP_TRANSITION_EVENT_RANGE_ENTERED) || (eEvent == PDUMP_TRANSITION_EVENT_BLOCK_STARTED))
        {
@@ -984,7 +965,7 @@ void SyncConnectionPDumpSyncBlocks(void *hSyncPrivData, PDUMP_TRANSITION_EVENT e
 
                OSLockAcquire(psSyncConnectionData->hLock);
 
-               PDUMPCOMMENT("Dump client Sync Prim state");
+               PDUMPCOMMENT(psDevNode, "Dump client Sync Prim state");
                dllist_foreach_node(&psSyncConnectionData->sListHead, psNode, psNext)
                {
                        SYNC_PRIMITIVE_BLOCK *psSyncBlock =
@@ -1168,11 +1149,11 @@ static PVRSRV_ERROR SyncRecordListInit(PVRSRV_DEVICE_NODE *psDevNode)
        PVR_GOTO_IF_ERROR(eError, fail_lock_create);
        dllist_init(&psDevNode->sSyncServerRecordList);
 
-       eError = PVRSRVRegisterDbgRequestNotify(&psDevNode->hSyncServerRecordNotify,
-                                                                                       psDevNode,
-                                                                                       _SyncRecordRequest,
-                                                                                       DEBUG_REQUEST_SYNCTRACKING,
-                                                                                       psDevNode);
+       eError = PVRSRVRegisterDeviceDbgRequestNotify(&psDevNode->hSyncServerRecordNotify,
+                                                         psDevNode,
+                                                         _SyncRecordRequest,
+                                                         DEBUG_REQUEST_SYNCTRACKING,
+                                                         psDevNode);
 
        PVR_GOTO_IF_ERROR(eError, fail_dbg_register);
 
@@ -1211,7 +1192,7 @@ static void SyncRecordListDeinit(PVRSRV_DEVICE_NODE *psDevNode)
 
        if (psDevNode->hSyncServerRecordNotify)
        {
-               PVRSRVUnregisterDbgRequestNotify(psDevNode->hSyncServerRecordNotify);
+               PVRSRVUnregisterDeviceDbgRequestNotify(psDevNode->hSyncServerRecordNotify);
        }
        OSLockDestroy(psDevNode->hSyncServerRecordLock);
 }
index cff592d..c250dd3 100644 (file)
@@ -733,7 +733,7 @@ TLServerWriteDataKM(PTL_STREAM_DESC psSD,
        PVR_ASSERT (psNode->psStream);
 
        eError = TLStreamWrite(psNode->psStream, pui8Data, ui32Size);
-       PVR_LOG_IF_ERROR(eError, "TLStreamWrite");
+       /* propagate error up but don't print anything here */
 
        OSLockAcquire(psGD->hTLGDLock);
        TLReturnStreamNode(psNode);
index 2d8e9c9..a80792e 100644 (file)
@@ -56,9 +56,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "tlstream.h"
 
 #include "pvrsrv.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #define EVENT_OBJECT_TIMEOUT_US 1000000ULL
 #define READ_PENDING_TIMEOUT_US 100000ULL
@@ -144,9 +141,6 @@ IMG_UINT32 TLStreamGetUT(IMG_HANDLE hStream)
 
 PVRSRV_ERROR TLAllocSharedMemIfNull(IMG_HANDLE hStream)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PTL_STREAM psStream = (PTL_STREAM) hStream;
        PVRSRV_ERROR eError;
 
@@ -187,15 +181,6 @@ PVRSRV_ERROR TLAllocSharedMemIfNull(IMG_HANDLE hStream)
        eError = DevmemAcquireCpuVirtAddr(psStream->psStreamMemDesc,
                                          (void**) &psStream->pbyBuffer);
        PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", e1);
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psStream->psStreamMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psStream->pbyBuffer - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
 
        return PVRSRV_OK;
 
@@ -1077,7 +1062,7 @@ TLStreamCommit(IMG_HANDLE hStream, IMG_UINT32 ui32ReqSize)
 
        /* Memory barrier required to ensure prior data written by writer is
         * flushed from WC buffer to main memory. */
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(NULL);
 
        /* Acquire stream lock to ensure other context(s) (if any)
         * wait on the lock (in DoTLStreamReserve) for consistent values
@@ -1088,6 +1073,9 @@ TLStreamCommit(IMG_HANDLE hStream, IMG_UINT32 ui32ReqSize)
        psTmp->ui32Write = ui32LWrite;
        psTmp->ui32Pending = ui32LPending;
 
+       /* Ensure write pointer is flushed */
+       OSWriteMemoryBarrier(&psTmp->ui32Write);
+
        TL_COUNTER_ADD(psTmp->ui32ProducerByteCount, ui32ReqSize);
        TL_COUNTER_INC(psTmp->ui32NumCommits);
 
index d9f4d34..427811a 100644 (file)
@@ -80,7 +80,7 @@ PvzClientMapDevPhysHeap(PVRSRV_DEVICE_CONFIG *psDevConfig)
        IMG_DEV_PHYADDR sDevPAddr;
        VMM_PVZ_CONNECTION *psVmmPvz;
        IMG_UINT32 uiFuncID = PVZ_BRIDGE_MAPDEVICEPHYSHEAP;
-       PHYS_HEAP *psFwPhysHeap = psDevConfig->psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_CONFIG];
+       PHYS_HEAP *psFwPhysHeap = psDevConfig->psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_MAIN];
 
        eError = PhysHeapGetDevPAddr(psFwPhysHeap, &sDevPAddr);
 
index 20c700b..488c8b4 100644 (file)
@@ -64,7 +64,6 @@ PVRSRV_ERROR PvzOnVmOnline(IMG_UINT32 ui32OSid)
        PVRSRV_ERROR       eError          = PVRSRV_OK;
        PVRSRV_DATA        *psPVRSRVData   = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_NODE *psDevNode;
-       PVRSRV_RGXDEV_INFO *psDevInfo;
 
        if (ui32OSid == 0 || ui32OSid >= RGX_NUM_OS_SUPPORTED)
        {
@@ -87,7 +86,6 @@ PVRSRV_ERROR PvzOnVmOnline(IMG_UINT32 ui32OSid)
 
        /* For now, limit support to single device setups */
        psDevNode = psPVRSRVData->psDeviceNodeList;
-       psDevInfo = psDevNode->pvDevice;
 
        if (psDevNode->eDevState == PVRSRV_DEVICE_STATE_INIT)
        {
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
-@File           rgxsignals.c
-@Title          RGX Signals routines
+@File
+@Title          PVR device dependent bridge Init/Deinit Module (kernel side)
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    RGX Signals routines
+@Description    Implements device dependent PVR Bridge init/deinit code
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,59 +41,71 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "rgxsignals.h"
-
-#include "rgxmem.h"
-#include "rgx_fwif_km.h"
-#include "mmu_common.h"
-#include "devicemem.h"
-#include "rgxfwutils.h"
-
-
-PVRSRV_ERROR
-PVRSRVRGXNotifySignalUpdateKM(CONNECTION_DATA *psConnection,
-                              PVRSRV_DEVICE_NODE *psDeviceNode,
-                              IMG_HANDLE hMemCtxPrivData,
-                              IMG_DEV_VIRTADDR sDevSignalAddress)
+#include "img_types.h"
+#include "img_defs.h"
+#include "rgx_bridge_init.h"
+#include "rgxdevice.h"
+
+#if defined(RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+PVRSRV_ERROR InitRGXTQ2Bridge(void);
+void DeinitRGXTQ2Bridge(void);
+#endif
+PVRSRV_ERROR InitRGXCMPBridge(void);
+void DeinitRGXCMPBridge(void);
+#if defined(SUPPORT_RGXRAY_BRIDGE)
+PVRSRV_ERROR InitRGXRAYBridge(void);
+void DeinitRGXRAYBridge(void);
+#endif
+
+PVRSRV_ERROR DeviceDepBridgeInit(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-       DEVMEM_MEMDESC *psFWMemContextMemDesc;
-       RGXFWIF_KCCB_CMD sKCCBCmd;
        PVRSRV_ERROR eError;
 
-       PVR_UNREFERENCED_PARAMETER(psConnection);
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE))
+       {
+               eError = InitRGXCMPBridge();
+               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXCMPBridge");
+       }
+
+#if defined(RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, FASTRENDER_DM))
+       {
+               eError = InitRGXTQ2Bridge();
+               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXTQ2Bridge");
+       }
+#endif
 
-       psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+#if defined(SUPPORT_RGXRAY_BRIDGE)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 0)
+       {
+               eError = InitRGXRAYBridge();
+               PVR_LOG_RETURN_IF_ERROR(eError, "InitRGXRAYBridge");
+       }
+#endif
 
-       /* Schedule the firmware command */
-       sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE;
-       sKCCBCmd.uCmdData.sSignalUpdateData.sDevSignalAddress = sDevSignalAddress;
-       eError = RGXSetFirmwareAddress(&sKCCBCmd.uCmdData.sSignalUpdateData.psFWMemContext,
-                             psFWMemContextMemDesc,
-                             0, RFW_FWADDR_NOREF_FLAG);
-       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", fail_fwaddr);
+       return PVRSRV_OK;
+}
 
-       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+void DeviceDepBridgeDeInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE))
        {
-               eError = RGXScheduleCommand((PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice,
-                                           RGXFWIF_DM_GP,
-                                           &sKCCBCmd,
-                                           0,
-                                           PDUMP_FLAGS_NONE);
-               if (eError != PVRSRV_ERROR_RETRY)
-               {
-                       break;
-               }
-               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-       } END_LOOP_UNTIL_TIMEOUT();
-
-       if (eError != PVRSRV_OK)
+               DeinitRGXCMPBridge();
+       }
+
+#if defined(RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, FASTRENDER_DM))
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                        "%s: Failed to schedule the FW command %d (%s)",
-                        __func__,
-                        eError, PVRSRVGETERRORSTRING(eError)));
+               DeinitRGXTQ2Bridge();
        }
+#endif
 
-fail_fwaddr:
-       return eError;
+#if defined(SUPPORT_RGXRAY_BRIDGE)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 0)
+       {
+               DeinitRGXRAYBridge();
+       }
+#endif
 }
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          System Description Header
+@Title          PVR device dependent bridge Init/Deinit Module (kernel side)
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header provides system-specific declarations and macros
+@Description    Implements device dependent PVR Bridge init/deinit code
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,17 +41,15 @@ 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(__SYSINFO_H__)
-#define __SYSINFO_H__
+#if !defined(RGX_BRIDGE_INIT_H)
+#define RGX_BRIDGE_INIT_H
 
+#include "img_types.h"
+#include "img_defs.h"
+#include "device.h"
+#include "rgxdevice.h"
 
+PVRSRV_ERROR DeviceDepBridgeInit(PVRSRV_RGXDEV_INFO *psDevInfo);
+void DeviceDepBridgeDeInit(PVRSRV_RGXDEV_INFO *psDevInfo);
 
-/*!< System specific poll/timeout details */
-#define MAX_HW_TIME_US                           (1000000)
-#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT  (1500)//(10000)
-#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
-#define WAIT_TRY_COUNT                           (20000)
-
-#define SYS_RGX_OF_COMPATIBLE "mediatek,mt8173-gpu"
-
-#endif /* !defined(__SYSINFO_H__) */
+#endif /* RGX_BRIDGE_INIT_H */
index 168d070..bd147dc 100644 (file)
@@ -91,7 +91,6 @@ PVRSRV_ERROR PVRSRVRGXSetBreakpointKM(CONNECTION_DATA    * psConnection,
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                  eFWDataMaster,
                                                  &sBPCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", unlock);
@@ -138,7 +137,6 @@ PVRSRV_ERROR PVRSRVRGXClearBreakpointKM(CONNECTION_DATA    * psConnection,
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                  psDevInfo->eBPDM,
                                                  &sBPCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", unlock);
@@ -188,7 +186,6 @@ PVRSRV_ERROR PVRSRVRGXEnableBreakpointKM(CONNECTION_DATA    * psConnection,
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                  psDevInfo->eBPDM,
                                                  &sBPCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", unlock);
@@ -236,7 +233,6 @@ PVRSRV_ERROR PVRSRVRGXDisableBreakpointKM(CONNECTION_DATA    * psConnection,
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                  psDevInfo->eBPDM,
                                                  &sBPCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", unlock);
@@ -275,7 +271,6 @@ PVRSRV_ERROR PVRSRVRGXOverallocateBPRegistersKM(CONNECTION_DATA    * psConnectio
        eError = RGXScheduleCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
                                                  RGXFWIF_DM_GP,
                                                  &sBPCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", unlock);
index c118bec..6c29bee 100644 (file)
@@ -57,7 +57,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 static IMG_UINT64* _RGXSearchBVNCTable( IMG_UINT64 *pui64Array,
                                                                IMG_UINT uiEnd,
                                                                IMG_UINT64 ui64SearchValue,
-                                                               IMG_UINT uiRowCount)
+                                                               IMG_UINT uiColCount)
 {
        IMG_UINT uiStart = 0, index;
        IMG_UINT64 value, *pui64Ptr = NULL;
@@ -65,7 +65,7 @@ static IMG_UINT64* _RGXSearchBVNCTable( IMG_UINT64 *pui64Array,
        while (uiStart < uiEnd)
        {
                index = (uiStart + uiEnd)/2;
-               pui64Ptr = pui64Array + (index * uiRowCount);
+               pui64Ptr = pui64Array + (index * uiColCount);
                value = *(pui64Ptr);
 
                if (value == ui64SearchValue)
@@ -104,23 +104,29 @@ static void _RGXBvncDumpParsedConfig(PVRSRV_DEVICE_NODE *psDeviceNode)
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "NC:       ", NUM_CLUSTERS);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "CSF:      ", CDM_CONTROL_STREAM_FORMAT);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "FBCDCA:   ", FBCDC_ARCHITECTURE);
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "META:     ", META);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "MCMB:     ", META_COREMEM_BANKS);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "MCMS:     ", META_COREMEM_SIZE);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "MDMACnt:  ", META_DMA_CHANNEL_COUNT);
+#endif
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "NIIP:     ", NUM_ISP_IPP_PIPES);
 #if defined(RGX_FEATURE_NUM_ISP_PER_SPU_MAX_VALUE_IDX)
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "NIPS:     ", NUM_ISP_PER_SPU);
+#endif
+#if defined(RGX_FEATURE_PBE_PER_SPU_MAX_VALUE_IDX)
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "PPS:      ", PBE_PER_SPU);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "NSPU:     ", NUM_SPU);
 #endif
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "PBW:      ", PHYS_BUS_WIDTH);
+#if defined(RGX_FEATURE_SCALABLE_TE_ARCH_MAX_VALUE_IDX)
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "STEArch:  ", SCALABLE_TE_ARCH);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "SVCEA:    ", SCALABLE_VCE);
+#endif
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "SLCBanks: ", SLC_BANKS);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "SLCCLS:   ", SLC_CACHE_LINE_SIZE_BITS);
        PVR_LOG(("SLCSize:   %d",  psDevInfo->sDevFeatureCfg.ui32SLCSizeInBytes));
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "VASB:     ", VIRTUAL_ADDRESS_SPACE_BITS);
-       PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "META:     ", META);
        PVR_LOG_DUMP_FEATURE_VALUE(psDevInfo, "NOSIDS:   ", NUM_OSIDS);
 
 #if defined(FEATURE_NO_VALUES_NAMES_MAX_IDX)
@@ -206,23 +212,32 @@ static void _RGXBvncParseFeatureValues(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT64
 #if defined(RGX_FEATURE_POWER_ISLAND_VERSION_MAX_VALUE_IDX)
        /* Code path for Volcanic */
 
-       psDevInfo->sDevFeatureCfg.ui32MAXDMCount =      RGXFWIF_DM_MIN_CNT;
-       psDevInfo->sDevFeatureCfg.ui32MAXDMMTSCount =   RGXFWIF_DM_MIN_MTS_CNT;
+       psDevInfo->sDevFeatureCfg.ui32MAXDMCount = RGXFWIF_DM_CDM+1;
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 1)
+       {
+               psDevInfo->sDevFeatureCfg.ui32MAXDMCount = MAX(psDevInfo->sDevFeatureCfg.ui32MAXDMCount, RGXFWIF_DM_RAY+1);
+       }
+#if defined(SUPPORT_AGP)
+       psDevInfo->sDevFeatureCfg.ui32MAXDMCount = MAX(psDevInfo->sDevFeatureCfg.ui32MAXDMCount, RGXFWIF_DM_GEOM2+1);
+#if defined(SUPPORT_AGP4)
+       psDevInfo->sDevFeatureCfg.ui32MAXDMCount = MAX(psDevInfo->sDevFeatureCfg.ui32MAXDMCount, RGXFWIF_DM_GEOM4+1);
+#endif
+#endif
 
        /* Get the max number of dusts in the core */
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, NUM_CLUSTERS))
        {
-               RGX_LAYER_PARAMS sParams;
-
-               OSCachedMemSet(&sParams, 0, sizeof(RGX_LAYER_PARAMS));
-               sParams.psDevInfo = psDevInfo;
+               RGX_LAYER_PARAMS sParams = {.psDevInfo = psDevInfo};
 
                if (RGX_DEVICE_GET_FEATURE_VALUE(&sParams, POWER_ISLAND_VERSION) == 1)
                {
+                       /* per SPU power island */
                        psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount = MAX(1, (RGX_GET_FEATURE_VALUE(psDevInfo, NUM_CLUSTERS) / 2));
                }
-               else if (RGX_DEVICE_GET_FEATURE_VALUE(&sParams, POWER_ISLAND_VERSION) == 2)
+               else if (RGX_DEVICE_GET_FEATURE_VALUE(&sParams, POWER_ISLAND_VERSION) >= 2)
                {
+                       /* per Cluster power island */
                        psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount = RGX_GET_FEATURE_VALUE(psDevInfo, NUM_CLUSTERS);
                }
                else
@@ -232,6 +247,19 @@ static void _RGXBvncParseFeatureValues(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT64
                        PVR_DPF((PVR_DBG_ERROR, "%s: Power island feature version not found!", __func__));
                        PVR_ASSERT(0);
                }
+
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+                       RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 1)
+               {
+                       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RT_RAC_PER_SPU))
+                       {
+                               psDevInfo->sDevFeatureCfg.ui32MAXRACCount = RGX_GET_FEATURE_VALUE(psDevInfo, NUM_SPU);
+                       }
+                       else
+                       {
+                               psDevInfo->sDevFeatureCfg.ui32MAXRACCount = 1;
+                       }
+               }
        }
        else
        {
@@ -240,13 +268,21 @@ static void _RGXBvncParseFeatureValues(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT64
                PVR_DPF((PVR_DBG_ERROR, "%s: Number of clusters feature value missing!", __func__));
                PVR_ASSERT(0);
        }
-#else
-       /* Code path for Rogue */
+#else /* defined(RGX_FEATURE_POWER_ISLAND_VERSION_MAX_VALUE_IDX) */
+       /* Code path for Rogue and Oceanic */
 
+       psDevInfo->sDevFeatureCfg.ui32MAXDMCount = RGXFWIF_DM_CDM+1;
+#if defined(SUPPORT_AGP)
+       psDevInfo->sDevFeatureCfg.ui32MAXDMCount = MAX(psDevInfo->sDevFeatureCfg.ui32MAXDMCount, RGXFWIF_DM_GEOM2+1);
+#endif
+
+       /* Meta feature not present in oceanic */
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
                psDevInfo->sDevFeatureCfg.ui32FeaturesValues[RGX_FEATURE_META_IDX] = RGX_FEATURE_VALUE_DISABLED;
        }
+#endif
 
        /* Get the max number of dusts in the core */
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, NUM_CLUSTERS))
@@ -260,13 +296,16 @@ static void _RGXBvncParseFeatureValues(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT64
                PVR_DPF((PVR_DBG_ERROR, "%s: Number of clusters feature value missing!", __func__));
                PVR_ASSERT(0);
        }
-#endif
+#endif /* defined(RGX_FEATURE_POWER_ISLAND_VERSION_MAX_VALUE_IDX) */
 
+       /* Meta feature not present in oceanic */
+#if defined(RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX)
        /* Transform the META coremem size info in bytes */
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META_COREMEM_SIZE))
        {
                psDevInfo->sDevFeatureCfg.ui32FeaturesValues[RGX_FEATURE_META_COREMEM_SIZE_IDX] *= 1024;
        }
+#endif
 }
 
 static void _RGXBvncAcquireAppHint(IMG_CHAR *pszBVNC, const IMG_UINT32 ui32RGXDevCount)
@@ -281,7 +320,8 @@ static void _RGXBvncAcquireAppHint(IMG_CHAR *pszBVNC, const IMG_UINT32 ui32RGXDe
 
        OSCreateKMAppHintState(&pvAppHintState);
 
-       bRet = (IMG_BOOL)OSGetKMAppHintSTRING(pvAppHintState,
+       bRet = (IMG_BOOL)OSGetKMAppHintSTRING(APPHINT_NO_DEVICE,
+                                               pvAppHintState,
                                                RGXBVNC,
                                                pszAppHintDefault,
                                                szBVNCAppHint,
@@ -389,8 +429,8 @@ static IMG_UINT32 _RGXBvncReadSLCSize(PVRSRV_DEVICE_NODE *psDeviceNode)
        PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
        IMG_UINT64 ui64SLCSize = 0ULL;
 
-#if defined(RGX_CR_CORE_ID__PBVNC)
-       /* Rogue hardware */
+#if defined(RGX_CR_SLC_SIZE_IN_KB)
+       /* Rogue and Oceanic hardware */
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, SLC_SIZE_CONFIGURABLE))
        {
                ui64SLCSize = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SLC_SIZE_IN_KB);
@@ -461,7 +501,8 @@ PVRSRV_ERROR RGXBvncInitialiseConfiguration(PVRSRV_DEVICE_NODE *psDeviceNode)
                const IMG_BOOL bAppHintDefault = PVRSRV_APPHINT_IGNOREHWREPORTEDBVNC;
 
                OSCreateKMAppHintState(&pvAppHintState);
-               OSGetKMAppHintBOOL(pvAppHintState,
+               OSGetKMAppHintBOOL(APPHINT_NO_DEVICE,
+                                                       pvAppHintState,
                                                        IgnoreHWReportedBVNC,
                                                        &bAppHintDefault,
                                                        &psDevInfo->bIgnoreHWReportedBVNC);
@@ -737,7 +778,7 @@ PVRSRV_ERROR RGXVerifyBVNC(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64Give
        /* The device info */
        psDevInfo = psDeviceNode->pvDevice;
 
-       PDUMPCOMMENT("PDUMP VERIFY CORE_ID registers for all OSIDs\n");
+       PDUMPCOMMENT(psDeviceNode, "PDUMP VERIFY CORE_ID registers for all OSIDs\n");
 
        /* construct the value to match against */
        if ((ui64GivenBVNC | ui64CoreIdMask) == 0) /* both zero means use configured DDK value */
@@ -788,7 +829,7 @@ PVRSRV_ERROR RGXVerifyBVNC(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64Give
 
 #if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) && defined(PDUMP)
                /* check upper DWORD */
-               eError = PDUMPREGPOL(RGX_PDUMPREG_NAME,
+               eError = PDUMPREGPOL(psDeviceNode, RGX_PDUMPREG_NAME,
                                     (RGX_CR_CORE_ID + 4) + (i << 16),
                                     (IMG_UINT32)(ui64MatchBVNC >> 32),
                                     0xFFFFFFFF,
@@ -797,7 +838,7 @@ PVRSRV_ERROR RGXVerifyBVNC(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64Give
                if (eError == PVRSRV_OK)
                {
                        /* check lower DWORD */
-                       eError = PDUMPREGPOL(RGX_PDUMPREG_NAME,
+                       eError = PDUMPREGPOL(psDeviceNode, RGX_PDUMPREG_NAME,
                                             RGX_CR_CORE_ID + (i << 16),
                                             (IMG_UINT32)(ui64MatchBVNC & 0xFFFFFFFF),
                                             0xFFFFFFFF,
index 1f32ad4..7a76f80 100644 (file)
@@ -60,9 +60,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxutils.h"
 #include "info_page.h"
 #include "rgxtimerquery.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #if defined(PVRSRV_FORCE_FLUSH_CCCB_ON_KICK)
 #include "cache_km.h"
@@ -174,6 +171,9 @@ PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
 {
 
        IMG_UINT32 ui32PollOffset;
+#if defined(PDUMP)
+       PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psClientCCB->psServerCommonContext);
+#endif
 
        if (BIT_ISSET(psClientCCB->ui32CCBFlags, CCB_FLAGS_CCB_STATE_OPEN))
        {
@@ -184,7 +184,8 @@ PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
                 */
                ui32PollOffset = psClientCCB->ui32FinishedPDumpWriteOffset;
 
-               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                                                         ui32PDumpFlags,
                                                          "cCCB(%s@%p): Draining open CCB rgxfw_roff < woff (%d)",
                                                          psClientCCB->szName,
                                                          psClientCCB,
@@ -197,7 +198,8 @@ PVRSRV_ERROR RGXCCBPDumpDrainCCB(RGX_CLIENT_CCB *psClientCCB,
                 */
                ui32PollOffset = psClientCCB->ui32LastPDumpWriteOffset;
 
-               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                                                         ui32PDumpFlags,
                                                          "cCCB(%s@%p): Draining CCB rgxfw_roff == woff (%d)",
                                                          psClientCCB->szName,
                                                          psClientCCB,
@@ -283,6 +285,9 @@ static PVRSRV_ERROR RGXCCBPDumpSyncCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 u
 static void RGXCCBPDumpFastForwardCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui32PDumpFlags)
 {
        volatile RGXFWIF_CCCB_CTL *psCCBCtl = psClientCCB->psClientCCBCtrl;
+#if defined(PDUMP)
+       PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psClientCCB->psServerCommonContext);
+#endif
 
        /* Make sure that we have synced live-FW and live-App threads */
        PVR_ASSERT(psCCBCtl->ui32ReadOffset == psClientCCB->ui32HostWriteOffset);
@@ -290,8 +295,16 @@ static void RGXCCBPDumpFastForwardCCB(RGX_CLIENT_CCB *psClientCCB, IMG_UINT32 ui
        psCCBCtl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset;
        psCCBCtl->ui32DepOffset = psClientCCB->ui32HostWriteOffset;
        psCCBCtl->ui32WriteOffset = psClientCCB->ui32HostWriteOffset;
+#if defined(SUPPORT_AGP)
+       psCCBCtl->ui32ReadOffset2 = psClientCCB->ui32HostWriteOffset;
+#if defined(SUPPORT_AGP4)
+       psCCBCtl->ui32ReadOffset3 = psClientCCB->ui32HostWriteOffset;
+       psCCBCtl->ui32ReadOffset4 = psClientCCB->ui32HostWriteOffset;
+#endif
+#endif
 
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                       ui32PDumpFlags,
                        "cCCB(%s@%p): Fast-forward from %d to %d",
                        psClientCCB->szName,
                        psClientCCB,
@@ -538,9 +551,6 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
                                                  DEVMEM_MEMDESC                **ppsClientCCBMemDesc,
                                                  DEVMEM_MEMDESC                **ppsClientCCBCtrlMemDesc)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_ERROR    eError = PVRSRV_OK;
        PVRSRV_MEMALLOCFLAGS_T  uiClientCCBMemAllocFlags, uiClientCCBCtlMemAllocFlags;
        IMG_UINT32              ui32FWMainLog2PageSize = DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareMainHeap);
@@ -613,7 +623,8 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
                                                                PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
                                                                PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                                                                PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                                                               PVRSRV_MEMALLOCFLAG_UNCACHED |
+                                                               PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED |
                                                                PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                                                                PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
                                                                PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN);
@@ -628,7 +639,7 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
                BIT_SET(psClientCCB->ui32CCBFlags, CCB_FLAGS_SLR_DISABLED);
        }
 
-       PDUMPCOMMENT("Allocate RGXFW cCCB");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate RGXFW cCCB");
 #if defined(PVRSRV_ENABLE_CCCB_GROW)
        if (BITMASK_HAS(psDevInfo->ui32DeviceFlags, RGXKM_DEVICE_STATE_CCB_GROW_EN))
        {
@@ -747,7 +758,7 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
                goto fail_map_ccb;
        }
 
-       PDUMPCOMMENT("Allocate RGXFW cCCB control");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate RGXFW cCCB control");
        eError = DevmemFwAllocate(psDevInfo,
                                                                                sizeof(RGXFWIF_CCCB_CTL),
                                                                                uiClientCCBCtlMemAllocFlags,
@@ -775,12 +786,10 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO      *psDevInfo,
                goto fail_map_ccbctrl;
        }
 
-       psClientCCB->psClientCCBCtrl->ui32WriteOffset = 0;
-       psClientCCB->psClientCCBCtrl->ui32ReadOffset = 0;
-       psClientCCB->psClientCCBCtrl->ui32DepOffset = 0;
+       /* psClientCCBCtrlMemDesc was zero alloc'd so no need to initialise offsets. */
        psClientCCB->psClientCCBCtrl->ui32WrapMask = ui32AllocSize - 1;
 
-       PDUMPCOMMENT("cCCB control");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "cCCB control");
        DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc,
                                           0,
                                           sizeof(RGXFWIF_CCCB_CTL),
@@ -831,7 +840,8 @@ PVRSRV_ERROR RGXCreateCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
         * the connection data, to ensure it's not freed too early
         */
        psClientCCB->psPDumpConnectionData = psConnectionData->psPDumpConnectionData;
-       PDUMPCOMMENT("New RGXFW cCCB(%s@%p) created",
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "New RGXFW cCCB(%s@%p) created",
                                 psClientCCB->szName,
                                 psClientCCB);
 
@@ -845,28 +855,10 @@ fail_pdumpreg:
        OSLockDestroy(psClientCCB->hCCBGrowLock);
 fail_create_ccbgrow_lock:
 #endif
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psClientCCB->psClientCCBCtrlMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psClientCCB->psClientCCBCtrl - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBCtrlMemDesc);
 fail_map_ccbctrl:
        DevmemFwUnmapAndFree(psDevInfo, psClientCCB->psClientCCBCtrlMemDesc);
 fail_alloc_ccbctrl:
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psClientCCB->psClientCCBMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psClientCCB->pvClientCCB - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psClientCCB->psClientCCBMemDesc);
 fail_map_ccb:
        DevmemFwUnmapAndFree(psDevInfo, psClientCCB->psClientCCBMemDesc);
@@ -1056,25 +1048,28 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
 
 #if defined(PDUMP)
        PVRSRV_ERROR eError;
-       IMG_BOOL        bInCaptureRange;
-       IMG_BOOL        bPdumpEnabled;
-       IMG_UINT64      ui64PDumpState = 0;
-
-       PDumpGetStateKM(&ui64PDumpState);
-       PDumpIsCaptureFrameKM(&bInCaptureRange);
-       bPdumpEnabled = (ui64PDumpState & PDUMP_STATE_CONNECTED) != 0
-               && (bInCaptureRange || PDUMP_IS_CONTINUOUS(ui32PDumpFlags));
+       PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psClientCCB->psServerCommonContext);
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       IMG_BOOL        bPDumpEnabled = PDumpCheckFlagsWrite(psDeviceNode, ui32PDumpFlags);
+       IMG_BOOL        bPDumpFlagsContinuous = PDUMP_IS_CONTINUOUS(ui32PDumpFlags);
 
        /*
                PDumpSetFrame will detect as we Transition into capture range for
                frame based data but if we are PDumping continuous data then we
                need to inform the PDump layer ourselves
+
+               First check is to confirm we are in continuous mode
+               Second check is to confirm the pdump client is connected and ready.
+               Third check is to confirm we are not in capture range.
        */
-       if ((ui64PDumpState & PDUMP_STATE_CONNECTED) != 0
-               && PDUMP_IS_CONTINUOUS(ui32PDumpFlags)
-               && !bInCaptureRange)
-       {
-               eError = PDumpTransition(psClientCCB->psPDumpConnectionData, PDUMP_TRANSITION_EVENT_RANGE_ENTERED, ui32PDumpFlags);
+       if (bPDumpFlagsContinuous &&
+               bPDumpEnabled &&
+               !PDumpCheckFlagsWrite(psDeviceNode, PDUMP_FLAGS_NONE))
+       {
+               eError = PDumpTransition(psDeviceNode,
+                                        psClientCCB->psPDumpConnectionData,
+                                        PDUMP_TRANSITION_EVENT_RANGE_ENTERED,
+                                        ui32PDumpFlags);
                if (eError != PVRSRV_OK)
                {
                        return eError;
@@ -1111,9 +1106,10 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
 
 #if defined(PDUMP)
                        /* Wait for sufficient CCB space to become available */
-                       PDUMPCOMMENTWITHFLAGS(0, "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
-                                                                       ui32CmdSize, psClientCCB->ui32HostWriteOffset,
-                                                                       psClientCCB->szName);
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                                 "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
+                                                                 ui32CmdSize, psClientCCB->ui32HostWriteOffset,
+                                                                 psClientCCB->szName);
                        DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
                                                offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
                                                psClientCCB->ui32HostWriteOffset,
@@ -1171,8 +1167,9 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
                                        psHeader->ui32CmdSize = ui32Remain - sizeof(RGXFWIF_CCB_CMD_HEADER);
 
 #if defined(PDUMP)
-                                       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize);
-                                       if (bPdumpEnabled)
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, ui32PDumpFlags,
+                                                                                 "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize);
+                                       if (bPDumpEnabled)
                                        {
                                                DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc,
                                                                                psClientCCB->ui32HostWriteOffset,
@@ -1222,8 +1219,8 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
                                        }
 
 #if defined(PDUMP)
-                                       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB update for grow");
-                                       if (bPdumpEnabled)
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, ui32PDumpFlags, "cCCB update for grow");
+                                       if (bPDumpEnabled)
                                        {
                                                DevmemPDumpLoadMem(psClientCCB->psClientCCBCtrlMemDesc,
                                                                                        offsetof(RGXFWIF_CCCB_CTL, ui32WrapMask),
@@ -1250,17 +1247,19 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
                                        /* CCB can't grow anymore and can't be wrapped */
 #if defined(PDUMP)
                                        /* Wait for sufficient CCB space to become available */
-                                       PDUMPCOMMENTWITHFLAGS(0, "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
-                                                                                       ui32Remain, psClientCCB->ui32HostWriteOffset,
-                                                                                       psClientCCB->szName);
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                                                 "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
+                                                                                 ui32Remain, psClientCCB->ui32HostWriteOffset,
+                                                                                 psClientCCB->szName);
                                        DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
                                                                offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
                                                                psClientCCB->ui32HostWriteOffset,
                                                                ui32Remain,
                                                                psClientCCB->ui32Size);
-                                       PDUMPCOMMENTWITHFLAGS(0, "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
-                                                                                       ui32CmdSize, 0 /*ui32HostWriteOffset after wrap */,
-                                                                                       psClientCCB->szName);
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                                                 "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
+                                                                                 ui32CmdSize, 0 /*ui32HostWriteOffset after wrap */,
+                                                                                 psClientCCB->szName);
                                        DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
                                                                offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
                                                                0 /*ui32HostWriteOffset after wrap */,
@@ -1277,17 +1276,19 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
                        {
 #if defined(PDUMP)
                                /* Wait for sufficient CCB space to become available */
-                               PDUMPCOMMENTWITHFLAGS(0, "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
-                                                                               ui32Remain, psClientCCB->ui32HostWriteOffset,
-                                                                               psClientCCB->szName);
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                                         "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
+                                                                         ui32Remain, psClientCCB->ui32HostWriteOffset,
+                                                                         psClientCCB->szName);
                                DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
                                                        offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
                                                        psClientCCB->ui32HostWriteOffset,
                                                        ui32Remain,
                                                        psClientCCB->ui32Size);
-                               PDUMPCOMMENTWITHFLAGS(0, "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
-                                                                               ui32CmdSize, 0 /*ui32HostWriteOffset after wrap */,
-                                                                               psClientCCB->szName);
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, 0,
+                                                                         "Wait for %u bytes to become available according cCCB Ctl (woff=%x) for %s",
+                                                                         ui32CmdSize, 0 /*ui32HostWriteOffset after wrap */,
+                                                                         psClientCCB->szName);
                                DevmemPDumpCBP(psClientCCB->psClientCCBCtrlMemDesc,
                                                        offsetof(RGXFWIF_CCCB_CTL, ui32ReadOffset),
                                                        0 /*ui32HostWriteOffset after wrap */,
@@ -1304,8 +1305,8 @@ PVRSRV_ERROR RGXAcquireCCB(RGX_CLIENT_CCB *psClientCCB,
                                        psHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_PADDING;
                                        psHeader->ui32CmdSize = ui32Remain - sizeof(RGXFWIF_CCB_CMD_HEADER);
 #if defined(PDUMP)
-                                       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize);
-                                       if (bPdumpEnabled)
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, ui32PDumpFlags, "cCCB(%p): Padding cmd %d", psClientCCB, psHeader->ui32CmdSize);
+                                       if (bPDumpEnabled)
                                        {
                                                DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc,
                                                                                psClientCCB->ui32HostWriteOffset,
@@ -1346,21 +1347,19 @@ void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
                                                                IMG_UINT32              ui32CmdSize,
                                                                IMG_UINT32              ui32PDumpFlags)
 {
-       IMG_BOOL        bInCaptureRange;
-       IMG_BOOL        bPdumpEnabled;
-       IMG_UINT64      ui64PDumpState = 0;
-
-       PDumpGetStateKM(&ui64PDumpState);
-       PDumpIsCaptureFrameKM(&bInCaptureRange);
-       bPdumpEnabled = (ui64PDumpState & PDUMP_STATE_CONNECTED) != 0
-               && (bInCaptureRange || PDUMP_IS_CONTINUOUS(ui32PDumpFlags));
+#if defined(PDUMP)
+       PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psClientCCB->psServerCommonContext);
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       IMG_BOOL        bPDumpEnabled = PDumpCheckFlagsWrite(psDeviceNode, ui32PDumpFlags);
+       IMG_BOOL        bPDumpFlagsContinuous = PDUMP_IS_CONTINUOUS(ui32PDumpFlags);
+#endif
 
 #if defined(PVRSRV_ENABLE_CCCB_GROW)
        OSLockAcquire(psClientCCB->hCCBGrowLock);
 #endif
        /*
         * If a padding command was needed then we should now move ui32HostWriteOffset
-        * forward. The command has already be dumped (if bPdumpEnabled).
+        * forward. The command has already be dumped (if bPDumpEnabled).
         */
        if ((psClientCCB->ui32HostWriteOffset + ui32CmdSize + PADDING_COMMAND_SIZE) > psClientCCB->ui32Size)
        {
@@ -1372,14 +1371,16 @@ void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
                psClientCCB->ui32ByteCount += ui32Remain;
        }
 
+#if defined(PDUMP)
        /* Dump the CCB data */
-       if (bPdumpEnabled)
+       if (bPDumpEnabled)
        {
                DevmemPDumpLoadMem(psClientCCB->psClientCCBMemDesc,
                                                   psClientCCB->ui32HostWriteOffset,
                                                   ui32CmdSize,
                                                   ui32PDumpFlags);
        }
+#endif
 
        /*
         * Check if there any fences being written that will already be
@@ -1513,19 +1514,27 @@ void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
                PDumpSetFrame will detect as we Transition out of capture range for
                frame based data but if we are PDumping continuous data then we
                need to inform the PDump layer ourselves
+
+               First check is to confirm we are in continuous mode
+               Second check is to confirm the pdump client is connected and ready.
+               Third check is to confirm we are not in capture range.
        */
-       if ((ui64PDumpState & PDUMP_STATE_CONNECTED) != 0
-               && PDUMP_IS_CONTINUOUS(ui32PDumpFlags)
-               && !bInCaptureRange)
+#if defined(PDUMP)
+       if (bPDumpFlagsContinuous &&
+               bPDumpEnabled &&
+               !PDumpCheckFlagsWrite(psDeviceNode, PDUMP_FLAGS_NONE))
        {
                PVRSRV_ERROR eError;
 
                /* Only Transitioning into capture range can cause an error */
-               eError = PDumpTransition(psClientCCB->psPDumpConnectionData, PDUMP_TRANSITION_EVENT_RANGE_EXITED, ui32PDumpFlags);
+               eError = PDumpTransition(psDeviceNode,
+                                        psClientCCB->psPDumpConnectionData,
+                                        PDUMP_TRANSITION_EVENT_RANGE_EXITED,
+                                        ui32PDumpFlags);
                PVR_ASSERT(eError == PVRSRV_OK);
        }
 
-       if (bPdumpEnabled)
+       if (bPDumpEnabled)
        {
                if (!BIT_ISSET(psClientCCB->ui32CCBFlags, CCB_FLAGS_CCB_STATE_OPEN))
                {
@@ -1538,6 +1547,7 @@ void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
                /* Update the PDump write offset to show we PDumped this command */
                psClientCCB->ui32LastPDumpWriteOffset = psClientCCB->ui32HostWriteOffset;
        }
+#endif
 
 #if defined(NO_HARDWARE)
        /*
@@ -1545,6 +1555,9 @@ void RGXReleaseCCB(RGX_CLIENT_CCB *psClientCCB,
        */
        psClientCCB->psClientCCBCtrl->ui32ReadOffset = psClientCCB->ui32HostWriteOffset;
        psClientCCB->psClientCCBCtrl->ui32DepOffset = psClientCCB->ui32HostWriteOffset;
+#if defined(SUPPORT_AGP)
+       psClientCCB->psClientCCBCtrl->ui32ReadOffset2 = psClientCCB->ui32HostWriteOffset;
+#endif
 #endif
 
 #if defined(PVRSRV_ENABLE_CCCB_GROW)
@@ -1576,7 +1589,8 @@ PVRSRV_ERROR RGXSetCCBFlags(RGX_CLIENT_CCB *psClientCCB,
        return PVRSRV_OK;
 }
 
-void RGXCmdHelperInitCmdCCB_CommandSize(IMG_UINT64 ui64FBSCEntryMask,
+void RGXCmdHelperInitCmdCCB_CommandSize(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                        IMG_UINT64 ui64FBSCEntryMask,
                                         IMG_UINT32 ui32ClientFenceCount,
                                         IMG_UINT32 ui32ClientUpdateCount,
                                         IMG_UINT32 ui32CmdSize,
@@ -1585,6 +1599,8 @@ void RGXCmdHelperInitCmdCCB_CommandSize(IMG_UINT64 ui64FBSCEntryMask,
                                         PRGXFWIF_UFO_ADDR         *ppRMWUFOAddr,
                                         RGX_CCB_CMD_HELPER_DATA *psCmdHelperData)
 {
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       IMG_BOOL bCacheInval = IMG_TRUE;
        /* Init the generated data members */
        psCmdHelperData->ui32FBSCInvalCmdSize = 0;
        psCmdHelperData->ui64FBSCEntryMask = 0;
@@ -1594,14 +1610,32 @@ void RGXCmdHelperInitCmdCCB_CommandSize(IMG_UINT64 ui64FBSCEntryMask,
        psCmdHelperData->ui32PostTimeStampCmdSize = 0;
        psCmdHelperData->ui32RMWUFOCmdSize = 0;
 
-       /* Total FBSC invalidate command size (header plus command data) */
+       /* Only compile if RGX_FEATURE_PDS_INSTRUCTION_CACHE_AUTO_INVALIDATE is defined to avoid
+        * compilation errors on rogue cores.
+        */
+#if defined(RGX_FEATURE_PDS_INSTRUCTION_CACHE_AUTO_INVALIDATE)
+       bCacheInval = !(PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, PDS_INSTRUCTION_CACHE_AUTO_INVALIDATE) &&
+                                   PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, USC_INSTRUCTION_CACHE_AUTO_INVALIDATE) &&
+                                   PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, TDM_SLC_MMU_AUTO_CACHE_OPS) &&
+                                   PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, GEOM_SLC_MMU_AUTO_CACHE_OPS) &&
+                                   PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, FRAG_SLC_MMU_AUTO_CACHE_OPS) &&
+                                   PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, COMPUTE_SLC_MMU_AUTO_CACHE_OPS)) ||
+                                   RGX_IS_BRN_SUPPORTED(psDevInfo, 71960) ||
+                                   RGX_IS_BRN_SUPPORTED(psDevInfo, 72143);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+#endif
 
-       if (ui64FBSCEntryMask != 0)
+       /* Total FBSC invalidate command size (header plus command data) */
+       if (bCacheInval)
        {
-               psCmdHelperData->ui32FBSCInvalCmdSize =
-                       RGX_CCB_FWALLOC_ALIGN(sizeof(psCmdHelperData->ui64FBSCEntryMask) +
-                                             sizeof(RGXFWIF_CCB_CMD_HEADER));
-               psCmdHelperData->ui64FBSCEntryMask = ui64FBSCEntryMask;
+               if (ui64FBSCEntryMask != 0)
+               {
+                       psCmdHelperData->ui32FBSCInvalCmdSize =
+                               RGX_CCB_FWALLOC_ALIGN(sizeof(psCmdHelperData->ui64FBSCEntryMask) +
+                                                     sizeof(RGXFWIF_CCB_CMD_HEADER));
+                       psCmdHelperData->ui64FBSCEntryMask = ui64FBSCEntryMask;
+               }
        }
 
        /* total DM command size (header plus command data) */
@@ -1665,6 +1699,8 @@ void RGXCmdHelperInitCmdCCB_OtherData(RGX_CLIENT_CCB            *psClientCCB,
                                       IMG_BOOL                  bCCBStateOpen,
                                       RGX_CCB_CMD_HELPER_DATA   *psCmdHelperData)
 {
+       PVRSRV_RGXDEV_INFO *psDevInfo = NULL;
+
        /* Job reference values */
        psCmdHelperData->ui32ExtJobRef = ui32ExtJobRef;
        psCmdHelperData->ui32IntJobRef = ui32IntJobRef;
@@ -1673,6 +1709,9 @@ void RGXCmdHelperInitCmdCCB_OtherData(RGX_CLIENT_CCB            *psClientCCB,
        psCmdHelperData->psClientCCB = psClientCCB;
 #if defined(PDUMP)
        psCmdHelperData->ui32PDumpFlags = ui32PDumpFlags;
+       psDevInfo = FWCommonContextGetRGXDevInfo(psCmdHelperData->psClientCCB->psServerCommonContext);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
 #endif
        psCmdHelperData->pszCommandName = pszCommandName;
        if (bCCBStateOpen)
@@ -1712,7 +1751,7 @@ void RGXCmdHelperInitCmdCCB_OtherData(RGX_CLIENT_CCB            *psClientCCB,
                psCmdHelperData->pRMWUFOAddr = *ppRMWUFOAddr;
        }
 
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
                        "%s Command Server Init on FWCtx %08x", pszCommandName,
                        FWCommonContextGetFWAddress(psClientCCB->psServerCommonContext).ui32Addr);
 
@@ -1725,7 +1764,8 @@ void RGXCmdHelperInitCmdCCB_OtherData(RGX_CLIENT_CCB            *psClientCCB,
 /*
        Work out how much space this command will require
 */
-void RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB            *psClientCCB,
+void RGXCmdHelperInitCmdCCB(PVRSRV_RGXDEV_INFO         *psDevInfo,
+                            RGX_CLIENT_CCB            *psClientCCB,
                             IMG_UINT64                ui64FBSCEntryMask,
                             IMG_UINT32                ui32ClientFenceCount,
                             PRGXFWIF_UFO_ADDR         *pauiFenceUFOAddress,
@@ -1747,7 +1787,8 @@ void RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB            *psClientCCB,
                             IMG_BOOL                  bCCBStateOpen,
                             RGX_CCB_CMD_HELPER_DATA   *psCmdHelperData)
 {
-       RGXCmdHelperInitCmdCCB_CommandSize(ui64FBSCEntryMask,
+       RGXCmdHelperInitCmdCCB_CommandSize(psDevInfo,
+                                        ui64FBSCEntryMask,
                                         ui32ClientFenceCount,
                                         ui32ClientUpdateCount,
                                         ui32CmdSize,
@@ -1790,6 +1831,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
        IMG_UINT32 i;
        void *pvStartPtr;
        PVRSRV_ERROR eError;
+#if defined(PDUMP)
+       PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(asCmdHelperData->psClientCCB->psServerCommonContext);
+#endif
 
        /*
                Check the number of fences & updates are valid.
@@ -1852,8 +1896,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
 
                if (psCmdHelperData->ui32ClientFenceCount+psCmdHelperData->ui32ClientUpdateCount != 0)
                {
-                       PDUMPCOMMENT("Start of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
-                                       psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                "Start of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
+                                                psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
                }
 
                pvCmdPtr = pvStartPtr;
@@ -1873,9 +1918,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                        psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
                        psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-                       psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+                       psHeader->sWorkEstKickData.ui16ReturnDataIndex = 0;
                        psHeader->sWorkEstKickData.ui64Deadline = 0;
-                       psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+                       psHeader->sWorkEstKickData.ui32CyclesPrediction = 0;
 #endif
 
                        pvCmdPtr = IMG_OFFSET_ADDR(pvCmdPtr, sizeof(RGXFWIF_CCB_CMD_HEADER));
@@ -1905,8 +1950,10 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                                PVR_DPF((PVR_DBG_ERROR, "%s client sync fence - 0x%x -> 0x%x",
                                                psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value));
 #endif
-                               PDUMPCOMMENT(".. %s client sync fence - 0x%x -> 0x%x",
-                                               psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value);
+                               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                        ".. %s client sync fence - 0x%x -> 0x%x",
+                                                        psCmdHelperData->psClientCCB->szName,
+                                                        psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value);
 
 
                        }
@@ -1929,9 +1976,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                        psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
                        psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-                       psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+                       psHeader->sWorkEstKickData.ui16ReturnDataIndex = 0;
                        psHeader->sWorkEstKickData.ui64Deadline = 0;
-                       psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+                       psHeader->sWorkEstKickData.ui32CyclesPrediction = 0;
 #endif
                        pui64FBSCInvalCmdData = IMG_OFFSET_ADDR(psHeader, sizeof(RGXFWIF_CCB_CMD_HEADER));
                        *pui64FBSCInvalCmdData = psCmdHelperData->ui64FBSCEntryMask;
@@ -1978,9 +2025,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                        }
                        else
                        {
-                               psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+                               psHeader->sWorkEstKickData.ui16ReturnDataIndex = 0;
                                psHeader->sWorkEstKickData.ui64Deadline = 0;
-                               psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+                               psHeader->sWorkEstKickData.ui32CyclesPrediction = 0;
                        }
 #endif
 
@@ -2011,9 +2058,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                        psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
                        psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-                       psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+                       psHeader->sWorkEstKickData.ui16ReturnDataIndex = 0;
                        psHeader->sWorkEstKickData.ui64Deadline = 0;
-                       psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+                       psHeader->sWorkEstKickData.ui32CyclesPrediction = 0;
 #endif
                        pvCmdPtr = IMG_OFFSET_ADDR(pvCmdPtr, sizeof(RGXFWIF_CCB_CMD_HEADER));
 
@@ -2037,9 +2084,9 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                        psHeader->ui32ExtJobRef = psCmdHelperData->ui32ExtJobRef;
                        psHeader->ui32IntJobRef = psCmdHelperData->ui32IntJobRef;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-                       psHeader->sWorkEstKickData.ui64ReturnDataIndex = 0;
+                       psHeader->sWorkEstKickData.ui16ReturnDataIndex = 0;
                        psHeader->sWorkEstKickData.ui64Deadline = 0;
-                       psHeader->sWorkEstKickData.ui64CyclesPrediction = 0;
+                       psHeader->sWorkEstKickData.ui32CyclesPrediction = 0;
 #endif
                        pvCmdPtr = IMG_OFFSET_ADDR(pvCmdPtr, sizeof(RGXFWIF_CCB_CMD_HEADER));
 
@@ -2067,8 +2114,10 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
                                PVR_DPF((PVR_DBG_ERROR, "%s client sync update - 0x%x -> 0x%x",
                                                psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value));
 #endif
-                               PDUMPCOMMENT(".. %s client sync update - 0x%x -> 0x%x",
-                                               psCmdHelperData->psClientCCB->szName, psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value);
+                               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                        ".. %s client sync update - 0x%x -> 0x%x",
+                                                        psCmdHelperData->psClientCCB->szName,
+                                                        psUFOPtr->puiAddrUFO.ui32Addr, psUFOPtr->ui32Value);
 
                        }
                }
@@ -2085,13 +2134,15 @@ PVRSRV_ERROR RGXCmdHelperAcquireCmdCCB(IMG_UINT32 ui32CmdCount,
 
                if (psCmdHelperData->ui32ClientFenceCount+psCmdHelperData->ui32ClientUpdateCount != 0)
                {
-                       PDUMPCOMMENT("End of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
-                                       psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                "End of %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
+                                                psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
                }
                else
                {
-                       PDUMPCOMMENT("No %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
-                                       psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                "No %s client syncs for cmd[%d] on FWCtx %08x Woff 0x%x bytes",
+                                                psCmdHelperData->psClientCCB->szName, i, ui32CtxAddr, ui32CcbWoff);
                }
        }
 
@@ -2123,6 +2174,9 @@ void RGXCmdHelperReleaseCmdCCB(IMG_UINT32 ui32CmdCount,
        for (i=0;i<ui32CmdCount;i++)
        {
                RGX_CCB_CMD_HELPER_DATA *psCmdHelperData = &asCmdHelperData[i];
+#if defined(PDUMP)
+               PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psCmdHelperData->psClientCCB->psServerCommonContext);
+#endif
 
 #if (!defined(__linux__) || !defined(SUPPORT_RGX)) && !defined(PDUMP)
                PVR_UNREFERENCED_PARAMETER(psCmdHelperData);
@@ -2155,7 +2209,8 @@ void RGXCmdHelperReleaseCmdCCB(IMG_UINT32 ui32CmdCount,
                        All the commands have been filled in so release the CCB space.
                        The FW still won't run this command until we kick it
                */
-               PDUMPCOMMENTWITHFLAGS(psCmdHelperData->ui32PDumpFlags,
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                               psCmdHelperData->ui32PDumpFlags,
                                "%s Command Server Release on FWCtx %08x",
                                psCmdHelperData->pszCommandName, ui32CtxAddr);
        }
@@ -2407,7 +2462,7 @@ void DumpCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
        psClientCCBCtrl = psCurrentClientCCB->psClientCCBCtrl;
        pvClientCCBBuff = psCurrentClientCCB->pvClientCCB;
        ui32EndOffset = psCurrentClientCCB->ui32HostWriteOffset;
-       OSMemoryBarrier();
+       OSMemoryBarrier(NULL);
        ui32Offset = psClientCCBCtrl->ui32ReadOffset;
        ui32DepOffset = psClientCCBCtrl->ui32DepOffset;
        /* NB. Use psCurrentClientCCB->ui32Size as basis for wrap mask (rather
@@ -2551,7 +2606,7 @@ void DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
                /* CCB is stalled on a fence... */
                if ((eCommandType == RGXFWIF_CCB_CMD_TYPE_FENCE) || (eCommandType == RGXFWIF_CCB_CMD_TYPE_FENCE_PR))
                {
-#if defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
                        PVRSRV_RGXDEV_INFO *psDevInfo = FWCommonContextGetRGXDevInfo(psCurrentClientCCB->psServerCommonContext);
                        IMG_UINT32 ui32Val;
 #endif
@@ -2566,11 +2621,11 @@ void DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
                                                           _CCBCmdTypename(eCommandType));
                        for (jj=0; jj<psCommandHeader->ui32CmdSize/sizeof(RGXFWIF_UFO); jj++)
                        {
-#if !defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if !defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
                                PVR_DUMPDEBUG_LOG("  Addr:0x%08x  Value=0x%08x",psUFOPtr[jj].puiAddrUFO.ui32Addr, psUFOPtr[jj].ui32Value);
 #else
                                ui32Val = 0;
-                               RGXReadWithSP(psDevInfo, psUFOPtr[jj].puiAddrUFO.ui32Addr, &ui32Val);
+                               RGXReadFWModuleAddr(psDevInfo, psUFOPtr[jj].puiAddrUFO.ui32Addr, &ui32Val);
                                PVR_DUMPDEBUG_LOG("  Addr:0x%08x Value(Host)=0x%08x Value(FW)=0x%08x",
                                                   psUFOPtr[jj].puiAddrUFO.ui32Addr,
                                                   psUFOPtr[jj].ui32Value, ui32Val);
@@ -2597,11 +2652,11 @@ void DumpStalledCCBCommand(PRGXFWIF_FWCOMMONCONTEXT sFWCommonContext,
                                                PVR_DUMPDEBUG_LOG(" preventing %s:",_CCBCmdTypename(eCommandType));
                                                for (jj=0; jj<psCommandHeader->ui32CmdSize/sizeof(RGXFWIF_UFO); jj++)
                                                {
-#if !defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if !defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
                                                        PVR_DUMPDEBUG_LOG("  Addr:0x%08x  Value=0x%08x",psUFOPtr[jj].puiAddrUFO.ui32Addr, psUFOPtr[jj].ui32Value);
 #else
                                                        ui32Val = 0;
-                                                       RGXReadWithSP(psDevInfo, psUFOPtr[jj].puiAddrUFO.ui32Addr, &ui32Val);
+                                                       RGXReadFWModuleAddr(psDevInfo, psUFOPtr[jj].puiAddrUFO.ui32Addr, &ui32Val);
                                                        PVR_DUMPDEBUG_LOG("  Addr:0x%08x Value(Host)=0x%08x Value(FW)=0x%08x",
                                                                           psUFOPtr[jj].puiAddrUFO.ui32Addr,
                                                                           psUFOPtr[jj].ui32Value,
@@ -2667,6 +2722,8 @@ void DumpStalledContextInfo(PVRSRV_RGXDEV_INFO *psDevInfo)
                                psDevInfo->psRGXFWIfFwOsData->ui8SLRLogWp = (psDevInfo->psRGXFWIfFwOsData->ui8SLRLogWp + 1) % PVR_SLR_LOG_ENTRIES;
                        }
                        psDevInfo->psRGXFWIfFwOsData->ui32ForcedUpdatesRequested++;
+                       /* flush write buffers for psRGXFWIfFwOsData */
+                       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfFwOsData->sSLRLog[psDevInfo->psRGXFWIfFwOsData->ui8SLRLogWp]);
 #endif
                        PVR_LOG(("Fence found on context 0x%x '%s' @ %d has %d UFOs",
                                 FWCommonContextGetFWAddress(psStalledClientCCB->psServerCommonContext).ui32Addr,
@@ -2732,7 +2789,6 @@ void DumpStalledContextInfo(PVRSRV_RGXDEV_INFO *psDevInfo)
                                        RGXScheduleCommand(FWCommonContextGetRGXDevInfo(psStalledClientCCB->psServerCommonContext),
                                                           RGXFWIF_DM_GP,
                                                           &sSignalFencesCmd,
-                                                          0,
                                                           PDUMP_FLAGS_CONTINUOUS);
                                }
                        }
index 6ddb9fd..0dddee1 100644 (file)
@@ -114,6 +114,13 @@ static_assert(RGX_TDM_CCB_SIZE_LOG2 >= MIN_SAFE_CCB_SIZE_LOG2 &&
 static_assert(RGX_TDM_CCB_MAX_SIZE_LOG2 >= PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_TDM &&
        RGX_TDM_CCB_MAX_SIZE_LOG2 <= MAX_SAFE_CCB_SIZE_LOG2, "TDM max CCB size is invalid");
 
+#define RGX_RDM_CCB_SIZE_LOG2          PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_RDM
+static_assert(RGX_RDM_CCB_SIZE_LOG2 >= MIN_SAFE_CCB_SIZE_LOG2 &&
+       RGX_RDM_CCB_SIZE_LOG2 <= MAX_SAFE_CCB_SIZE_LOG2, "RDM CCB size is invalid");
+#define RGX_RDM_CCB_MAX_SIZE_LOG2              PVRSRV_RGX_LOG2_CLIENT_CCB_MAX_SIZE_RDM
+static_assert(RGX_RDM_CCB_MAX_SIZE_LOG2 >= PVRSRV_RGX_LOG2_CLIENT_CCB_SIZE_RDM &&
+       RGX_RDM_CCB_MAX_SIZE_LOG2 <= MAX_SAFE_CCB_SIZE_LOG2, "RDM max CCB size is invalid");
+
 typedef struct _RGX_CLIENT_CCB_ RGX_CLIENT_CCB;
 
 /*
@@ -262,7 +269,8 @@ IMG_UINT32 RGXGetWrapMaskCCB(RGX_CLIENT_CCB *psClientCCB);
 PVRSRV_ERROR RGXSetCCBFlags(RGX_CLIENT_CCB *psClientCCB,
                                                        IMG_UINT32              ui32Flags);
 
-void RGXCmdHelperInitCmdCCB_CommandSize(IMG_UINT64 ui64FBSCEntryMask,
+void RGXCmdHelperInitCmdCCB_CommandSize(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                               IMG_UINT64 ui64FBSCEntryMask,
                                         IMG_UINT32 ui32ClientFenceCount,
                                         IMG_UINT32 ui32ClientUpdateCount,
                                         IMG_UINT32 ui32CmdSize,
@@ -292,7 +300,8 @@ void RGXCmdHelperInitCmdCCB_OtherData(RGX_CLIENT_CCB *psClientCCB,
                                       IMG_BOOL bCCBStateOpen,
                                       RGX_CCB_CMD_HELPER_DATA *psCmdHelperData);
 
-void RGXCmdHelperInitCmdCCB(RGX_CLIENT_CCB          *psClientCCB,
+void RGXCmdHelperInitCmdCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                       RGX_CLIENT_CCB          *psClientCCB,
                             IMG_UINT64              ui64FBSCEntryMask,
                             IMG_UINT32              ui32ClientFenceCount,
                             PRGXFWIF_UFO_ADDR       *pauiFenceUFOAddress,
index 81c662f..1e7a51f 100644 (file)
@@ -95,7 +95,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
        IMG_BOOL bWaitForFwUpdate = IMG_FALSE;
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
 
        ui32OldRGXFWLogTpe = psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType;
 
@@ -111,7 +111,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
         * before requesting the FW to read it
         */
        psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType = ui32RGXFWLogType;
-       OSMemoryBarrier();
+       OSMemoryBarrier(&psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType);
 
        /* Allocate firmware trace buffer resource(s) if not already done */
        if (RGXTraceBufferIsInitRequired(psDevInfo))
@@ -139,7 +139,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
                         "%s: Failed to allocate resource on-demand. Reverting to old value",
                         __func__));
                psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType = ui32OldRGXFWLogTpe;
-               OSMemoryBarrier();
+               OSMemoryBarrier(&psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType);
 
                OSLockRelease(psDevInfo->hRGXFWIfBufInitLock);
 
@@ -148,7 +148,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
 
        OSLockRelease(psDevInfo->hRGXFWIfBufInitLock);
 
-       eError = PVRSRVPowerLock((const PPVRSRV_DEVICE_NODE) psDeviceNode);
+       eError = PVRSRVPowerLock((PPVRSRV_DEVICE_NODE) psDeviceNode);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -158,7 +158,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
                return eError;
        }
 
-       eError = PVRSRVGetDevicePowerState((const PPVRSRV_DEVICE_NODE) psDeviceNode, &ePowerState);
+       eError = PVRSRVGetDevicePowerState((PPVRSRV_DEVICE_NODE) psDeviceNode, &ePowerState);
 
        if ((eError == PVRSRV_OK) && (ePowerState != PVRSRV_DEV_POWER_STATE_OFF))
        {
@@ -174,7 +174,7 @@ PVRSRVRGXFWDebugSetFWLogKM(
        }
 
 unlock:
-       PVRSRVPowerUnlock((const PPVRSRV_DEVICE_NODE) psDeviceNode);
+       PVRSRVPowerUnlock( (PPVRSRV_DEVICE_NODE) psDeviceNode);
        if (bWaitForFwUpdate)
        {
                /* Wait for the LogType value to be updated in FW */
index 8865855..0a9813b 100644 (file)
@@ -177,6 +177,7 @@ found:
  @Return        void
 
 ******************************************************************************/
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static void RGXFWConfigureSegID(const void *hPrivate,
                                 IMG_UINT64 ui64SegOutAddr,
                                 IMG_UINT32 ui32SegBase,
@@ -217,6 +218,7 @@ static void RGXFWConfigureSegID(const void *hPrivate,
 
        *ppui32BootConf = pui32BootConf;
 }
+#endif
 
 /*!
 *******************************************************************************
@@ -233,6 +235,7 @@ static void RGXFWConfigureSegID(const void *hPrivate,
  @Return        void
 
 ******************************************************************************/
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static void RGXFWConfigureSegMMU(const void       *hPrivate,
                                  IMG_DEV_VIRTADDR *psFWCodeDevVAddrBase,
                                  IMG_DEV_VIRTADDR *psFWDataDevVAddrBase,
@@ -282,6 +285,7 @@ static void RGXFWConfigureSegMMU(const void       *hPrivate,
                }
        }
 }
+#endif
 
 /*!
 *******************************************************************************
@@ -297,6 +301,7 @@ static void RGXFWConfigureSegMMU(const void       *hPrivate,
  @Return        void
 
 ******************************************************************************/
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static void RGXFWConfigureMetaCaches(const void *hPrivate,
                                      IMG_UINT32 ui32NumThreads,
                                      IMG_UINT32 **ppui32BootConf)
@@ -323,8 +328,8 @@ static void RGXFWConfigureMetaCaches(const void *hPrivate,
        RGXCommentLog(hPrivate, "********** Meta caches configuration *********");
 
        /* Initialise I/Dcache settings */
-       ui32DCacheT0 = ui32DCacheT1 = META_CR_SYSC_DCPARTX_CACHED_WRITE_ENABLE;
-       ui32DCacheT2 = ui32DCacheT3 = META_CR_SYSC_DCPARTX_CACHED_WRITE_ENABLE;
+       ui32DCacheT0 = ui32DCacheT1 = (IMG_UINT32)META_CR_SYSC_DCPARTX_CACHED_WRITE_ENABLE;
+       ui32DCacheT2 = ui32DCacheT3 = (IMG_UINT32)META_CR_SYSC_DCPARTX_CACHED_WRITE_ENABLE;
        ui32ICacheT0 = ui32ICacheT1 = ui32ICacheT2 = ui32ICacheT3 = 0;
 
        if (ui32NumThreads == 1)
@@ -413,6 +418,7 @@ static void RGXFWConfigureMetaCaches(const void *hPrivate,
 
        *ppui32BootConf = pui32BootConf;
 }
+#endif
 
 /*!
 *******************************************************************************
@@ -891,20 +897,27 @@ PVRSRV_ERROR RGXProcessFWImage(const void *hPrivate,
                                void *pvFWData,
                                void *pvFWCorememCode,
                                void *pvFWCorememData,
-                               RGX_FW_BOOT_PARAMS *puFWParams)
+                               PVRSRV_FW_BOOT_PARAMS *puFWParams)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_BOOL bMIPS = IMG_FALSE;
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
        IMG_BOOL bRISCV = RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR);
+#endif
        IMG_BOOL bMETA;
 
 #if defined(RGX_FEATURE_MIPS_BIT_MASK)
-       bMIPS = RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS);
+       bMIPS = (IMG_BOOL)RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS);
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+       bMETA = (IMG_BOOL)(!bMIPS && !bRISCV);
+#else
+       bMETA = !bMIPS;
 #endif
-       bMETA = !bMIPS && !bRISCV;
 
        if (bMETA)
        {
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
                IMG_UINT32 *pui32BootConf = NULL;
                /* Skip bootloader configuration if a pointer to the FW code
                 * allocation is not available
@@ -974,17 +987,20 @@ PVRSRV_ERROR RGXProcessFWImage(const void *hPrivate,
                                *pui32BootConf++ = 0;
                        }
 
+#if defined(RGX_FEATURE_META_DMA_BIT_MASK)
                        if (RGX_DEVICE_HAS_FEATURE(hPrivate, META_DMA))
                        {
                                *pui32BootConf++ = (IMG_UINT32) (puFWParams->sMeta.sFWCorememCodeDevVAddr.uiAddr >> 32);
                                *pui32BootConf++ = (IMG_UINT32) puFWParams->sMeta.sFWCorememCodeDevVAddr.uiAddr;
                        }
                        else
+#endif
                        {
                                *pui32BootConf++ = 0;
                                *pui32BootConf++ = 0;
                        }
                }
+#endif /* defined(RGX_FEATURE_META_MAX_VALUE_IDX) */
        }
 #if defined(RGXMIPSFW_MAX_NUM_PAGETABLE_PAGES)
        else if (bMIPS)
index 9fe64f0..e5f9a2a 100644 (file)
@@ -53,45 +53,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 #include "rgxlayer.h"
 
-
-typedef union _RGX_FW_BOOT_PARAMS_
-{
-       struct
-       {
-               IMG_DEV_VIRTADDR sFWCodeDevVAddr;
-               IMG_DEV_VIRTADDR sFWDataDevVAddr;
-               IMG_DEV_VIRTADDR sFWCorememCodeDevVAddr;
-               RGXFWIF_DEV_VIRTADDR sFWCorememCodeFWAddr;
-               IMG_DEVMEM_SIZE_T uiFWCorememCodeSize;
-               IMG_DEV_VIRTADDR sFWCorememDataDevVAddr;
-               RGXFWIF_DEV_VIRTADDR sFWCorememDataFWAddr;
-               IMG_UINT32 ui32NumThreads;
-       } sMeta;
-
-#if defined(RGXMIPSFW_MAX_NUM_PAGETABLE_PAGES)
-       struct
-       {
-               IMG_DEV_PHYADDR sGPURegAddr;
-               IMG_DEV_PHYADDR asFWPageTableAddr[RGXMIPSFW_MAX_NUM_PAGETABLE_PAGES];
-               IMG_DEV_PHYADDR sFWStackAddr;
-               IMG_UINT32 ui32FWPageTableLog2PageSize;
-               IMG_UINT32 ui32FWPageTableNumPages;
-       } sMips;
-#endif
-
-       struct
-       {
-               IMG_DEV_VIRTADDR sFWCorememCodeDevVAddr;
-               RGXFWIF_DEV_VIRTADDR sFWCorememCodeFWAddr;
-               IMG_DEVMEM_SIZE_T uiFWCorememCodeSize;
-
-               IMG_DEV_VIRTADDR sFWCorememDataDevVAddr;
-               RGXFWIF_DEV_VIRTADDR sFWCorememDataFWAddr;
-               IMG_DEVMEM_SIZE_T uiFWCorememDataSize;
-       } sRISCV;
-
-} RGX_FW_BOOT_PARAMS;
-
 /*!
 *******************************************************************************
 
@@ -257,6 +218,6 @@ PVRSRV_ERROR RGXProcessFWImage(const void *hPrivate,
                                void *pvFWData,
                                void *pvFWCorememCode,
                                void *pvFWCorememData,
-                               RGX_FW_BOOT_PARAMS *puFWParams);
+                               PVRSRV_FW_BOOT_PARAMS *puFWParams);
 
 #endif /* RGXFWIMAGEUTILS_H */
index bcb1ed1..e2b472d 100644 (file)
@@ -71,9 +71,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxinit.h"
 
 #include "info_page_defs.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 /* This is defined by default to enable producer callbacks.
  * Clients of the TL interface can disable the use of the callback
@@ -324,7 +321,7 @@ static IMG_UINT32 RGXHWPerfDataStore(PVRSRV_RGXDEV_INFO     *psDevInfo)
         * indexes of the FW buffer */
        ui32SrcRIdx = psFwSysData->ui32HWPerfRIdx;
        ui32SrcWIdx = psFwSysData->ui32HWPerfWIdx;
-       OSMemoryBarrier();
+       OSMemoryBarrier(NULL);
        ui32SrcWrapCount = psFwSysData->ui32HWPerfWrapCount;
 
 #if defined(HWPERF_MISR_FUNC_DEBUG) || defined(EMULATOR)
@@ -361,9 +358,10 @@ static IMG_UINT32 RGXHWPerfDataStore(PVRSRV_RGXDEV_INFO    *psDevInfo)
                        /* Advance the read index and the free bytes counter by the number
                         * of bytes transported. Items will be left in buffer if not all data
                         * could be transported. Exit to allow buffer to drain. */
-                       psFwSysData->ui32HWPerfRIdx = RGXHWPerfAdvanceRIdx(
-                                       psDevInfo->ui32RGXFWIfHWPerfBufSize, ui32SrcRIdx,
-                                       ui32BytesCopied);
+                       OSWriteDeviceMem32WithWMB(&psFwSysData->ui32HWPerfRIdx,
+                                                 RGXHWPerfAdvanceRIdx(psDevInfo->ui32RGXFWIfHWPerfBufSize,
+                                                                      ui32SrcRIdx,
+                                                                      ui32BytesCopied));
 
                        ui32BytesCopiedSum += ui32BytesCopied;
                }
@@ -392,9 +390,10 @@ static IMG_UINT32 RGXHWPerfDataStore(PVRSRV_RGXDEV_INFO    *psDevInfo)
                        /* Update Wrap Count */
                        if ( ui32SrcRIdx == 0)
                        {
-                               psFwSysData->ui32HWPerfWrapCount = psDevInfo->ui32RGXFWIfHWPerfBufSize;
+                               OSWriteDeviceMem32WithWMB(&psFwSysData->ui32HWPerfWrapCount,
+                                                         psDevInfo->ui32RGXFWIfHWPerfBufSize);
                        }
-                       psFwSysData->ui32HWPerfRIdx = ui32SrcRIdx;
+                       OSWriteDeviceMem32WithWMB(&psFwSysData->ui32HWPerfRIdx, ui32SrcRIdx);
 
                        ui32BytesCopiedSum += ui32BytesCopied;
 
@@ -563,7 +562,7 @@ PVRSRV_ERROR RGXHWPerfInit(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
        PVR_DPF_ENTERED;
 
        /* expecting a valid device info */
-       PVR_ASSERT(psRgxDevInfo);
+       PVR_RETURN_IF_INVALID_PARAM(psRgxDevInfo != NULL);
 
        /* Create a lock for HWPerf server module used for serializing, L1 to L2
         * copy calls (e.g. in case of TL producer callback) and L1, L2 resource
@@ -632,6 +631,8 @@ static void _HWPerfFWOnReaderOpenCB(void *pvArg)
        RGXFWIF_KCCB_CMD sKccbCmd;
        IMG_UINT32 ui32kCCBCommandSlot;
 
+       PVRSRV_VZ_RETN_IF_MODE(GUEST);
+
        /* Clear any previously suspended state for bSuspendHWPerfL2DataCopy as we
         * now have a reader attached so the data will be delivered upstream. */
        if (psRgxDevInfo->bSuspendHWPerfL2DataCopy)
@@ -648,7 +649,6 @@ static void _HWPerfFWOnReaderOpenCB(void *pvArg)
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevNode->pvDevice,
                                                                                          RGXFWIF_DM_GP,
                                                                                          &sKccbCmd,
-                                                                                         0,
                                                                                          PDUMP_FLAGS_CONTINUOUS,
                                                                                          &ui32kCCBCommandSlot);
        if (eError != PVRSRV_OK)
@@ -679,9 +679,6 @@ static void _HWPerfFWOnReaderOpenCB(void *pvArg)
  */ /**************************************************************************/
 PVRSRV_ERROR RGXHWPerfInitOnDemandResources(PVRSRV_RGXDEV_INFO* psRgxDevInfo)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        IMG_HANDLE hStream = NULL; /* Init required for noHW */
        PVRSRV_ERROR eError;
        IMG_UINT32 ui32L2BufferSize = 0;
@@ -693,13 +690,15 @@ PVRSRV_ERROR RGXHWPerfInitOnDemandResources(PVRSRV_RGXDEV_INFO* psRgxDevInfo)
 
        PVR_DPF_ENTERED;
 
-       /* Create the L1 HWPerf buffer on demand */
+       /* Create the L1 HWPerf buffer on demand, read-only for the CPU
+        * (except for the zero/poison operations) */
        uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT)
                                                | PVRSRV_MEMALLOCFLAG_GPU_READABLE
                                                | PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE
+                                               | PVRSRV_MEMALLOCFLAG_GPU_UNCACHED
                                                | PVRSRV_MEMALLOCFLAG_CPU_READABLE
+                                               | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC
                                                | PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE
-                                               | PVRSRV_MEMALLOCFLAG_UNCACHED
 #if defined(PDUMP) /* Helps show where the packet data ends */
                                                | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC
 #else /* Helps show corruption issues in driver-live */
@@ -741,7 +740,7 @@ PVRSRV_ERROR RGXHWPerfInitOnDemandResources(PVRSRV_RGXDEV_INFO* psRgxDevInfo)
 #endif
 
        /* flush write buffers for psRgxDevInfo->psRGXFWIfRuntimeCfg */
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psRgxDevInfo->psRGXFWIfRuntimeCfg->sHWPerfBuf.ui32Addr);
 
        eError = DevmemAcquireCpuVirtAddr(psRgxDevInfo->psRGXFWIfHWPerfBufMemDesc,
                                          (void**)&psRgxDevInfo->psRGXFWIfHWPerfBuf);
@@ -752,15 +751,6 @@ PVRSRV_ERROR RGXHWPerfInitOnDemandResources(PVRSRV_RGXDEV_INFO* psRgxDevInfo)
                                __func__, eError));
                goto e0;
        }
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psRgxDevInfo->psRGXFWIfHWPerfBufMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psRgxDevInfo->psRGXFWIfHWPerfBuf - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
 
        /* On NO-HW driver, there is no MISR installed to copy data from L1 to L2. Hence,
         * L2 buffer is not allocated */
@@ -893,6 +883,8 @@ static PVRSRV_ERROR RGXHWPerfCtrlFwBuffer(const PVRSRV_DEVICE_NODE *psDeviceNode
        RGXFWIF_KCCB_CMD sKccbCmd;
        IMG_UINT32 ui32kCCBCommandSlot;
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        /* If this method is being used whether to enable or disable
         * then the hwperf buffers (host and FW) are likely to be needed
         * eventually so create them, also helps unit testing. Buffers
@@ -925,7 +917,7 @@ static PVRSRV_ERROR RGXHWPerfCtrlFwBuffer(const PVRSRV_DEVICE_NODE *psDeviceNode
                }
        }
 
-#if defined(RGX_FEATURE_HWPERF_VOLCANIC) && defined(SUPPORT_POWMON_COMPONENT)
+#if defined(RGX_FEATURE_HWPERF_VOLCANIC) && defined(SUPPORT_POWMON_COMPONENT) && defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
        if (RGXPowmonBufferIsInitRequired(psDeviceNode->pvDevice))
        {
                /* Allocate power monitoring log buffer if enabled */
@@ -956,7 +948,6 @@ static PVRSRV_ERROR RGXHWPerfCtrlFwBuffer(const PVRSRV_DEVICE_NODE *psDeviceNode
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
                                                  RGXFWIF_DM_GP,
                                                  &sKccbCmd,
-                                                 0,
                                                  IMG_TRUE,
                                                  &ui32kCCBCommandSlot);
        if (eError != PVRSRV_OK)
@@ -1122,25 +1113,25 @@ PVRSRV_ERROR RGXHWPerfSetFwFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                   const void *psPrivate,
                                   IMG_UINT64 ui64Value)
 {
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-       PVRSRV_DEVICE_NODE *psDevNode;
        PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDeviceInfo;
 
-       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
-       psDevNode = psPVRSRVData->psDeviceNodeList;
-       /* Control HWPerf on all the devices */
-       while (psDevNode)
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode != NULL);
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode->pvDevice != NULL);
+
+       psDeviceInfo = psDeviceNode->pvDevice;
+
+       eError = RGXHWPerfCtrlFwBuffer(psDeviceNode, IMG_FALSE, ui64Value);
+       if (eError != PVRSRV_OK)
        {
-               eError = RGXHWPerfCtrlFwBuffer(psDevNode, IMG_FALSE, ui64Value);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "Failed to set HWPerf firmware filter for device (%d)", psDevNode->sDevId.i32OsDeviceID));
-                       return eError;
-               }
-               psDevNode = psDevNode->psNext;
+               PVR_DPF((PVR_DBG_ERROR,
+                       "Failed to set HWPerf firmware filter for device (%u)",
+                       psDeviceNode->sDevId.ui32InternalID));
+               return eError;
        }
+
        return PVRSRV_OK;
 }
 
@@ -1149,19 +1140,14 @@ PVRSRV_ERROR RGXHWPerfReadFwFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                    const void *psPrivate,
                                    IMG_UINT64 *pui64Value)
 {
-       PVRSRV_RGXDEV_INFO *psDevice;
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode != NULL);
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode->pvDevice != NULL);
 
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
-       if (!psDeviceNode || !psDeviceNode->pvDevice)
-       {
-               return PVRSRV_ERROR_INVALID_PARAMS;
-       }
+       *pui64Value =
+           ((PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice)->ui64HWPerfFilter;
 
-       /* Configuration command is applied for all devices, so filter value should
-        * be same for all */
-       psDevice = psDeviceNode->pvDevice;
-       *pui64Value = psDevice->ui64HWPerfFilter;
        return PVRSRV_OK;
 }
 
@@ -1170,25 +1156,22 @@ PVRSRV_ERROR RGXHWPerfSetHostFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                     const void *psPrivate,
                                     IMG_UINT32 ui32Value)
 {
-       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
-       PVRSRV_DEVICE_NODE *psDevNode;
        PVRSRV_ERROR eError;
 
-       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode != NULL);
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode->pvDevice != NULL);
+
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
-       psDevNode = psPVRSRVData->psDeviceNodeList;
-       /* Control HWPerf on all the devices */
-       while (psDevNode)
+       eError = RGXHWPerfCtrlHostBuffer(psDeviceNode, IMG_FALSE, ui32Value);
+       if (eError != PVRSRV_OK)
        {
-               eError = RGXHWPerfCtrlHostBuffer(psDevNode, IMG_FALSE, ui32Value);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "Failed to set HWPerf firmware filter for device (%d)", psDevNode->sDevId.i32OsDeviceID));
-                       return eError;
-               }
-               psDevNode = psDevNode->psNext;
+               PVR_DPF((PVR_DBG_ERROR,
+                       "Failed to set HWPerf firmware filter for device (%u)",
+                       psDeviceNode->sDevId.ui32InternalID));
+               return eError;
        }
+
        return PVRSRV_OK;
 }
 
@@ -1197,17 +1180,14 @@ PVRSRV_ERROR RGXHWPerfReadHostFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
                                      const void *psPrivate,
                                      IMG_UINT32 *pui32Value)
 {
-       PVRSRV_RGXDEV_INFO *psDevice;
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode != NULL);
+       PVR_RETURN_IF_INVALID_PARAM(psDeviceNode->pvDevice != NULL);
 
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
-       if (!psDeviceNode || !psDeviceNode->pvDevice)
-       {
-               return PVRSRV_ERROR_INVALID_PARAMS;
-       }
+       *pui32Value =
+           ((PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice)->ui32HWPerfHostFilter;
 
-       psDevice = psDeviceNode->pvDevice;
-       *pui32Value = psDevice->ui32HWPerfHostFilter;
        return PVRSRV_OK;
 }
 
@@ -1336,7 +1316,7 @@ PVRSRV_ERROR RGXHWPerfHostInit(PVRSRV_RGXDEV_INFO *psRgxDevInfo, IMG_UINT32 ui32
 
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
-       PVR_ASSERT(psRgxDevInfo != NULL);
+       PVR_RETURN_IF_INVALID_PARAM(psRgxDevInfo != NULL);
 
        eError = OSLockCreate(&psRgxDevInfo->hLockHWPerfHostStream);
        PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate", error);
@@ -1356,6 +1336,10 @@ error:
        return eError;
 }
 
+#define RGX_HWPERF_HOST_CLIENT_INFO_PROC_NAME_BASE_SIZE \
+       ((IMG_UINT32)(offsetof(RGX_HWPERF_HOST_CLIENT_INFO_DATA, uDetail) + \
+               sizeof(((RGX_HWPERF_HOST_CLIENT_INFO_DETAIL*)0)->sProcName.ui32Count)))
+
 static void _HWPerfHostOnConnectCB(void *pvArg)
 {
        PVRSRV_RGXDEV_INFO* psDevice;
@@ -1373,6 +1357,65 @@ static void _HWPerfHostOnConnectCB(void *pvArg)
                eError = PVRSRVCreateHWPerfHostThread(PVRSRV_APPHINT_HWPERFHOSTTHREADTIMEOUTINMS);
                PVR_LOG_IF_ERROR(eError, "PVRSRVCreateHWPerfHostThread");
        }
+
+       if (RGXHWPerfHostIsEventEnabled(psDevice, RGX_HWPERF_HOST_CLIENT_INFO))
+       {
+               // GCC throws -Werror=frame-larger-than error if the frame size is > 1024 bytes,
+               // so use a heap allocation - is there an alternate solution?
+               IMG_BYTE *pbPktPayload = (IMG_BYTE*)OSAllocMem(RGX_HWPERF_MAX_PAYLOAD_SIZE);
+
+               if (pbPktPayload)
+               {
+                       RGX_HWPERF_HOST_CLIENT_INFO_DATA *psHostClientInfo;
+                       RGX_HWPERF_HOST_CLIENT_PROC_NAME *psProcName;
+                       IMG_UINT32 ui32TotalPayloadSize, ui32NameLen, ui32ProcNamePktSize;
+                       DLLIST_NODE *pNode, *pNext;
+
+                       psHostClientInfo = IMG_OFFSET_ADDR(pbPktPayload,0);
+                       psHostClientInfo->eType = RGX_HWPERF_HOST_CLIENT_INFO_TYPE_PROCESS_NAME;
+                       psHostClientInfo->uDetail.sProcName.ui32Count = 0U;
+                       psProcName = psHostClientInfo->uDetail.sProcName.asProcNames;
+                       ui32TotalPayloadSize = RGX_HWPERF_HOST_CLIENT_INFO_PROC_NAME_BASE_SIZE;
+
+                       OSLockAcquire(psDevice->psDeviceNode->hConnectionsLock);
+
+                       // Announce current client connections to the reader
+                       dllist_foreach_node(&psDevice->psDeviceNode->sConnections, pNode, pNext)
+                       {
+                               CONNECTION_DATA *psData = IMG_CONTAINER_OF(pNode, CONNECTION_DATA, sConnectionListNode);
+
+                               ui32NameLen = OSStringLength(psData->pszProcName) + 1U;
+                               ui32ProcNamePktSize = RGX_HWPERF_HOST_CLIENT_PROC_NAME_SIZE(ui32NameLen);
+
+                               // Unlikely case where we have too much data to fit into a single hwperf packet
+                               if (ui32ProcNamePktSize + ui32TotalPayloadSize > RGX_HWPERF_MAX_PAYLOAD_SIZE)
+                               {
+                                       RGXHWPerfHostPostRaw(psDevice, RGX_HWPERF_HOST_CLIENT_INFO, pbPktPayload, ui32TotalPayloadSize);
+
+                                       psHostClientInfo->uDetail.sProcName.ui32Count = 0U;
+                                       psProcName = psHostClientInfo->uDetail.sProcName.asProcNames;
+                                       ui32TotalPayloadSize = RGX_HWPERF_HOST_CLIENT_INFO_PROC_NAME_BASE_SIZE;
+                               }
+
+                               // Setup packet data
+                               psHostClientInfo->uDetail.sProcName.ui32Count++;
+                               psProcName->uiClientPID = psData->pid;
+                               psProcName->ui32Length = ui32NameLen;
+                               (void)OSStringLCopy(psProcName->acName, psData->pszProcName, ui32NameLen);
+
+                               psProcName = (RGX_HWPERF_HOST_CLIENT_PROC_NAME*)IMG_OFFSET_ADDR(psProcName, ui32ProcNamePktSize);
+                               ui32TotalPayloadSize += ui32ProcNamePktSize;
+                       }
+
+                       OSLockRelease(psDevice->psDeviceNode->hConnectionsLock);
+                       RGXHWPerfHostPostRaw(psDevice, RGX_HWPERF_HOST_CLIENT_INFO, pbPktPayload, ui32TotalPayloadSize);
+                       OSFreeMem(pbPktPayload);
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: OUT OF MEMORY. Could not allocate memory for RGX_HWPERF_HOST_CLIENT_INFO_DATA packet.", __func__));
+               }
+       }
 }
 
 /* Avoiding a holder struct using fields below, as a struct gets along padding,
@@ -1410,10 +1453,17 @@ static void _HWPerfHostDeferredEventsEmitter(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
 PVRSRV_ERROR RGXHWPerfHostInitOnDemandResources(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
 {
        PVRSRV_ERROR eError;
-       IMG_CHAR pszHWPerfHostStreamName[sizeof(PVRSRV_TL_HWPERF_HOST_SERVER_STREAM) + 5]; /* 5 makes space up to "hwperf_host_9999" streams */
+       /* 5 makes space up to "hwperf_host_9999" streams */
+       IMG_CHAR pszHWPerfHostStreamName[sizeof(PVRSRV_TL_HWPERF_HOST_SERVER_STREAM) + 5];
 
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
 
+       if (psRgxDevInfo->hHWPerfHostStream != NULL)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "HWPerf host stream already initialised"));
+               return PVRSRV_OK;
+       }
+
        /* form the HWPerf host stream name, corresponding to this DevNode; which can make sense in the UM */
        if (OSSNPrintf(pszHWPerfHostStreamName, sizeof(pszHWPerfHostStreamName), "%s%d",
                       PVRSRV_TL_HWPERF_HOST_SERVER_STREAM,
@@ -1794,7 +1844,7 @@ static void _GetHWPerfHostPacketSpecifics(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
        OSSpinLockAcquire(psRgxDevInfo->hHWPerfHostSpinLock, uiFlags);
 
        *pui32Ordinal = psRgxDevInfo->ui32HWPerfHostNextOrdinal++;
-       *pui64Timestamp = RGXTimeCorrGetClockus64();
+       *pui64Timestamp = RGXTimeCorrGetClockus64(psRgxDevInfo->psDeviceNode);
 
        if (!bSleepAllowed)
        {
@@ -1872,7 +1922,7 @@ static inline void _SetupHostEnqPacketData(IMG_UINT8 *pui8Dest,
                                            IMG_UINT64 ui64CheckFenceUID,
                                            IMG_UINT64 ui64UpdateFenceUID,
                                            IMG_UINT64 ui64DeadlineInus,
-                                           IMG_UINT64 ui64CycleEstimate)
+                                           IMG_UINT32 ui32CycleEstimate)
 {
        RGX_HWPERF_HOST_ENQ_DATA *psData = (RGX_HWPERF_HOST_ENQ_DATA *)
                                        IMG_OFFSET_ADDR(pui8Dest, sizeof(RGX_HWPERF_V2_PACKET_HDR));
@@ -1887,7 +1937,38 @@ static inline void _SetupHostEnqPacketData(IMG_UINT8 *pui8Dest,
        psData->ui64CheckFence_UID = ui64CheckFenceUID;
        psData->ui64UpdateFence_UID = ui64UpdateFenceUID;
        psData->ui64DeadlineInus = ui64DeadlineInus;
-       psData->ui64CycleEstimate = ui64CycleEstimate;
+       psData->ui32CycleEstimate = ui32CycleEstimate;
+}
+
+void RGXHWPerfHostPostRaw(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
+                                                 RGX_HWPERF_HOST_EVENT_TYPE eEvType,
+                                                 IMG_BYTE *pbPayload,
+                                                 IMG_UINT32 ui32PayloadSize)
+{
+       IMG_UINT8 *pui8Dest;
+       IMG_UINT32 ui32PktSize;
+       IMG_UINT32 ui32Ordinal;
+       IMG_UINT64 ui64Timestamp;
+
+       PVR_ASSERT(ui32PayloadSize <= RGX_HWPERF_MAX_PAYLOAD_SIZE);
+
+       _GetHWPerfHostPacketSpecifics(psRgxDevInfo, &ui32Ordinal, &ui64Timestamp, NULL, IMG_TRUE);
+       _PostFunctionPrologue(psRgxDevInfo, ui32Ordinal);
+
+       ui32PktSize = RGX_HWPERF_MAKE_SIZE_VARIABLE(ui32PayloadSize);
+       pui8Dest = _ReserveHWPerfStream(psRgxDevInfo, ui32PktSize);
+
+       if (pui8Dest == NULL)
+       {
+               goto cleanup;
+       }
+
+       _SetupHostPacketHeader(psRgxDevInfo, pui8Dest, eEvType, ui32PktSize, ui32Ordinal, ui64Timestamp);
+       OSDeviceMemCopy((IMG_UINT8*)IMG_OFFSET_ADDR(pui8Dest, sizeof(RGX_HWPERF_V2_PACKET_HDR)), pbPayload, ui32PayloadSize);
+       _CommitHWPerfStream(psRgxDevInfo, ui32PktSize);
+
+cleanup:
+       _PostFunctionEpilogue(psRgxDevInfo, ui32Ordinal);
 }
 
 void RGXHWPerfHostPostEnqEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
@@ -1902,7 +1983,7 @@ void RGXHWPerfHostPostEnqEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                IMG_UINT64 ui64CheckFenceUID,
                                IMG_UINT64 ui64UpdateFenceUID,
                                IMG_UINT64 ui64DeadlineInus,
-                               IMG_UINT64 ui64CycleEstimate )
+                               IMG_UINT32 ui32CycleEstimate )
 {
        IMG_UINT8 *pui8Dest;
        IMG_UINT32 ui32Size = RGX_HWPERF_MAKE_SIZE_FIXED(RGX_HWPERF_HOST_ENQ_DATA);
@@ -1933,7 +2014,7 @@ void RGXHWPerfHostPostEnqEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                ui64CheckFenceUID,
                                ui64UpdateFenceUID,
                                ui64DeadlineInus,
-                               ui64CycleEstimate);
+                               ui32CycleEstimate);
 
        _CommitHWPerfStream(psRgxDevInfo, ui32Size);
 
@@ -1994,9 +2075,6 @@ static inline void _SetupHostUfoPacketData(IMG_UINT8 *pui8Dest,
                                        psUFOData->sCheckSuccess.ui32FWAddr;
                        puData->sCheckSuccess.ui32Value =
                                        psUFOData->sCheckSuccess.ui32Value;
-
-                       puData = (RGX_HWPERF_UFO_DATA_ELEMENT *)
-                                                       IMG_OFFSET_ADDR(puData, sizeof(puData->sCheckSuccess));
                        break;
                case RGX_HWPERF_UFO_EV_CHECK_FAIL:
                case RGX_HWPERF_UFO_EV_PRCHECK_FAIL:
@@ -2006,9 +2084,6 @@ static inline void _SetupHostUfoPacketData(IMG_UINT8 *pui8Dest,
                                        psUFOData->sCheckFail.ui32Value;
                        puData->sCheckFail.ui32Required =
                                        psUFOData->sCheckFail.ui32Required;
-
-                       puData = (RGX_HWPERF_UFO_DATA_ELEMENT *)
-                                               IMG_OFFSET_ADDR(puData, sizeof(puData->sCheckFail));
                        break;
                case RGX_HWPERF_UFO_EV_UPDATE:
                        puData->sUpdate.ui32FWAddr =
@@ -2017,9 +2092,6 @@ static inline void _SetupHostUfoPacketData(IMG_UINT8 *pui8Dest,
                                        psUFOData->sUpdate.ui32OldValue;
                        puData->sUpdate.ui32NewValue =
                                        psUFOData->sUpdate.ui32NewValue;
-
-                       puData = (RGX_HWPERF_UFO_DATA_ELEMENT *)
-                                               IMG_OFFSET_ADDR(puData, sizeof(puData->sUpdate));
                        break;
                default:
                        // unknown type - this should never happen
@@ -2445,6 +2517,13 @@ void RGXHWPerfHostPostClkSyncEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
        IMG_UINT32 ui32Ordinal;
        IMG_UINT64 ui64Timestamp;
 
+       /* if the buffer for time correlation data is not yet available (possibly
+        * device not initialised yet) skip this event */
+       if (psRgxDevInfo->psRGXFWIfGpuUtilFWCb == NULL)
+       {
+               return;
+       }
+
        _GetHWPerfHostPacketSpecifics(psRgxDevInfo, &ui32Ordinal, &ui64Timestamp,
                                      NULL, IMG_TRUE);
        _PostFunctionPrologue(psRgxDevInfo, ui32Ordinal);
@@ -2803,6 +2882,45 @@ cleanup:
 
 }
 
+void RGXHWPerfHostPostClientInfoProcName(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
+                                         IMG_PID uiPID,
+                                                                            const IMG_CHAR *psName)
+{
+       RGX_HWPERF_HOST_CLIENT_INFO_DATA* psPkt;
+       IMG_UINT8 *pui8Dest;
+       IMG_UINT32 ui32Size;
+       IMG_UINT32 ui32NameLen;
+       IMG_UINT32 ui32Ordinal;
+       IMG_UINT64 ui64Timestamp;
+
+       _GetHWPerfHostPacketSpecifics(psRgxDevInfo, &ui32Ordinal, &ui64Timestamp, NULL, IMG_TRUE);
+       _PostFunctionPrologue(psRgxDevInfo, ui32Ordinal);
+
+       ui32NameLen = OSStringLength(psName) + 1U;
+       ui32Size = RGX_HWPERF_MAKE_SIZE_VARIABLE(RGX_HWPERF_HOST_CLIENT_INFO_PROC_NAME_BASE_SIZE
+               + RGX_HWPERF_HOST_CLIENT_PROC_NAME_SIZE(ui32NameLen));
+
+       if ((pui8Dest = _ReserveHWPerfStream(psRgxDevInfo, ui32Size)) == NULL)
+       {
+               goto cleanup;
+       }
+
+       _SetupHostPacketHeader(psRgxDevInfo, pui8Dest, RGX_HWPERF_HOST_CLIENT_INFO,
+                              ui32Size, ui32Ordinal, ui64Timestamp);
+
+       psPkt = (RGX_HWPERF_HOST_CLIENT_INFO_DATA*)IMG_OFFSET_ADDR(pui8Dest, sizeof(RGX_HWPERF_V2_PACKET_HDR));
+       psPkt->eType = RGX_HWPERF_HOST_CLIENT_INFO_TYPE_PROCESS_NAME;
+       psPkt->uDetail.sProcName.ui32Count = 1U;
+       psPkt->uDetail.sProcName.asProcNames[0].uiClientPID = uiPID;
+       psPkt->uDetail.sProcName.asProcNames[0].ui32Length = ui32NameLen;
+       (void)OSStringLCopy(psPkt->uDetail.sProcName.asProcNames[0].acName, psName, ui32NameLen);
+
+       _CommitHWPerfStream(psRgxDevInfo, ui32Size);
+
+cleanup:
+       _PostFunctionEpilogue(psRgxDevInfo, ui32Ordinal);
+}
+
 /******************************************************************************
  * Currently only implemented on Linux. Feature can be enabled to provide
  * an interface to 3rd-party kernel modules that wish to access the
@@ -2857,7 +2975,9 @@ PVRSRV_ERROR RGXHWPerfLazyConnect(RGX_HWPERF_CONNECTION** ppsHWPerfConnection)
        /* early save the return pointer to aid clean-up if failure occurs */
        *ppsHWPerfConnection = psHWPerfConnection;
 
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
        psDeviceNode = psPVRSRVData->psDeviceNodeList;
+
        while (psDeviceNode)
        {
                if (psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_ACTIVE)
@@ -2873,6 +2993,7 @@ PVRSRV_ERROR RGXHWPerfLazyConnect(RGX_HWPERF_CONNECTION** ppsHWPerfConnection)
                psNewHWPerfDevice = OSAllocMem(sizeof(*psNewHWPerfDevice));
                if (!psNewHWPerfDevice)
                {
+                       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
                        return PVRSRV_ERROR_OUT_OF_MEMORY;
                }
                /* Insert node at head of the list */
@@ -2884,11 +3005,13 @@ PVRSRV_ERROR RGXHWPerfLazyConnect(RGX_HWPERF_CONNECTION** ppsHWPerfConnection)
                psNewHWPerfDevice->hDevData = (IMG_HANDLE)psDevData;
                if (!psDevData)
                {
+                       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
                        return PVRSRV_ERROR_OUT_OF_MEMORY;
                }
                if (OSSNPrintf(psNewHWPerfDevice->pszName, sizeof(psNewHWPerfDevice->pszName),
-                              "hwperf_device_%d", psDeviceNode->sDevId.i32OsDeviceID) < 0)
+                                  "hwperf_device_%d", psDeviceNode->sDevId.i32OsDeviceID) < 0)
                {
+                       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
                        PVR_DPF((PVR_DBG_ERROR,
                                         "%s: Failed to form HWPerf device name for device %d",
                                        __func__,
@@ -2905,6 +3028,8 @@ PVRSRV_ERROR RGXHWPerfLazyConnect(RGX_HWPERF_CONNECTION** ppsHWPerfConnection)
                bFWActive = IMG_TRUE;
        }
 
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
        if (!bFWActive)
        {
                return PVRSRV_ERROR_NOT_READY;
@@ -3081,7 +3206,7 @@ PVRSRV_ERROR PVRSRVRGXControlHWPerfBlocksKM(
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
 
        PVR_DPF_ENTERED;
 
@@ -3105,7 +3230,6 @@ PVRSRV_ERROR PVRSRVRGXControlHWPerfBlocksKM(
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
                                                  RGXFWIF_DM_GP,
                                                  &sKccbCmd,
-                                                 0,
                                                  PDUMP_FLAGS_CONTINUOUS,
                                                  &ui32kCCBCommandSlot);
        PVR_LOG_RETURN_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot");
index 640cf62..76957c3 100644 (file)
@@ -109,6 +109,11 @@ void RGXHWPerfHostDeInit(PVRSRV_RGXDEV_INFO        *psRgxDevInfo);
 void RGXHWPerfHostSetEventFilter(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                  IMG_UINT32 ui32Filter);
 
+void RGXHWPerfHostPostRaw(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
+                                                 RGX_HWPERF_HOST_EVENT_TYPE eEvType,
+                                                 IMG_BYTE *pbPayload,
+                                                 IMG_UINT32 ui32PayloadSize);
+
 void RGXHWPerfHostPostEnqEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                RGX_HWPERF_KICK_TYPE eEnqType,
                                IMG_UINT32 ui32Pid,
@@ -121,7 +126,7 @@ void RGXHWPerfHostPostEnqEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                IMG_UINT64 ui64CheckFenceUID,
                                IMG_UINT64 ui64UpdateFenceUID,
                                IMG_UINT64 ui64DeadlineInus,
-                               IMG_UINT64 ui64CycleEstimate);
+                               IMG_UINT32 ui32CycleEstimate);
 
 void RGXHWPerfHostPostAllocEvent(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                  RGX_HWPERF_HOST_RESOURCE_TYPE eAllocType,
@@ -169,6 +174,10 @@ void RGXHWPerfHostPostSWTimelineAdv(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
                                                                        PVRSRV_TIMELINE hSWTimeline,
                                                                        IMG_UINT64 ui64SyncPtIndex);
 
+void RGXHWPerfHostPostClientInfoProcName(PVRSRV_RGXDEV_INFO *psRgxDevInfo,
+                                         IMG_PID uiPID,
+                                                                            const IMG_CHAR *psName);
+
 IMG_BOOL RGXHWPerfHostIsEventEnabled(PVRSRV_RGXDEV_INFO *psRgxDevInfo, RGX_HWPERF_HOST_EVENT_TYPE eEvent);
 
 #define _RGX_HWPERF_HOST_FILTER(CTX, EV) \
@@ -466,6 +475,20 @@ do { \
                RGXHWPerfHostPostSWTimelineAdv((I), (PID), (SW_TL), (SPI)); \
        } \
 } while (0)
+
+/**
+ * @param D      Device Node pointer
+ * @param PID    Process ID that the following timeline belongs to
+ * @param N      Null terminated string containing the process name
+ */
+#define RGXSRV_HWPERF_HOST_CLIENT_INFO_PROCESS_NAME(D, PID, N) \
+do { \
+       if (RGXHWPerfHostIsEventEnabled(_RGX_DEVICE_INFO_FROM_NODE(D), RGX_HWPERF_HOST_CLIENT_INFO)) \
+       { \
+               RGXHWPerfHostPostClientInfoProcName(_RGX_DEVICE_INFO_FROM_NODE(D), (PID), (N)); \
+       } \
+} while (0)
+
 #else
 
 #define RGXSRV_HWPERF_ENQ(C, P, X, E, I, K, CF, UF, UT, CHKUID, UPDUID, D, CE)
@@ -482,6 +505,7 @@ do { \
 #define RGXSRV_HWPERF_HOST_INFO(I, T)
 #define RGXSRV_HWPERF_SYNC_FENCE_WAIT(I, T, PID, F, D)
 #define RGXSRV_HWPERF_SYNC_SW_TL_ADV(I, PID, SW_TL, SPI)
+#define RGXSRV_HWPERF_HOST_CLIENT_INFO_PROCESS_NAME(D, PID, N)
 
 #endif
 
index 6a40d9b..73f1b78 100644 (file)
@@ -200,18 +200,19 @@ PVRSRV_ERROR PVRSRVRGXSetKickSyncContextPropertyKM(RGX_SERVER_KICKSYNC_CONTEXT *
                                                    IMG_UINT64 ui64Input,
                                                    IMG_UINT64 *pui64Output)
 {
-       PVRSRV_ERROR eError;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (eContextProperty)
        {
                case RGX_CONTEXT_PROPERTY_FLAGS:
                {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
                        OSLockAcquire(psKickSyncContext->hLock);
                        eError = FWCommonContextSetFlags(psKickSyncContext->psServerCommonContext,
-                                                        (IMG_UINT32)ui64Input);
+                                                        ui32ContextFlags);
 
                        OSLockRelease(psKickSyncContext->hLock);
-                       PVR_LOG_IF_ERROR(eError, "FWCommonContextSetFlags");
                        break;
                }
 
@@ -272,7 +273,6 @@ IMG_UINT32 CheckForStalledClientKickSyncCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
 }
 
 PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContext,
-                                 IMG_UINT32                    ui32ClientCacheOpSeqNum,
                                  IMG_UINT32                    ui32ClientUpdateCount,
                                  SYNC_PRIMITIVE_BLOCK       ** pauiClientUpdateUFODevVarBlock,
                                  IMG_UINT32                  * paui32ClientUpdateOffset,
@@ -594,7 +594,8 @@ PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContext
                }
 #endif
 
-       RGXCmdHelperInitCmdCCB(psClientCCB,
+       RGXCmdHelperInitCmdCCB(psDevInfo,
+                              psClientCCB,
                               0, /* empty ui64FBSCEntryMask */
                               ui32ClientFenceCount,
                               pauiClientFenceUFOAddress,
@@ -676,7 +677,6 @@ PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContext
                eError2 = RGXScheduleCommand(psKickSyncContext->psDeviceNode->pvDevice,
                                             RGXFWIF_DM_GP,
                                             & sKickSyncKCCBCmd,
-                                            ui32ClientCacheOpSeqNum,
                                             PDUMP_FLAGS_NONE);
                if (eError2 != PVRSRV_ERROR_RETRY)
                {
@@ -694,6 +694,10 @@ PVRSRV_ERROR PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKickSyncContext
                PVR_DPF((PVR_DBG_ERROR,
                         "PVRSRVRGXKickSync failed to schedule kernel CCB command. (0x%x)",
                         eError));
+               if (eError == PVRSRV_OK)
+               {
+                       eError = eError2;
+               }
        }
 
        /*
index b968520..57b49a0 100644 (file)
@@ -110,7 +110,6 @@ PVRSRV_ERROR PVRSRVRGXSetKickSyncContextPropertyKM(RGX_SERVER_KICKSYNC_CONTEXT *
 */ /**************************************************************************/
 PVRSRV_ERROR
 PVRSRVRGXKickSyncKM(RGX_SERVER_KICKSYNC_CONTEXT * psKicksyncContext,
-                    IMG_UINT32                    ui32ClientCacheOpSeqNum,
                     IMG_UINT32                    ui32ClientUpdateCount,
                     SYNC_PRIMITIVE_BLOCK       ** pauiClientUpdateUFODevVarBlock,
                     IMG_UINT32                  * paui32ClientUpdateDevVarOffset,
index f0434e2..de38b1c 100644 (file)
@@ -58,15 +58,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgx_memallocflags.h"
 #include "rgx_bvnc_defs_km.h"
 #include "info_page.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #if defined(PDUMP)
 #include "sync.h"
 #endif
 
-typedef struct SERVER_MMU_CONTEXT_TAG
+struct SERVER_MMU_CONTEXT_TAG
 {
        DEVMEM_MEMDESC *psFWMemContextMemDesc;
        PRGXFWIF_FWMEMCONTEXT sFWMemContextDevVirtAddr;
@@ -76,7 +73,7 @@ typedef struct SERVER_MMU_CONTEXT_TAG
        IMG_UINT64 ui64FBSCEntryMask;
        DLLIST_NODE sNode;
        PVRSRV_RGXDEV_INFO *psDevInfo;
-} SERVER_MMU_CONTEXT;
+}; /* SERVER_MMU_CONTEXT is typedef-ed in rgxmem.h */
 
 PVRSRV_ERROR RGXSLCFlushRange(PVRSRV_DEVICE_NODE *psDeviceNode,
                                                          MMU_CONTEXT *psMMUContext,
@@ -111,7 +108,8 @@ PVRSRV_ERROR RGXSLCFlushRange(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        /* Schedule the SLC flush command */
 #if defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Submit SLC flush and invalidate");
 #endif
        sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
        sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = bInvalidate;
@@ -225,7 +223,9 @@ void RGXMMUCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode,
                case MMU_LEVEL_1:
                        ui32NewCacheFlags = RGXFWIF_MMUCACHEDATA_FLAGS_PT;
 
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
                        if (!(RGX_IS_FEATURE_SUPPORTED(psDevInfo, SLC_VIVT)))
+#endif
                        {
                                ui32NewCacheFlags |= RGXFWIF_MMUCACHEDATA_FLAGS_TLB;
                        }
@@ -238,11 +238,13 @@ void RGXMMUCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode,
                        break;
        }
 
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, SLC_VIVT))
        {
                MMU_AppendCacheFlags(psMMUContext, ui32NewCacheFlags);
        }
        else
+#endif
        {
                MMU_AppendCacheFlags(psDevInfo->psKernelMMUCtx, ui32NewCacheFlags);
        }
@@ -286,7 +288,7 @@ PVRSRV_ERROR _PrepareAndSubmitCacheCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
        sFlushCmd.uCmdData.sMMUCacheData.ui32CacheFlags = ui32CacheFlags;
 
 #if defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Submit MMU flush and invalidate (flags = 0x%08x)",
                              ui32CacheFlags);
 #endif
@@ -312,7 +314,7 @@ PVRSRV_ERROR RGXMMUCacheInvalidateKick(PVRSRV_DEVICE_NODE *psDeviceNode,
 {
        PVRSRV_ERROR eError;
        IMG_UINT32 ui32FWCacheFlags;
-
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
        eError = PVRSRVPowerLock(psDeviceNode);
        if (eError != PVRSRV_OK)
        {
@@ -330,15 +332,16 @@ PVRSRV_ERROR RGXMMUCacheInvalidateKick(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        /* Ensure device is powered up before sending cache command */
-       PDUMPPOWCMDSTART();
+       PDUMPPOWCMDSTART(psDeviceNode);
        eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                                                 PVRSRV_DEV_POWER_STATE_ON,
-                                                                                IMG_FALSE);
-       PDUMPPOWCMDEND();
+                                                                                PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDeviceNode);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_WARNING, "%s: failed to transition RGX to ON (%s)",
                                        __func__, PVRSRVGetErrorString(eError)));
+               MMU_AppendCacheFlags(psDevInfo->psKernelMMUCtx, ui32FWCacheFlags);
                goto _PowerUnlockAndReturnErr;
        }
 
@@ -347,6 +350,9 @@ PVRSRV_ERROR RGXMMUCacheInvalidateKick(PVRSRV_DEVICE_NODE *psDeviceNode,
        if (eError != PVRSRV_OK)
        {
                /* failed to submit cache operations, return failure */
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to submit cache command (%s)",
+                                       __func__, PVRSRVGetErrorString(eError)));
+               MMU_AppendCacheFlags(psDevInfo->psKernelMMUCtx, ui32FWCacheFlags);
                goto _PowerUnlockAndReturnErr;
        }
 
@@ -439,7 +445,8 @@ void RGXUnregisterMemoryContext(IMG_HANDLE hPrivData)
                 * MMU cache commands (always dumped) might have a pointer to this FW
                 * memory context, wait until the FW has caught-up to the latest command.
                 */
-               PDUMPCOMMENT("Ensure FW has executed all MMU invalidations on FW memory "
+               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                            "Ensure FW has executed all MMU invalidations on FW memory "
                             "context 0x%x before freeing it", sFWAddr.ui32Addr);
                SyncPrimPDumpPol(psDevInfo->psDeviceNode->psMMUCacheSyncPrim,
                                 psDevInfo->psDeviceNode->ui32NextMMUInvalidateUpdate - 1,
@@ -466,7 +473,7 @@ void RGXUnregisterMemoryContext(IMG_HANDLE hPrivData)
        /*
         * Free the firmware memory context.
         */
-       PDUMPCOMMENT("Free FW memory context");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Free FW memory context");
        DevmemFwUnmapAndFree(psDevInfo, psServerMMUContext->psFWMemContextMemDesc);
 
        OSFreeMem(psServerMMUContext);
@@ -479,9 +486,6 @@ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE    *psDeviceNode,
                                                                          MMU_CONTEXT                   *psMMUContext,
                                                                          IMG_HANDLE                    *hPrivData)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_ERROR                    eError;
        PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
        PVRSRV_MEMALLOCFLAGS_T  uiFWMemContextMemAllocFlags;
@@ -539,7 +543,7 @@ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE    *psDeviceNode,
                        Allocate device memory for the firmware memory context for the new
                        application.
                */
-               PDUMPCOMMENT("Allocate RGX firmware memory context");
+               PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate RGX firmware memory context");
                eError = DevmemFwAllocate(psDevInfo,
                                                                sizeof(*psFWMemContext),
                                                                uiFWMemContextMemAllocFlags | PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
@@ -568,15 +572,6 @@ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE   *psDeviceNode,
                                 eError));
                        goto fail_acquire_cpu_addr;
                }
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFWMemContextMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFWMemContext - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-               }
-#endif
 
                /*
                 * Write the new memory context's page catalogue into the firmware memory
@@ -596,7 +591,7 @@ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE    *psDeviceNode,
                /*
                 * Set default values for the rest of the structure.
                 */
-               psFWMemContext->uiPageCatBaseRegID = RGXFW_BIF_INVALID_PCREG;
+               psFWMemContext->uiPageCatBaseRegSet = RGXFW_BIF_INVALID_PCSET;
                psFWMemContext->uiBreakpointAddr = 0;
                psFWMemContext->uiBPHandlerAddr = 0;
                psFWMemContext->uiBreakpointCtl = 0;
@@ -680,10 +675,11 @@ PVRSRV_ERROR RGXRegisterMemoryContext(PVRSRV_DEVICE_NODE  *psDeviceNode,
                              OSGetCurrentClientProcessNameKM(),
                              sizeof(psServerMMUContext->szProcessName));
 
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "New memory context: Process Name: %s PID: %u (0x%08X)",
-                                                                               psServerMMUContext->szProcessName,
-                                                                               psServerMMUContext->uiPID,
-                                                                               psServerMMUContext->uiPID);
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "New memory context: Process Name: %s PID: %u (0x%08X)",
+                                     psServerMMUContext->szProcessName,
+                                     psServerMMUContext->uiPID,
+                                     psServerMMUContext->uiPID);
 
                OSWRLockAcquireWrite(psDevInfo->hMemoryCtxListLock);
                dllist_add_to_tail(&psDevInfo->sMemoryContextList, &psServerMMUContext->sNode);
index 285eca3..7240c96 100644 (file)
@@ -69,6 +69,8 @@ PVRSRV_ERROR PDVFSLimitMaxFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui
        PVRSRV_ERROR                    eError;
        IMG_UINT32                              ui32CmdKCCBSlot;
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        if (!_PDVFSEnabled())
        {
                /* No error message to avoid excessive messages */
@@ -93,7 +95,7 @@ PVRSRV_ERROR PDVFSLimitMaxFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui
                OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
        } END_LOOP_UNTIL_TIMEOUT();
 
-       return PVRSRV_OK;
+       return eError;
 }
 
 PVRSRV_ERROR PDVFSLimitMinFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32MinOPPPoint)
@@ -102,6 +104,8 @@ PVRSRV_ERROR PDVFSLimitMinFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui
        PVRSRV_ERROR                    eError;
        IMG_UINT32                              ui32CmdKCCBSlot;
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        if (!_PDVFSEnabled())
        {
                /* No error message to avoid excessive messages */
@@ -126,7 +130,7 @@ PVRSRV_ERROR PDVFSLimitMinFrequency(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui
                OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
        } END_LOOP_UNTIL_TIMEOUT();
 
-       return PVRSRV_OK;
+       return eError;
 }
 
 
index 600ba94..ef39bea 100644 (file)
@@ -105,6 +105,8 @@ PVRSRV_ERROR PVRSRVRGXAddRegConfigKM(CONNECTION_DATA * psConnection,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        OSLockAcquire(psRegCfg->hLock);
 
        if (psRegCfg->bEnabled)
@@ -134,7 +136,6 @@ PVRSRV_ERROR PVRSRVRGXAddRegConfigKM(CONNECTION_DATA * psConnection,
        eError = RGXScheduleCommand(psDeviceNode->pvDevice,
                                RGXFWIF_DM_GP,
                                &sRegCfgCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
        if (eError != PVRSRV_OK)
        {
@@ -172,6 +173,8 @@ PVRSRV_ERROR PVRSRVRGXClearRegConfigKM(CONNECTION_DATA * psConnection,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        OSLockAcquire(psRegCfg->hLock);
 
        if (psRegCfg->bEnabled)
@@ -189,7 +192,6 @@ PVRSRV_ERROR PVRSRVRGXClearRegConfigKM(CONNECTION_DATA * psConnection,
        eError = RGXScheduleCommand(psDeviceNode->pvDevice,
                                RGXFWIF_DM_GP,
                                &sRegCfgCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
        if (eError != PVRSRV_OK)
        {
@@ -229,6 +231,8 @@ PVRSRV_ERROR PVRSRVRGXEnableRegConfigKM(CONNECTION_DATA * psConnection,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        OSLockAcquire(psRegCfg->hLock);
 
        sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
@@ -237,7 +241,6 @@ PVRSRV_ERROR PVRSRVRGXEnableRegConfigKM(CONNECTION_DATA * psConnection,
        eError = RGXScheduleCommand(psDeviceNode->pvDevice,
                                RGXFWIF_DM_GP,
                                &sRegCfgCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
        if (eError != PVRSRV_OK)
        {
@@ -275,6 +278,8 @@ PVRSRV_ERROR PVRSRVRGXDisableRegConfigKM(CONNECTION_DATA * psConnection,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        OSLockAcquire(psRegCfg->hLock);
 
        sRegCfgCmd.eCmdType = RGXFWIF_KCCB_CMD_REGCONFIG;
@@ -283,7 +288,6 @@ PVRSRV_ERROR PVRSRVRGXDisableRegConfigKM(CONNECTION_DATA * psConnection,
        eError = RGXScheduleCommand(psDeviceNode->pvDevice,
                                RGXFWIF_DM_GP,
                                &sRegCfgCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
        if (eError != PVRSRV_OK)
        {
index 990d7e6..407c0fb 100644 (file)
@@ -164,7 +164,7 @@ PVRSRVTQLoadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
 
        ui32NumPages = (sHeader.ui32SizeFragment / RGX_BIF_PM_PHYSICAL_PAGE_SIZE) + 1;
 
-       PDUMPCOMMENT("Allocate TDM USC PMR Block (Pages %08X)", ui32NumPages);
+       PDUMPCOMMENT(psDeviceNode, "Allocate TDM USC PMR Block (Pages %08X)", ui32NumPages);
 
        eError = PhysmemNewRamBackedPMR(NULL,
                                                                        psDeviceNode,
@@ -182,7 +182,8 @@ PVRSRVTQLoadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
                                                                        "tquscpmr",
                                                                        PVR_SYS_ALLOC_PID,
                                                                        (PMR**)&psDevInfo->hTQUSCSharedMem,
-                                                                       PDUMP_NONE);
+                                                                       PDUMP_NONE,
+                                                                       NULL);
        if (eError != PVRSRV_OK)
        {
                PVR_LOG(("%s: Unexpected error from PhysmemNewRamBackedPMR (%s)",
@@ -213,7 +214,7 @@ PVRSRVTQLoadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
 
        ui32NumPages = (sHeader.ui32SizeClientMem / RGX_BIF_PM_PHYSICAL_PAGE_SIZE) + 1;
 
-       PDUMPCOMMENT("Allocate TDM Client PMR Block (Pages %08X)", ui32NumPages);
+       PDUMPCOMMENT(psDeviceNode, "Allocate TDM Client PMR Block (Pages %08X)", ui32NumPages);
 
        eError = PhysmemNewRamBackedPMR(NULL,
                                                                        psDeviceNode,
@@ -231,7 +232,8 @@ PVRSRVTQLoadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
                                                                        "tqclipmr",
                                                                        PVR_SYS_ALLOC_PID,
                                                                        (PMR**)&psDevInfo->hTQCLISharedMem,
-                                                                       PDUMP_NONE);
+                                                                       PDUMP_NONE,
+                                                                       NULL);
        if (eError != PVRSRV_OK)
        {
                PVR_LOG(("%s: Unexpected error from PhysmemNewRamBackedPMR (%s)",
@@ -291,23 +293,10 @@ PVRSRVTQAcquireShaders(PVRSRV_DEVICE_NODE  * psDeviceNode,
        *ppsCLIPMRMem = psDevInfo->hTQCLISharedMem;
 }
 
-PVRSRV_ERROR
-PVRSRVTQUnloadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
+void PVRSRVTQUnloadShaders(PVRSRV_DEVICE_NODE * psDeviceNode)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       PVRSRV_ERROR eError;
-
-       eError = PMRUnrefPMR(psDevInfo->hTQUSCSharedMem);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
 
-       eError = PMRUnrefPMR(psDevInfo->hTQCLISharedMem);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
-
-       return PVRSRV_OK;
+       (void) PMRUnrefPMR(psDevInfo->hTQUSCSharedMem);
+       (void) PMRUnrefPMR(psDevInfo->hTQCLISharedMem);
 }
index 20db8dd..7676ede 100644 (file)
@@ -77,9 +77,7 @@ PVRSRVTQAcquireShaders(PVRSRV_DEVICE_NODE  *psDeviceNode,
 @Function       PVRSRVTQUnLoadShaders
 @Description    Unref PMR memory.
 @Input          psDeviceNode Device node
-@Return         PVRSRV_ERROR Returns PVRSRV_OK on success.
 */ /**************************************************************************/
-PVRSRV_ERROR
-PVRSRVTQUnloadShaders(PVRSRV_DEVICE_NODE *psDeviceNode);
+void PVRSRVTQUnloadShaders(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 #endif /* RGXSHADER_H */
index 106b7bd..87ca2cf 100644 (file)
@@ -67,6 +67,7 @@ PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
        IMG_HANDLE                  hMemCtxPrivData,
        IMG_UINT32                                      ui32PackedCCBSizeU88,
        IMG_UINT32                  ui32ContextFlags,
+       IMG_UINT64                                      ui64RobustnessAddress,
        RGX_SERVER_TQ_TDM_CONTEXT **ppsTransferContext);
 
 
@@ -86,7 +87,6 @@ PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psT
 PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
        RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext,
        IMG_UINT32                  ui32PDumpFlags,
-       IMG_UINT32                  ui32ClientCacheOpSeqNum,
        IMG_UINT32                  ui32ClientUpdateCount,
        SYNC_PRIMITIVE_BLOCK     ** pauiClientUpdateUFODevVarBlock,
        IMG_UINT32                * paui32ClientUpdateSyncOffset,
index 875411d..584dbf1 100644 (file)
@@ -62,8 +62,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  *****************************************************************************/
 
-static IMG_UINT32 g_ui32ClockSource = PVRSRV_APPHINT_TIMECORRCLOCK;
-
 /*
        AppHint interfaces
 */
@@ -75,6 +73,9 @@ static PVRSRV_ERROR _SetClock(const PVRSRV_DEVICE_NODE *psDeviceNode,
        static __maybe_unused const char* const apszClocks[] = {
                "mono", "mono_raw", "sched"
        };
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       PVR_ASSERT(psDeviceNode->pvDevice != NULL);
 
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
@@ -88,10 +89,10 @@ static PVRSRV_ERROR _SetClock(const PVRSRV_DEVICE_NODE *psDeviceNode,
                       RGXTIMECORR_EVENT_CLOCK_CHANGE);
 
        PVR_DPF((PVR_DBG_WARNING, "Setting time correlation clock from \"%s\" to \"%s\"",
-                       apszClocks[g_ui32ClockSource],
+                       apszClocks[psDevInfo->ui32ClockSource],
                        apszClocks[ui32Value]));
 
-       g_ui32ClockSource = ui32Value;
+       psDevInfo->ui32ClockSource = ui32Value;
 
        RGXTimeCorrBegin((PVRSRV_DEVICE_NODE *) psDeviceNode,
                         RGXTIMECORR_EVENT_CLOCK_CHANGE);
@@ -103,7 +104,10 @@ static PVRSRV_ERROR _GetClock(const PVRSRV_DEVICE_NODE *psDeviceNode,
                               const void *psPrivate,
                               IMG_UINT32 *pui32Value)
 {
-       *pui32Value = g_ui32ClockSource;
+       PVR_ASSERT(psDeviceNode->pvDevice != NULL);
+
+       *pui32Value =
+           ((PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice)->ui32ClockSource;
 
        PVR_UNREFERENCED_PARAMETER(psPrivate);
 
@@ -120,11 +124,11 @@ void RGXTimeCorrInitAppHintCallbacks(const PVRSRV_DEVICE_NODE *psDeviceNode)
        End of AppHint interface
 */
 
-IMG_UINT64 RGXTimeCorrGetClockns64(void)
+IMG_UINT64 RGXTimeCorrGetClockns64(const PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        IMG_UINT64 ui64Clock;
 
-       switch (g_ui32ClockSource) {
+       switch (((PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice)->ui32ClockSource) {
                case RGXTIMECORR_CLOCK_MONO:
                        return ((void) OSClockMonotonicns64(&ui64Clock), ui64Clock);
                case RGXTIMECORR_CLOCK_MONO_RAW:
@@ -137,10 +141,10 @@ IMG_UINT64 RGXTimeCorrGetClockns64(void)
        }
 }
 
-IMG_UINT64 RGXTimeCorrGetClockus64(void)
+IMG_UINT64 RGXTimeCorrGetClockus64(const PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        IMG_UINT32 rem;
-       return OSDivide64r64(RGXTimeCorrGetClockns64(), 1000, &rem);
+       return OSDivide64r64(RGXTimeCorrGetClockns64(psDeviceNode), 1000, &rem);
 }
 
 void RGXGetTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode,
@@ -239,7 +243,7 @@ static void _RGXMakeTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode, RGXTIMECORR_E
        }
 #endif
        psTimeCorr->ui64CRTimeStamp = RGXReadHWTimerReg(psDevInfo);
-       psTimeCorr->ui64OSTimeStamp = RGXTimeCorrGetClockns64();
+       psTimeCorr->ui64OSTimeStamp = RGXTimeCorrGetClockns64(psDeviceNode);
        psTimeCorr->ui32CoreClockSpeed = _RGXGetEstimatedGPUClockSpeed(psDevInfo);
        psTimeCorr->ui64CRDeltaToOSDeltaKNs = RGXTimeCorrGetConversionFactor(psTimeCorr->ui32CoreClockSpeed);
 
@@ -255,7 +259,7 @@ static void _RGXMakeTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode, RGXTIMECORR_E
        }
 
        /* Make sure the values are written to memory before updating the index of the current entry */
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(psTimeCorr);
 
        /* Update the index of the current entry in the timer correlation array */
        psGpuUtilFWCB->ui32TimeCorrSeqCount = ui32NewSeqCount;
@@ -300,7 +304,7 @@ static void _RGXCheckTimeCorrData(PVRSRV_DEVICE_NODE *psDeviceNode,
         * they represent the same current time sampled from different clock sources.
         */
        ui64CRTimeStamp = RGXReadHWTimerReg(psDevInfo);
-       ui64OSTimeStamp = RGXTimeCorrGetClockns64();
+       ui64OSTimeStamp = RGXTimeCorrGetClockns64(psDeviceNode);
 
        if ((ui64OSTimeStamp - psTimeCorr->ui64OSTimeStamp) < (1 << SCALING_FACTOR))
        {
@@ -401,7 +405,7 @@ static void _RGXGPUFreqCalibrationPeriodStart(PVRSRV_DEVICE_NODE *psDeviceNode,
        IMG_UINT32 ui32CoreClockSpeed, ui32Index;
 
        IMG_UINT64 ui64CRTimestamp = RGXReadHWTimerReg(psDevInfo);
-       IMG_UINT64 ui64OSTimestamp = RGXTimeCorrGetClockus64();
+       IMG_UINT64 ui64OSTimestamp = RGXTimeCorrGetClockus64(psDeviceNode);
 
        psGpuDVFSTable->ui64CalibrationCRTimestamp = ui64CRTimestamp;
        psGpuDVFSTable->ui64CalibrationOSTimestamp = ui64OSTimestamp;
@@ -450,7 +454,7 @@ static void _RGXGPUFreqCalibrationPeriodStop(PVRSRV_DEVICE_NODE *psDeviceNode,
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
        IMG_UINT64 ui64CRTimestamp = RGXReadHWTimerReg(psDevInfo);
-       IMG_UINT64 ui64OSTimestamp = RGXTimeCorrGetClockus64();
+       IMG_UINT64 ui64OSTimestamp = RGXTimeCorrGetClockus64(psDeviceNode);
 
        psGpuDVFSTable->ui64CalibrationCRTimediff =
            ui64CRTimestamp - psGpuDVFSTable->ui64CalibrationCRTimestamp;
@@ -579,7 +583,7 @@ void RGXTimeCorrRestartPeriodic(IMG_HANDLE hDevHandle)
        PVRSRV_DEVICE_NODE     *psDeviceNode   = hDevHandle;
        PVRSRV_RGXDEV_INFO     *psDevInfo      = psDeviceNode->pvDevice;
        RGX_GPU_DVFS_TABLE     *psGpuDVFSTable = psDevInfo->psGpuDVFSTable;
-       IMG_UINT64             ui64TimeNow     = RGXTimeCorrGetClockus64();
+       IMG_UINT64             ui64TimeNow     = RGXTimeCorrGetClockus64(psDeviceNode);
        PVRSRV_DEV_POWER_STATE ePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
        PVRSRV_VZ_RETN_IF_MODE(GUEST);
 
@@ -613,9 +617,9 @@ void RGXTimeCorrRestartPeriodic(IMG_HANDLE hDevHandle)
 /*
        RGXTimeCorrGetClockSource
 */
-RGXTIMECORR_CLOCK_TYPE RGXTimeCorrGetClockSource(void)
+RGXTIMECORR_CLOCK_TYPE RGXTimeCorrGetClockSource(const PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       return g_ui32ClockSource;
+       return ((PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice)->ui32ClockSource;
 }
 
 /*
@@ -633,9 +637,8 @@ PVRSRVRGXCurrentTime(CONNECTION_DATA    * psConnection,
                      IMG_UINT64         * pui64Time)
 {
        PVR_UNREFERENCED_PARAMETER(psConnection);
-       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 
-       *pui64Time = RGXTimeCorrGetClockns64();
+       *pui64Time = RGXTimeCorrGetClockns64(psDeviceNode);
 
        return PVRSRV_OK;
 }
index 135665c..e1cfff9 100644 (file)
@@ -175,10 +175,11 @@ void RGXTimeCorrRestartPeriodic(IMG_HANDLE hDevHandle);
 
  @Description Returns value of currently selected clock (in ns).
 
+ @Input       psDeviceNode : RGX Device Node
  @Return      clock value from currently selected clock source
 
 ******************************************************************************/
-IMG_UINT64 RGXTimeCorrGetClockns64(void);
+IMG_UINT64 RGXTimeCorrGetClockns64(const PVRSRV_DEVICE_NODE *psDeviceNode);
 
 /*!
 ******************************************************************************
@@ -187,10 +188,11 @@ IMG_UINT64 RGXTimeCorrGetClockns64(void);
 
  @Description Returns value of currently selected clock (in us).
 
+ @Input       psDeviceNode : RGX Device Node
  @Return      clock value from currently selected clock source
 
 ******************************************************************************/
-IMG_UINT64 RGXTimeCorrGetClockus64(void);
+IMG_UINT64 RGXTimeCorrGetClockus64(const PVRSRV_DEVICE_NODE *psDeviceNode);
 
 /*!
 ******************************************************************************
@@ -199,10 +201,11 @@ IMG_UINT64 RGXTimeCorrGetClockus64(void);
 
  @Description Returns currently selected clock source
 
+ @Input       psDeviceNode : RGX Device Node
  @Return      clock source type
 
 ******************************************************************************/
-RGXTIMECORR_CLOCK_TYPE RGXTimeCorrGetClockSource(void);
+RGXTIMECORR_CLOCK_TYPE RGXTimeCorrGetClockSource(const PVRSRV_DEVICE_NODE *psDeviceNode);
 
 /*!
 ******************************************************************************
index e65571b..d5d11bf 100644 (file)
@@ -72,6 +72,7 @@ PVRSRVRGXBeginTimerQueryKM(CONNECTION_DATA    * psConnection,
        /* clear the stamps, in case there is no Kick */
        psDevInfo->pui64StartTimeById[ui32QueryId] = 0UL;
        psDevInfo->pui64EndTimeById[ui32QueryId]   = 0UL;
+       OSWriteMemoryBarrier(&psDevInfo->pui64EndTimeById[ui32QueryId]);
 
        /* save of the active query index */
        psDevInfo->ui32ActiveQueryId = ui32QueryId;
index f27babc..866fd01 100644 (file)
@@ -75,7 +75,9 @@ PVRSRV_ERROR RGXSetAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
        IMG_UINT32 ui32State)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
+#if !defined(NO_HARDWARE)
        PVRSRV_RGXDEV_INFO *psDevInfo;
+#endif
 
        PVR_UNREFERENCED_PARAMETER(pvPrivateData);
 
@@ -84,21 +86,19 @@ PVRSRV_ERROR RGXSetAPMState(const PVRSRV_DEVICE_NODE *psDeviceNode,
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
-       psDevInfo = psDeviceNode->pvDevice;
-
-       if (RGX_ACTIVEPM_FORCE_OFF != ui32State
-               || !psDevInfo->pvAPMISRData)
+       if (RGX_ACTIVEPM_FORCE_OFF != ui32State)
        {
                return PVRSRV_ERROR_NOT_SUPPORTED;
        }
 
 #if !defined(NO_HARDWARE)
-       eError = OSUninstallMISR(psDevInfo->pvAPMISRData);
-       if (PVRSRV_OK == eError)
+       psDevInfo = psDeviceNode->pvDevice;
+
+       if (psDevInfo->pvAPMISRData)
        {
                psDevInfo->eActivePMConf = RGX_ACTIVEPM_FORCE_OFF;
                psDevInfo->pvAPMISRData = NULL;
-               eError = PVRSRVSetDeviceDefaultPowerState((const PPVRSRV_DEVICE_NODE)psDeviceNode,
+               eError = PVRSRVSetDeviceDefaultPowerState((PPVRSRV_DEVICE_NODE)psDeviceNode,
                                                          PVRSRV_DEV_POWER_STATE_ON);
        }
 #endif
index e0bd055..02e0683 100644 (file)
@@ -317,7 +317,7 @@ PVRSRV_ERROR WorkEstPrepare(PVRSRV_RGXDEV_INFO        *psDevInfo,
        psDevInfo->ui32ReturnDataWO = (ui32ReturnDataWO + 1) & RETURN_DATA_ARRAY_WRAP_MASK;
 
        /* Index for the return data passed to/from the firmware. */
-       psWorkEstKickData->ui64ReturnDataIndex = ui32ReturnDataWO;
+       psWorkEstKickData->ui16ReturnDataIndex = ui32ReturnDataWO;
        if (ui64DeadlineInus > ui64CurrentTime)
        {
                /* Rounding is done to reduce multiple deadlines with minor spread flooding the fw workload array. */
@@ -360,9 +360,15 @@ PVRSRV_ERROR WorkEstPrepare(PVRSRV_RGXDEV_INFO        *psDevInfo,
        if (pui64CyclePrediction != NULL)
        {
                /* Cycle prediction is available, store this prediction */
-               psWorkEstKickData->ui64CyclesPrediction = *pui64CyclePrediction;
+               psWorkEstKickData->ui32CyclesPrediction = *pui64CyclePrediction;
 
 #if defined(PVRSRV_NEED_PVR_DPF)
+               if (*pui64CyclePrediction >= IMG_UINT32_MAX)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "Workload estimate overflow:"
+                                       " %" IMG_UINT64_FMTSPEC, *pui64CyclePrediction));
+               }
+
                switch (eDMCmdType)
                {
                        case RGXFWIF_CCB_CMD_TYPE_GEOM:
@@ -396,7 +402,7 @@ PVRSRV_ERROR WorkEstPrepare(PVRSRV_RGXDEV_INFO        *psDevInfo,
        else
        {
                /* There is no prediction */
-               psWorkEstKickData->ui64CyclesPrediction = 0;
+               psWorkEstKickData->ui32CyclesPrediction = 0;
        }
 
        return PVRSRV_OK;
@@ -424,19 +430,19 @@ PVRSRV_ERROR WorkEstRetire(PVRSRV_RGXDEV_INFO *psDevInfo,
                                "WorkEstRetire: Missing return command",
                                PVRSRV_ERROR_INVALID_PARAMS);
 
-       if (psReturnCmd->ui64ReturnDataIndex >= RETURN_DATA_ARRAY_SIZE)
+       if (psReturnCmd->ui16ReturnDataIndex >= RETURN_DATA_ARRAY_SIZE)
        {
                PVR_DPF((PVR_DBG_ERROR, "WorkEstRetire: Handle reference out-of-bounds:"
-                       " %" IMG_UINT64_FMTSPEC " >= %" IMG_UINT64_FMTSPEC,
-                       psReturnCmd->ui64ReturnDataIndex,
-                       (IMG_UINT64) RETURN_DATA_ARRAY_SIZE));
+                       " %u >= %u",
+                       psReturnCmd->ui16ReturnDataIndex,
+                       RETURN_DATA_ARRAY_SIZE));
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
        OSLockAcquire(psDevInfo->hWorkEstLock);
 
        /* Retrieve/validate the return data from this completed workload */
-       psReturnData = &psDevInfo->asReturnData[psReturnCmd->ui64ReturnDataIndex];
+       psReturnData = &psDevInfo->asReturnData[psReturnCmd->ui16ReturnDataIndex];
        psWorkloadCharacteristics = &psReturnData->sWorkloadCharacteristics;
        psWorkEstHostData = psReturnData->psWorkEstHostData;
        PVR_LOG_GOTO_IF_FALSE(psWorkEstHostData,
@@ -479,7 +485,7 @@ PVRSRV_ERROR WorkEstRetire(PVRSRV_RGXDEV_INFO *psDevInfo,
        {
                /* There is no existing entry for this workload characteristics,
                 * store it */
-               paui64WorkloadHashData[ui32HashArrayWO] = psReturnCmd->ui64CyclesTaken;
+               paui64WorkloadHashData[ui32HashArrayWO] = psReturnCmd->ui32CyclesTaken;
                pasWorkloadHashKeys[ui32HashArrayWO] = *psWorkloadCharacteristics;
        }
        else
@@ -487,7 +493,7 @@ PVRSRV_ERROR WorkEstRetire(PVRSRV_RGXDEV_INFO *psDevInfo,
                /* Found prior entry for workload characteristics, average with
                 * completed; also reset the old value to 0 so it is known to be
                 * invalid */
-               paui64WorkloadHashData[ui32HashArrayWO] = (*pui64CyclesTaken + psReturnCmd->ui64CyclesTaken)/2;
+               paui64WorkloadHashData[ui32HashArrayWO] = (*pui64CyclesTaken + psReturnCmd->ui32CyclesTaken)/2;
                pasWorkloadHashKeys[ui32HashArrayWO] = *psWorkloadCharacteristics;
                *pui64CyclesTaken = 0;
        }
index 4704753..952940f 100644 (file)
@@ -63,9 +63,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "sync_internal.h"
 #include "sync.h"
 #include "rgx_memallocflags.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #if defined(SUPPORT_BUFFER_SYNC)
 #include "pvr_buffer_sync.h"
@@ -125,9 +122,6 @@ PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                        *psConnection,
                                                                                         IMG_UINT32                                     ui32MaxDeadlineMS,
                                                                                         RGX_SERVER_COMPUTE_CONTEXT     **ppsComputeContext)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
        DEVMEM_MEMDESC                          *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
        RGX_SERVER_COMPUTE_CONTEXT      *psComputeContext;
@@ -176,7 +170,7 @@ PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                        *psConnection,
                Allocate device memory for the firmware GPU context suspend state.
                Note: the FW reads/writes the state to memory by accessing the GPU register interface.
        */
-       PDUMPCOMMENT("Allocate RGX firmware compute context suspend state");
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware compute context suspend state");
 
        eError = DevmemFwAllocate(psDevInfo,
                                                          sizeof(RGXFWIF_COMPUTECTX_STATE),
@@ -215,7 +209,8 @@ PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                        *psConnection,
                }
 
                /* Copy the Framework client data into the framework buffer */
-               eError = PVRSRVRGXFrameworkCopyCommand(psComputeContext->psFWFrameworkMemDesc,
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psComputeContext->psFWFrameworkMemDesc,
                                pbyFrameworkCommand,
                                ui32FrameworkCommandSize);
                if (eError != PVRSRV_OK)
@@ -263,15 +258,6 @@ PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                       *psConnection,
 
        OSDeviceMemCopy(&psFWComputeContext->sStaticComputeContextState, pStaticComputecontextState, ui32StaticComputecontextStateSize);
        DevmemPDumpLoadMem(psComputeContext->psFWComputeContextMemDesc, 0, sizeof(RGXFWIF_FWCOMPUTECONTEXT), PDUMP_FLAGS_CONTINUOUS);
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psComputeContext->psFWComputeContextMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFWComputeContext - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psComputeContext->psFWComputeContextMemDesc);
 
 #if defined(SUPPORT_BUFFER_SYNC)
@@ -327,11 +313,6 @@ fail_fwcomputecontext:
 
 PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
 {
-#if defined(SUPPORT_WORKLOAD_ESTIMATION)
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-#endif
        PVRSRV_ERROR                            eError = PVRSRV_OK;
        PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
@@ -378,15 +359,6 @@ PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComp
                                PVRSRVGetErrorString(eError)));
                return eError;
        }
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psComputeContext->psFWComputeContextMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFWComputeContext - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
 
        ui32WorkEstCCBSubmitted = psFWComputeContext->ui32WorkEstCCBSubmitted;
 
@@ -430,7 +402,6 @@ PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComp
 
 
 PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT     *psComputeContext,
-                                                               IMG_UINT32                                      ui32ClientCacheOpSeqNum,
                                                                IMG_UINT32                                      ui32ClientUpdateCount,
                                                                SYNC_PRIMITIVE_BLOCK            **pauiClientUpdateUFODevVarBlock,
                                                                IMG_UINT32                                      *paui32ClientUpdateSyncOffset,
@@ -862,7 +833,8 @@ PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT  *psComputeContext,
                                  &pPostAddr,
                                  &pRMWUFOAddr);
 
-       RGXCmdHelperInitCmdCCB(psClientCCB,
+       RGXCmdHelperInitCmdCCB(psDevInfo,
+                              psClientCCB,
                               0,
                               ui32IntClientFenceCount,
                               pauiIntFenceUFOAddress,
@@ -987,7 +959,6 @@ PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT  *psComputeContext,
                eError2 = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
                                                                        RGXFWIF_DM_CDM,
                                                                        &sCmpKCCBCmd,
-                                                                       ui32ClientCacheOpSeqNum,
                                                                        ui32PDumpFlags);
                if (eError2 != PVRSRV_ERROR_RETRY)
                {
@@ -1125,7 +1096,8 @@ PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeCo
        PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
 
 #if defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit Compute flush");
+       PDUMPCOMMENTWITHFLAGS(psComputeContext->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Submit Compute flush");
 #endif
        sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
        sFlushCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_FALSE;
@@ -1139,7 +1111,6 @@ PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeCo
                eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                                        RGXFWIF_DM_CDM,
                                                                        &sFlushCmd,
-                                                                       0,
                                                                        PDUMP_FLAGS_CONTINUOUS,
                                                                        &ui32kCCBCommandSlot);
                /* Iterate if we hit a PVRSRV_ERROR_KERNEL_CCB_FULL error */
@@ -1212,7 +1183,6 @@ PVRSRV_ERROR PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(RGX_SERVER_COMPUTE_CONTEX
                        eError = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
                                                                                RGXFWIF_DM_CDM,
                                                                                &sKCCBCmd,
-                                                                               0,
                                                                                PDUMP_FLAGS_NONE);
                        if (eError != PVRSRV_ERROR_RETRY)
                        {
@@ -1272,17 +1242,18 @@ PVRSRV_ERROR PVRSRVRGXSetComputeContextPropertyKM(RGX_SERVER_COMPUTE_CONTEXT *ps
                                                   IMG_UINT64 ui64Input,
                                                   IMG_UINT64 *pui64Output)
 {
-       PVRSRV_ERROR eError;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (eContextProperty)
        {
                case RGX_CONTEXT_PROPERTY_FLAGS:
                {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
                        OSLockAcquire(psComputeContext->hLock);
                        eError = FWCommonContextSetFlags(psComputeContext->psServerCommonContext,
-                                                        (IMG_UINT32)ui64Input);
+                                                        ui32ContextFlags);
                        OSLockRelease(psComputeContext->hLock);
-                       PVR_LOG_IF_ERROR(eError, "FWCommonContextSetFlags");
                        break;
                }
 
index ebe2c3f..0ac6e4a 100644 (file)
@@ -102,7 +102,6 @@ PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComp
  @Return   PVRSRV_ERROR
 ******************************************************************************/
 PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT     *psComputeContext,
-                                                               IMG_UINT32                                      ui32ClientCacheOpSeqNum,
                                                                IMG_UINT32                                      ui32ClientUpdateCount,
                                                                SYNC_PRIMITIVE_BLOCK            **pauiClientUpdateUFODevVarBlock,
                                                                IMG_UINT32                                      *paui32ClientUpdateSyncOffset,
index 1bb8068..86dcb9e 100644 (file)
@@ -61,7 +61,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv.h"
 #include "services_km.h"
 
-#include "rgxfwimageutils.h"
 #include "devicemem.h"
 #include "devicemem_pdump.h"
 #include "devicemem_utils.h"
@@ -95,7 +94,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DD_SUMMARY_INDENT  ""
 #define DD_NORMAL_INDENT   "    "
 
-#define RGX_DEBUG_STR_SIZE             (150U)
+#define RGX_DEBUG_STR_SIZE                     (150U)
 #define MAX_FW_DESCRIPTION_LENGTH      (500U)
 
 #define RGX_CR_BIF_CAT_BASE0                              (0x1200U)
@@ -178,9 +177,6 @@ static const IMG_FLAGS2DESC asCswOpts2Description[] =
        {RGXFWIF_INICFG_CTXSWITCH_PROFILE_NODELAY, " No Delay CSW profile;"},
        {RGXFWIF_INICFG_CTXSWITCH_MODE_RAND, " Random Csw enabled;"},
        {RGXFWIF_INICFG_CTXSWITCH_SRESET_EN, " SoftReset;"},
-       {RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX, " VDM CS INDEX mode;"},
-       {RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE, " VDM CS INSTANCE mode;"},
-       {RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST, " VDM CS LIST mode;"},
 };
 
 static const IMG_FLAGS2DESC asMisc2Description[] =
@@ -190,11 +186,9 @@ static const IMG_FLAGS2DESC asMisc2Description[] =
        {RGXFWIF_INICFG_FBCDC_V3_1_EN, " FBCDCv3.1;"},
        {RGXFWIF_INICFG_CHECK_MLIST_EN, " Check MList;"},
        {RGXFWIF_INICFG_DISABLE_CLKGATING_EN, " ClockGating Off;"},
-       {RGXFWIF_INICFG_POLL_COUNTERS_EN, " Poll Counters;"},
        {RGXFWIF_INICFG_REGCONFIG_EN, " Register Config;"},
        {RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY, " Assert on OOM;"},
        {RGXFWIF_INICFG_HWP_DISABLE_FILTER, " HWP Filter Off;"},
-       {RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN, " Custom PerfTimer;"},
        {RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN, " CDM Random kill;"},
        {RGXFWIF_INICFG_DISABLE_DM_OVERLAP, " DM Overlap Off;"},
        {RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER, " Assert on HWR;"},
@@ -247,6 +241,39 @@ static const IMG_FLAGS2DESC asDmState2Description[] =
                {RGXFWIF_DM_STATE_GPU_ECC_HWR, " GPU ECC hwr;"},
 };
 
+const IMG_CHAR * const gapszMipsPermissionPTFlags[4] =
+{
+       "    ",
+       "XI  ",
+       "RI  ",
+       "RIXI"
+};
+
+const IMG_CHAR * const gapszMipsCoherencyPTFlags[8] =
+{
+       "C",
+       "C",
+       " ",
+       "C",
+       "C",
+       "C",
+       "C",
+       " "
+};
+
+const IMG_CHAR * const gapszMipsDirtyGlobalValidPTFlags[8] =
+{
+       "   ",
+       "  G",
+       " V ",
+       " VG",
+       "D  ",
+       "D G",
+       "DV ",
+       "DVG"
+};
+
+#if !defined(SUPPORT_TRUSTED_DEVICE)
 #if !defined(NO_HARDWARE)
 /* Translation of MIPS exception encoding */
 typedef struct _MIPS_EXCEPTION_ENCODING_
@@ -305,6 +332,7 @@ static IMG_CHAR const *_GetMIPSExcString(IMG_UINT32 ui32ExcCode)
        return apsMIPSExcCodes[ui32ExcCode].pszStr;
 }
 #endif
+#endif /* !defined(SUPPORT_TRUSTED_DEVICE) */
 
 typedef struct _RGXMIPSFW_C0_DEBUG_TBL_ENTRY_
 {
@@ -312,6 +340,7 @@ typedef struct _RGXMIPSFW_C0_DEBUG_TBL_ENTRY_
     const IMG_CHAR * pszExplanation;
 } RGXMIPSFW_C0_DEBUG_TBL_ENTRY;
 
+#if !defined(SUPPORT_TRUSTED_DEVICE)
 #if !defined(NO_HARDWARE)
 static const RGXMIPSFW_C0_DEBUG_TBL_ENTRY sMIPS_C0_DebugTable[] =
 {
@@ -329,9 +358,10 @@ static const RGXMIPSFW_C0_DEBUG_TBL_ENTRY sMIPS_C0_DebugTable[] =
     { RGXMIPSFW_C0_DEBUG_CACHEEP,  "Imprecise Cache Error pending" },
     { RGXMIPSFW_C0_DEBUG_MCHECKP,  "Imprecise Machine Check exception pending" },
     { RGXMIPSFW_C0_DEBUG_IBUSEP,   "Instruction fetch Bus Error exception pending" },
-    { RGXMIPSFW_C0_DEBUG_DBD,      "Debug exception occurred in branch delay slot" }
+    { (IMG_UINT32)RGXMIPSFW_C0_DEBUG_DBD,      "Debug exception occurred in branch delay slot" }
 };
 #endif
+#endif /* !defined(SUPPORT_TRUSTED_DEVICE) */
 
 static const IMG_CHAR * const apszFwOsStateName[RGXFW_CONNECTION_FW_STATE_COUNT] =
 {
@@ -359,7 +389,7 @@ RGXPollMetaRegThroughSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegOffset,
 
        do
        {
-               eError = RGXReadWithSP(psDevInfo, ui32RegOffset, &ui32RegValue);
+               eError = RGXReadFWModuleAddr(psDevInfo, ui32RegOffset, &ui32RegValue);
                if (eError != PVRSRV_OK)
                {
                        return eError;
@@ -382,9 +412,9 @@ RGXReadMetaCoreReg(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegAddr, IMG_UI
        PVR_LOG_RETURN_IF_ERROR(eError, "RGXPollMetaRegThroughSP");
 
        /* Set the reg we are interested in reading */
-       eError = RGXWriteWithSP(psDevInfo, META_CR_TXUXXRXRQ_OFFSET,
+       eError = RGXWriteFWModuleAddr(psDevInfo, META_CR_TXUXXRXRQ_OFFSET,
                                ui32RegAddr | META_CR_TXUXXRXRQ_RDnWR_BIT);
-       PVR_LOG_RETURN_IF_ERROR(eError, "RGXWriteWithSP");
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXWriteFWModuleAddr");
 
        /* Core Read Done? */
        eError = RGXPollMetaRegThroughSP(psDevInfo,
@@ -394,34 +424,11 @@ RGXReadMetaCoreReg(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegAddr, IMG_UI
        PVR_LOG_RETURN_IF_ERROR(eError, "RGXPollMetaRegThroughSP");
 
        /* Read the value */
-       return RGXReadWithSP(psDevInfo, META_CR_TXUXXRXDT_OFFSET, pui32RegVal);
-}
-
-PVRSRV_ERROR
-RGXReadWithSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 *pui32Value)
-{
-       PVRSRV_ERROR eError = RGXReadMETAAddr(psDevInfo, ui32FWAddr, pui32Value);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: %s", __func__, PVRSRVGetErrorString(eError)));
-       }
-
-       return eError;
-}
-
-PVRSRV_ERROR
-RGXWriteWithSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 ui32Value)
-{
-       PVRSRV_ERROR eError = RGXWriteMETAAddr(psDevInfo, ui32FWAddr, ui32Value);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: %s", __func__, PVRSRVGetErrorString(eError)));
-       }
-       return eError;
+       return RGXReadFWModuleAddr(psDevInfo, META_CR_TXUXXRXDT_OFFSET, pui32RegVal);
 }
 
 #if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
-static PVRSRV_ERROR _ValidateWithSP(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+static PVRSRV_ERROR _ValidateWithFWModule(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                void *pvDumpDebugFile,
                                                PVRSRV_RGXDEV_INFO *psDevInfo,
                                                RGXFWIF_DEV_VIRTADDR *psFWAddr,
@@ -430,197 +437,77 @@ static PVRSRV_ERROR _ValidateWithSP(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                const IMG_CHAR *pszDesc,
                                                IMG_UINT32 ui32StartOffset)
 {
-       PVRSRV_ERROR eError;
-       IMG_UINT32 ui32Value, i;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32Value = 0;
        IMG_UINT32 ui32FWCodeDevVAAddr = psFWAddr->ui32Addr + ui32StartOffset;
        IMG_UINT32 *pui32FWCode = (IMG_PUINT32) ((IMG_PBYTE)pvHostCodeAddr + ui32StartOffset);
+       IMG_UINT32 i;
 
-       ui32MaxLen -= ui32StartOffset;
-       ui32MaxLen /= sizeof(IMG_UINT32); /* Byte -> 32 bit words */
-
-       for (i = 0; i < ui32MaxLen; i++)
+#if defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
-               eError = RGXReadMETAAddr(psDevInfo, ui32FWCodeDevVAAddr, &ui32Value);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: %s", __func__, PVRSRVGetErrorString(eError)));
-                       return eError;
-               }
-
-               PVR_DPF((PVR_DBG_VERBOSE, "0x%x: CPU 0x%08x, FW 0x%08x", i * 4, pui32FWCode[i], ui32Value));
-
-               if (pui32FWCode[i] != ui32Value)
-               {
-                       PVR_DUMPDEBUG_LOG("_ValidateWithSP: Mismatch while validating %s at offset 0x%x: CPU 0x%08x (%p), FW 0x%08x (%x)",
-                                pszDesc,
-                                (i * 4) + ui32StartOffset, pui32FWCode[i], pui32FWCode, ui32Value, ui32FWCodeDevVAAddr);
-                       return PVRSRV_ERROR_FW_IMAGE_MISMATCH;
-               }
-
-               ui32FWCodeDevVAAddr += 4;
+               return PVRSRV_OK;
        }
-
-       PVR_DUMPDEBUG_LOG("Match between Host and Meta view of the %s", pszDesc);
-       return PVRSRV_OK;
-}
-
-#if !defined(EMULATOR)
-static PVRSRV_ERROR _ValidateWithDM(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                                               void *pvDumpDebugFile,
-                                               PVRSRV_RGXDEV_INFO *psDevInfo,
-                                               RGXFWIF_DEV_VIRTADDR *psFWAddr,
-                                               void *pvHostCodeAddr,
-                                               IMG_UINT32 ui32MaxLen,
-                                               const IMG_CHAR *pszDesc,
-                                               IMG_UINT32 ui32StartOffset)
-{
-       PVRSRV_ERROR eError;
-       IMG_UINT32 ui32Value, i;
-       IMG_UINT32 ui32FWCodeDevVAAddr = psFWAddr->ui32Addr + ui32StartOffset;
-       IMG_UINT32 *pui32FWCode = IMG_OFFSET_ADDR(pvHostCodeAddr, ui32StartOffset);
+#endif
 
        ui32MaxLen -= ui32StartOffset;
        ui32MaxLen /= sizeof(IMG_UINT32); /* Byte -> 32 bit words */
 
        for (i = 0; i < ui32MaxLen; i++)
        {
-               eError = RGXRiscvReadMem(psDevInfo, ui32FWCodeDevVAAddr, &ui32Value);
+               eError = RGXReadFWModuleAddr(psDevInfo, ui32FWCodeDevVAAddr, &ui32Value);
                if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR, "%s: %s", __func__, PVRSRVGetErrorString(eError)));
                        return eError;
                }
 
-               PVR_DPF((PVR_DBG_VERBOSE, "0x%x: CPU 0x%08x, FW 0x%08x", i * 4, pui32FWCode[i], ui32Value));
-
-               if (pui32FWCode[i] != ui32Value)
+#if defined(EMULATOR)
+               if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+#endif
                {
-                       PVR_DUMPDEBUG_LOG("%s: Mismatch while validating %s at offset 0x%x: CPU 0x%08x (0x%p), FW 0x%08x (0x%x)",
-                                __func__, pszDesc,
-                                (i * 4) + ui32StartOffset, pui32FWCode[i], pui32FWCode, ui32Value, ui32FWCodeDevVAAddr);
+                       PVR_DPF((PVR_DBG_VERBOSE, "0x%x: CPU 0x%08x, FW 0x%08x", i * 4, pui32FWCode[i], ui32Value));
 
-                       return PVRSRV_ERROR_FW_IMAGE_MISMATCH;
+                       if (pui32FWCode[i] != ui32Value)
+                       {
+                               PVR_DUMPDEBUG_LOG("%s: Mismatch while validating %s at offset 0x%x: CPU 0x%08x (%p), FW 0x%08x (%x)",
+                                        __func__, pszDesc,
+                                        (i * 4) + ui32StartOffset, pui32FWCode[i], pui32FWCode, ui32Value, ui32FWCodeDevVAAddr);
+                               return PVRSRV_ERROR_FW_IMAGE_MISMATCH;
+                       }
                }
 
                ui32FWCodeDevVAAddr += 4;
        }
 
-       PVR_DUMPDEBUG_LOG("Match between Host and RISC-V view of the %s", pszDesc);
+       PVR_DUMPDEBUG_LOG("Match between Host and Firmware view of the %s", pszDesc);
        return PVRSRV_OK;
 }
 #endif
-#endif
 
-#if !defined(NO_HARDWARE)
-static PVRSRV_ERROR _ValidateFWImageForMIPS(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+static PVRSRV_ERROR _ValidateFWImage(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                void *pvDumpDebugFile,
-                                               PVRSRV_RGXDEV_INFO *psDevInfo,
-                                               char *pszFormat)
+                                               PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#if !defined(SUPPORT_TRUSTED_DEVICE)
+#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
        PVRSRV_ERROR eError;
-       IMG_UINT32 *pui32HostFWCode = NULL;
+       IMG_UINT32 *pui32HostFWCode = NULL, *pui32HostFWCoremem = NULL;
        OS_FW_IMAGE *psRGXFW = NULL;
        const IMG_BYTE *pbRGXFirmware = NULL;
        IMG_UINT32 *pui32CodeMemoryPointer;
+       RGXFWIF_DEV_VIRTADDR sFWAddr;
+       IMG_UINT32 ui32StartOffset = 0;
        RGX_LAYER_PARAMS sLayerParams;
        sLayerParams.psDevInfo = psDevInfo;
 
-       /* Load FW from system for code verification */
-       pui32HostFWCode = OSAllocZMem(psDevInfo->ui32FWCodeSizeInBytes);
-       if (pui32HostFWCode == NULL)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Failed in allocating memory for FW code. "
-                               "So skipping FW code verification",
-                               __func__));
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       /* Load FW image */
-       eError = RGXLoadAndGetFWData(psDevInfo->psDeviceNode, &psRGXFW, &pbRGXFirmware);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to load FW image file (%s).",
-                        __func__, PVRSRVGetErrorString(eError)));
-               eError = PVRSRV_ERROR_INVALID_PARAMS;
-               goto cleanup_initfw;
-       }
-
-       eError = ProcessELFCommandStream(&sLayerParams, pbRGXFirmware, pui32HostFWCode, NULL, NULL, NULL);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed in parsing FW image file.", __func__));
-               goto cleanup_initfw;
-       }
-
-       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc, (void **)&pui32CodeMemoryPointer);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Error in acquiring MIPS FW code memory area (%s)",
-                               __func__,
-                               PVRSRVGetErrorString(eError)));
-               goto cleanup_initfw;
-       }
-
-       if (OSMemCmp(pui32HostFWCode, pui32CodeMemoryPointer, psDevInfo->ui32FWCodeSizeInBytes) == 0)
-       {
-               PVR_DUMPDEBUG_LOG("%sMatch between Host and MIPS views of the FW code", pszFormat);
-       }
-       else
-       {
-               IMG_UINT32 ui32Count = 10; /* Show only the first 10 mismatches */
-               IMG_UINT32 ui32Offset;
-
-               PVR_DUMPDEBUG_LOG("%sMismatch between Host and MIPS views of the FW code", pszFormat);
-               for (ui32Offset = 0; (ui32Offset*4 < psDevInfo->ui32FWCodeSizeInBytes) || (ui32Count == 0); ui32Offset++)
-               {
-                       if (pui32HostFWCode[ui32Offset] != pui32CodeMemoryPointer[ui32Offset])
-                       {
-                               PVR_DUMPDEBUG_LOG("%s   At %d bytes, code should be 0x%x but it is instead 0x%x",
-                                  pszFormat, ui32Offset*4, pui32HostFWCode[ui32Offset], pui32CodeMemoryPointer[ui32Offset]);
-                               ui32Count--;
-                       }
-               }
-       }
-
-       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
-
-cleanup_initfw:
-       if (psRGXFW)
-       {
-               OSUnloadFirmware(psRGXFW);
-       }
-
-       if (pui32HostFWCode)
+#if defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
-               OSFreeMem(pui32HostFWCode);
+               PVR_DUMPDEBUG_LOG("Validation of RISC-V FW code is disabled on emulator");
+               return PVRSRV_OK;
        }
-       return eError;
-#else
-       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-       PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
-       PVR_UNREFERENCED_PARAMETER(psDevInfo);
-       PVR_UNREFERENCED_PARAMETER(pszFormat);
-       return PVRSRV_OK;
-#endif
-}
 #endif
 
-static PVRSRV_ERROR _ValidateFWImageForMETA(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                                               void *pvDumpDebugFile,
-                                               PVRSRV_RGXDEV_INFO *psDevInfo)
-{
-#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
-       IMG_UINT32 *pui32HostFWCode = NULL, *pui32HostFWCoremem = NULL;
-       OS_FW_IMAGE *psRGXFW = NULL;
-       const IMG_BYTE *pbRGXFirmware = NULL;
-       RGXFWIF_DEV_VIRTADDR sFWAddr;
-       PVRSRV_ERROR eError;
-       RGX_LAYER_PARAMS sLayerParams;
-       sLayerParams.psDevInfo = psDevInfo;
-
        if (psDevInfo->pvRegsBaseKM == NULL)
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: RGX registers not mapped yet!", __func__));
@@ -662,150 +549,116 @@ static PVRSRV_ERROR _ValidateFWImageForMETA(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugP
                goto cleanup_initfw;
        }
 
-       eError = ProcessLDRCommandStream(&sLayerParams, pbRGXFirmware,
-                                       (void*) pui32HostFWCode, NULL,
-                                       (void*) pui32HostFWCoremem, NULL, NULL);
-       if (eError != PVRSRV_OK)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed in parsing FW image file.", __func__));
-               goto cleanup_initfw;
+               eError = ProcessLDRCommandStream(&sLayerParams, pbRGXFirmware,
+                                               (void*) pui32HostFWCode, NULL,
+                                               (void*) pui32HostFWCoremem, NULL, NULL);
        }
-
-       /* starting checking after BOOT LOADER config */
-       sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
-       eError = _ValidateWithSP(pfnDumpDebugPrintf, pvDumpDebugFile,
-                                       psDevInfo, &sFWAddr,
-                                       pui32HostFWCode, psDevInfo->ui32FWCodeSizeInBytes,
-                                       "FW code", RGXFW_MAX_BOOTLDR_OFFSET);
-       if (eError != PVRSRV_OK)
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
-               goto cleanup_initfw;
+               eError = ProcessELFCommandStream(&sLayerParams, pbRGXFirmware,
+                                                pui32HostFWCode, NULL,
+                                                NULL, NULL);
        }
-
-       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
-               sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
-
-               eError = _ValidateWithSP(pfnDumpDebugPrintf, pvDumpDebugFile,
-                                               psDevInfo, &sFWAddr,
-                                               pui32HostFWCoremem, psDevInfo->ui32FWCorememCodeSizeInBytes,
-                                               "FW coremem code", 0);
+               eError = ProcessELFCommandStream(&sLayerParams, pbRGXFirmware,
+                                                pui32HostFWCode, NULL,
+                                                pui32HostFWCoremem, NULL);
        }
 
-cleanup_initfw:
-       if (psRGXFW)
-       {
-               OSUnloadFirmware(psRGXFW);
-       }
-
-       if (pui32HostFWCoremem)
-       {
-               OSFreeMem(pui32HostFWCoremem);
-       }
-freeHostFWCode:
-       if (pui32HostFWCode)
-       {
-               OSFreeMem(pui32HostFWCode);
-       }
-       return eError;
-#else
-       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-       PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
-       PVR_UNREFERENCED_PARAMETER(psDevInfo);
-       return PVRSRV_OK;
-#endif
-}
-
-static PVRSRV_ERROR _ValidateFWImageForRISCV(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                                               void *pvDumpDebugFile,
-                                               PVRSRV_RGXDEV_INFO *psDevInfo)
-{
-#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE) && !defined(EMULATOR)
-       IMG_UINT32 *pui32HostFWCode = NULL, *pui32HostFWCoremem = NULL;
-       OS_FW_IMAGE *psRGXFW = NULL;
-       const IMG_BYTE *pbRGXFirmware = NULL;
-       RGXFWIF_DEV_VIRTADDR sFWAddr;
-       PVRSRV_ERROR eError;
-       RGX_LAYER_PARAMS sLayerParams;
-       sLayerParams.psDevInfo = psDevInfo;
-
-       if (psDevInfo->pvRegsBaseKM == NULL)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: RGX registers not mapped yet!", __func__));
-               return PVRSRV_ERROR_BAD_MAPPING;
-       }
-
-       /* Load FW from system for code verification */
-       pui32HostFWCode = OSAllocZMem(psDevInfo->ui32FWCodeSizeInBytes);
-       if (pui32HostFWCode == NULL)
+       if (eError != PVRSRV_OK)
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Failed in allocating memory for FW code. "
-                               "So skipping FW code verification",
-                               __func__));
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed in parsing FW image file.", __func__));
+               goto cleanup_initfw;
        }
 
-       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
-               pui32HostFWCoremem = OSAllocZMem(psDevInfo->ui32FWCorememCodeSizeInBytes);
-               if (pui32HostFWCoremem == NULL)
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc, (void **)&pui32CodeMemoryPointer);
+               if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR,
-                                       "%s: Failed in allocating memory for FW core code. "
-                                       "So skipping FW code verification",
-                                       __func__));
-                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-                       goto freeHostFWCode;
+                                       "%s: Error in acquiring MIPS FW code memory area (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto cleanup_initfw;
                }
-       }
-
-       /* Load FW image */
-       eError = RGXLoadAndGetFWData(psDevInfo->psDeviceNode, &psRGXFW, &pbRGXFirmware);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to load FW image file (%s).",
-                        __func__, PVRSRVGetErrorString(eError)));
-               eError = PVRSRV_ERROR_INVALID_PARAMS;
-               goto cleanup_initfw;
-       }
 
-       eError = ProcessELFCommandStream(&sLayerParams, pbRGXFirmware,
-                                        pui32HostFWCode, NULL,
-                                        pui32HostFWCoremem, NULL);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed in parsing FW image file.", __func__));
-               goto cleanup_initfw;
-       }
+               if (OSMemCmp(pui32HostFWCode, pui32CodeMemoryPointer, psDevInfo->ui32FWCodeSizeInBytes) == 0)
+               {
+                       PVR_DUMPDEBUG_LOG("Match between Host and MIPS views of the FW code" );
+               }
+               else
+               {
+                       IMG_UINT32 ui32Count = 10; /* Show only the first 10 mismatches */
+                       IMG_UINT32 ui32Offset;
 
-       /* Use bootloader code remap which is always configured before the FW is started */
-       sFWAddr.ui32Addr = RGXRISCVFW_BOOTLDR_CODE_BASE;
+                       PVR_DUMPDEBUG_LOG("Mismatch between Host and MIPS views of the FW code");
+                       for (ui32Offset = 0; (ui32Offset*4 < psDevInfo->ui32FWCodeSizeInBytes) || (ui32Count == 0); ui32Offset++)
+                       {
+                               if (pui32HostFWCode[ui32Offset] != pui32CodeMemoryPointer[ui32Offset])
+                               {
+                                       PVR_DUMPDEBUG_LOG("At %d bytes, code should be 0x%x but it is instead 0x%x",
+                                          ui32Offset*4, pui32HostFWCode[ui32Offset], pui32CodeMemoryPointer[ui32Offset]);
+                                       ui32Count--;
+                               }
+                       }
+               }
 
-       eError = _ValidateWithDM(pfnDumpDebugPrintf, pvDumpDebugFile,
-                                       psDevInfo, &sFWAddr,
-                                       pui32HostFWCode, psDevInfo->ui32FWCodeSizeInBytes,
-                                       "FW code", 0);
-       if (eError != PVRSRV_OK)
-       {
-               goto cleanup_initfw;
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
        }
-
-       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       else
        {
-               sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, RISCV_COREMEM_CODE);
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       /* starting checking after BOOT LOADER config */
+                       sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
 
-               /* Core must be halted while issuing abstract commands */
-               eError = RGXRiscvHalt(psDevInfo);
-               PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+                       ui32StartOffset = RGXFW_MAX_BOOTLDR_OFFSET;
+               }
+               else
+               {
+                       /* Use bootloader code remap which is always configured before the FW is started */
+                       sFWAddr.ui32Addr = RGXRISCVFW_BOOTLDR_CODE_BASE;
+               }
 
-               eError = _ValidateWithDM(pfnDumpDebugPrintf, pvDumpDebugFile,
+               eError = _ValidateWithFWModule(pfnDumpDebugPrintf, pvDumpDebugFile,
                                                psDevInfo, &sFWAddr,
-                                               pui32HostFWCoremem, psDevInfo->ui32FWCorememCodeSizeInBytes,
-                                               "FW coremem code", 0);
+                                               pui32HostFWCode, psDevInfo->ui32FWCodeSizeInBytes,
+                                               "FW code", ui32StartOffset);
+               if (eError != PVRSRV_OK)
+               {
+                       goto cleanup_initfw;
+               }
+
+               if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+               {
+                       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+                       {
+                               sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
+                       }
+                       else
+                       {
+                               sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, RISCV_COREMEM_CODE);
+
+                               /* Core must be halted while issuing abstract commands */
+                               eError = RGXRiscvHalt(psDevInfo);
+                               PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+                       }
+
+                       eError = _ValidateWithFWModule(pfnDumpDebugPrintf, pvDumpDebugFile,
+                                                       psDevInfo, &sFWAddr,
+                                                       pui32HostFWCoremem, psDevInfo->ui32FWCorememCodeSizeInBytes,
+                                                       "FW coremem code", 0);
 
-               eError = RGXRiscvResume(psDevInfo);
-               PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+                       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+                       {
+                               eError = RGXRiscvResume(psDevInfo);
+                               PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+                       }
+               }
        }
 
 cleanup_initfw:
@@ -825,9 +678,6 @@ freeHostFWCode:
        }
        return eError;
 #else
-#if defined(EMULATOR)
-       PVR_DUMPDEBUG_LOG("Validation of RISC-V FW code is disabled on emulator");
-#endif
        PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
        PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
        PVR_UNREFERENCED_PARAMETER(psDevInfo);
@@ -835,7 +685,7 @@ freeHostFWCode:
 #endif
 }
 
-#if defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
 PVRSRV_ERROR ValidateFWOnLoad(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 #if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
@@ -849,8 +699,17 @@ PVRSRV_ERROR ValidateFWOnLoad(PVRSRV_RGXDEV_INFO *psDevInfo)
                return eError;
        }
 
-       sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
-       eError = _ValidateWithSP(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer, psDevInfo->ui32FWCodeSizeInBytes, "FW code", 0);
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
+       }
+       else
+       {
+               PVR_ASSERT(RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR));
+               sFWAddr.ui32Addr = RGXRISCVFW_BOOTLDR_CODE_BASE;
+       };
+
+       eError = _ValidateWithFWModule(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer, psDevInfo->ui32FWCodeSizeInBytes, "FW code", 0);
        if (eError != PVRSRV_OK)
        {
                goto releaseFWCodeMapping;
@@ -858,22 +717,30 @@ PVRSRV_ERROR ValidateFWOnLoad(PVRSRV_RGXDEV_INFO *psDevInfo)
 
        if (psDevInfo->ui32FWCorememCodeSizeInBytes)
        {
-               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCorememMemDesc, (void **)&pbCodeMemoryPointer);
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc, (void **)&pbCodeMemoryPointer);
                if (eError != PVRSRV_OK)
                {
                        goto releaseFWCoreCodeMapping;
                }
 
-               sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
+               }
+               else
+               {
+                       PVR_ASSERT(RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR));
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, RISCV_COREMEM_CODE);
+               }
 
-               eError = _ValidateWithSP(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer,
+               eError = _ValidateWithFWModule(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer,
                                                psDevInfo->ui32FWCorememCodeSizeInBytes, "FW coremem code", 0);
        }
 
 releaseFWCoreCodeMapping:
        if (psDevInfo->ui32FWCorememCodeSizeInBytes)
        {
-               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCorememMemDesc);
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
        }
 releaseFWCodeMapping:
        DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
@@ -967,17 +834,17 @@ static void _RGXDecodeBIFReqTagsXE(PVRSRV_RGXDEV_INFO     *psDevInfo,
        switch (ui32TagID)
        {
                /* MMU tags */
-               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PT:
-               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PD:
-               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PC:
-               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PM:
+               case RGX_MH_TAG_ENCODING_MH_TAG_MMU:
+               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_MMU:
+               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_IFU:
+               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_LSU:
                {
                        switch (ui32TagID)
                        {
-                               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PT: pszTagID = "MMU PT"; break;
-                               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PD: pszTagID = "MMU PD"; break;
-                               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PC: pszTagID = "MMU PC"; break;
-                               case RGX_MH_TAG_ENCODING_MH_TAG_MMU_PM: pszTagID = "MMU PM"; break;
+                               case RGX_MH_TAG_ENCODING_MH_TAG_MMU:        pszTagID = "MMU"; break;
+                               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_MMU:        pszTagID = "CPU MMU"; break;
+                               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_IFU:        pszTagID = "CPU IFU"; break;
+                               case RGX_MH_TAG_ENCODING_MH_TAG_CPU_LSU:        pszTagID = "CPU LSU"; break;
                        }
                        switch (ui32TagSB)
                        {
@@ -1759,7 +1626,7 @@ static const IMG_CHAR* _RGXDecodeMMULevel(IMG_UINT32 ui32MMULevel)
 
 ******************************************************************************/
 static void _RGXDecodeMMUReqTags(PVRSRV_RGXDEV_INFO    *psDevInfo,
-                                                               IMG_UINT32  ui32TagID,
+                                                                IMG_UINT32  ui32TagID,
                                                                 IMG_UINT32  ui32TagSB,
                                                                 IMG_BOOL    bRead,
                                                                 IMG_CHAR    **ppszTagID,
@@ -2186,6 +2053,7 @@ static void _RGXDecodeMMUReqTags(PVRSRV_RGXDEV_INFO    *psDevInfo,
        *ppszTagSB = pszTagSB;
 }
 
+
 static void ConvertOSTimestampToSAndNS(IMG_UINT64 ui64OSTimer,
                                                        IMG_UINT64 *pui64Seconds,
                                                        IMG_UINT64 *pui64Nanoseconds)
@@ -2205,6 +2073,7 @@ typedef enum _DEVICEMEM_HISTORY_QUERY_INDEX_
        DEVICEMEM_HISTORY_QUERY_INDEX_COUNT,
 } DEVICEMEM_HISTORY_QUERY_INDEX;
 
+
 /*!
 *******************************************************************************
 
@@ -2395,7 +2264,6 @@ static IMG_BOOL _GetDevicememHistoryData(IMG_PID uiPID, IMG_DEV_VIRTADDR sFaultD
                                                        DEVICEMEM_HISTORY_QUERY_OUT asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_COUNT],
                                                        IMG_UINT32 ui32PageSizeBytes)
 {
-       IMG_UINT32 i;
        DEVICEMEM_HISTORY_QUERY_IN sQueryIn;
        IMG_BOOL bAnyHits = IMG_FALSE;
 
@@ -2413,39 +2281,38 @@ static IMG_BOOL _GetDevicememHistoryData(IMG_PID uiPID, IMG_DEV_VIRTADDR sFaultD
                sQueryIn.uiPID = uiPID;
        }
 
-       /* query the DevicememHistory about the preceding / faulting / next page */
-
-       for (i = DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING; i < DEVICEMEM_HISTORY_QUERY_INDEX_COUNT; i++)
+       /* Query the DevicememHistory for all allocations in the previous page... */
+       sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) - ui32PageSizeBytes;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING],
+                                 ui32PageSizeBytes, IMG_TRUE))
        {
-               IMG_BOOL bHits;
-
-               switch (i)
-               {
-                       case DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING:
-                               sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) - 1;
-                               break;
-                       case DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED:
-                               sQueryIn.sDevVAddr = sFaultDevVAddr;
-                               break;
-                       case DEVICEMEM_HISTORY_QUERY_INDEX_NEXT:
-                               sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) + ui32PageSizeBytes;
-                               break;
-               }
-
-               /* First try matching any record at the exact address... */
-               bHits = DevicememHistoryQuery(&sQueryIn, &asQueryOut[i], ui32PageSizeBytes, IMG_FALSE);
-               if (!bHits)
-               {
-                       /* If not matched then try matching any record in the same page... */
-                       bHits = DevicememHistoryQuery(&sQueryIn, &asQueryOut[i], ui32PageSizeBytes, IMG_TRUE);
-               }
+               bAnyHits = IMG_TRUE;
+       }
 
-               if (bHits)
+       /* Query the DevicememHistory for any record at the exact address... */
+       sQueryIn.sDevVAddr = sFaultDevVAddr;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED],
+                                 ui32PageSizeBytes, IMG_FALSE))
+       {
+               bAnyHits = IMG_TRUE;
+       }
+       else
+       {
+               /* If not matched then try matching any record in the faulting page... */
+               if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED],
+                                         ui32PageSizeBytes, IMG_TRUE))
                {
                        bAnyHits = IMG_TRUE;
                }
        }
 
+       /* Query the DevicememHistory for all allocations in the next page... */
+       sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) + ui32PageSizeBytes;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_NEXT],
+                                 ui32PageSizeBytes, IMG_TRUE))
+       {
+               bAnyHits = IMG_TRUE;
+       }
 
        return bAnyHits;
 }
@@ -2567,7 +2434,7 @@ static void _PrintFaultInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        {
                for (i = DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING; i < DEVICEMEM_HISTORY_QUERY_INDEX_COUNT; i++)
                {
-                       const IMG_CHAR *pszWhich;
+                       const IMG_CHAR *pszWhich = NULL;
 
                        switch (i)
                        {
@@ -2975,6 +2842,7 @@ static_assert((RGX_CR_MMU_FAULT_STATUS_TYPE_SHIFT == RGX_CR_MMU_FAULT_STATUS_MET
 
 
 
+#if !defined(SUPPORT_TRUSTED_DEVICE)
 #if !defined(NO_HARDWARE)
 static PVRSRV_ERROR _RGXMipsExtraDebug(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_MIPS_STATE *psMIPSState)
 {
@@ -3009,8 +2877,9 @@ static PVRSRV_ERROR _RGXMipsExtraDebug(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_MIPS_S
        /* Make sure the synchronisation flag is set to 0 */
        pui32SyncFlag = &pui32NMIMemoryPointer[RGXMIPSFW_NMI_SYNC_FLAG_OFFSET];
        *pui32SyncFlag = 0;
-       OSWriteMemoryBarrier();
-       (void) *pui32SyncFlag;
+
+       /* Readback performed as a part of memory barrier */
+       OSWriteMemoryBarrier(pui32SyncFlag);
 
        /* Enable NMI issuing in the MIPS wrapper */
        OSWriteHWReg64(pvRegsBaseKM,
@@ -3057,8 +2926,9 @@ static PVRSRV_ERROR _RGXMipsExtraDebug(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_MIPS_S
 
        /* Allow the firmware to proceed */
        *pui32SyncFlag = 1;
-       OSWriteMemoryBarrier();
-       (void) *pui32SyncFlag;
+
+       /* Readback performed as a part of memory barrier */
+       OSWriteMemoryBarrier(pui32SyncFlag);
 
        /* Wait for the FW to have finished the NMI routine */
        ui32RegRead = OSReadHWReg32(pvRegsBaseKM,
@@ -3293,38 +3163,6 @@ static inline void _RGXMipsDumpTLBEntry(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrint
        IMG_UINT64 ui64Remap0AddrOut = 0, ui64Remap1AddrOut = 0;
        IMG_UINT32 ui32Remap0AddrIn = 0, ui32Remap1AddrIn = 0;
 
-       static const IMG_CHAR * const apszPermissionInhibit[4] =
-       {
-               "",
-               "XI",
-               "RI",
-               "RIXI"
-       };
-
-       static const IMG_CHAR * const apszCoherencyTLB[8] =
-       {
-               "C",
-               "C",
-               " ",
-               "C",
-               "C",
-               "C",
-               "C",
-               " "
-       };
-
-       static const IMG_CHAR * const apszDirtyGlobalValid[8] =
-       {
-               "   ",
-               "  G",
-               " V ",
-               " VG",
-               "D  ",
-               "D G",
-               "DV ",
-               "DVG"
-       };
-
        if (bDumpRemapEntries)
        {
                /* RemapAddrIn is always 4k aligned and on 32 bit */
@@ -3351,13 +3189,13 @@ static inline void _RGXMipsDumpTLBEntry(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrint
                          psTLBEntry->ui32TLBHi,
                          RGXMIPSFW_TLB_GET_PAGE_SIZE(psTLBEntry->ui32TLBPageMask),
                          ui64PA0,
-                         apszPermissionInhibit[RGXMIPSFW_TLB_GET_INHIBIT(psTLBEntry->ui32TLBLo0)],
-                         apszDirtyGlobalValid[RGXMIPSFW_TLB_GET_DGV(psTLBEntry->ui32TLBLo0)],
-                         apszCoherencyTLB[RGXMIPSFW_TLB_GET_COHERENCY(psTLBEntry->ui32TLBLo0)],
+                         gapszMipsPermissionPTFlags[RGXMIPSFW_TLB_GET_INHIBIT(psTLBEntry->ui32TLBLo0)],
+                         gapszMipsDirtyGlobalValidPTFlags[RGXMIPSFW_TLB_GET_DGV(psTLBEntry->ui32TLBLo0)],
+                         gapszMipsCoherencyPTFlags[RGXMIPSFW_TLB_GET_COHERENCY(psTLBEntry->ui32TLBLo0)],
                          ui64PA1,
-                         apszPermissionInhibit[RGXMIPSFW_TLB_GET_INHIBIT(psTLBEntry->ui32TLBLo1)],
-                         apszDirtyGlobalValid[RGXMIPSFW_TLB_GET_DGV(psTLBEntry->ui32TLBLo1)],
-                         apszCoherencyTLB[RGXMIPSFW_TLB_GET_COHERENCY(psTLBEntry->ui32TLBLo1)]);
+                         gapszMipsPermissionPTFlags[RGXMIPSFW_TLB_GET_INHIBIT(psTLBEntry->ui32TLBLo1)],
+                         gapszMipsDirtyGlobalValidPTFlags[RGXMIPSFW_TLB_GET_DGV(psTLBEntry->ui32TLBLo1)],
+                         gapszMipsCoherencyPTFlags[RGXMIPSFW_TLB_GET_COHERENCY(psTLBEntry->ui32TLBLo1)]);
 
        if (bDumpRemapEntries)
        {
@@ -3376,6 +3214,7 @@ static inline void _RGXMipsDumpTLBEntry(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrint
 }
 
 #endif /* !defined(NO_HARDWARE) */
+#endif /* !defined(SUPPORT_TRUSTED_DEVICE) */
 
 static inline IMG_CHAR const *_GetRISCVException(IMG_UINT32 ui32Mcause)
 {
@@ -3400,8 +3239,11 @@ static inline IMG_CHAR const *_GetRISCVException(IMG_UINT32 ui32Mcause)
        Appends flags strings to a null-terminated string buffer - each flag
        description string starts with a space.
 */
-static void _Flags2Description(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, const IMG_FLAGS2DESC *psConvTable,
-                               IMG_UINT32 ui32TableSize, IMG_UINT32 ui32Flags)
+static void _Flags2Description(IMG_CHAR *psDesc,
+                               IMG_UINT32 ui32DescSize,
+                               const IMG_FLAGS2DESC *psConvTable,
+                               IMG_UINT32 ui32TableSize,
+                               IMG_UINT32 ui32Flags)
 {
        IMG_UINT32 ui32Idx;
 
@@ -3419,11 +3261,11 @@ static void _Flags2Description(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, const
 */
 static void _GetFwSysFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, IMG_UINT32 ui32RawFlags)
 {
-       const IMG_CHAR *psCswLabel = "Ctx switch options:";
-       size_t uLabelLen = OSStringLength(psCswLabel);
+       const IMG_CHAR szCswLabel[] = "Ctx switch options:";
+       size_t uLabelLen = sizeof(szCswLabel) - 1;
        const size_t uiBytesPerDesc = (ui32DescSize - uLabelLen) / 2U - 1U;
 
-       OSStringLCopy(psDesc, psCswLabel, ui32DescSize);
+       OSStringLCopy(psDesc, szCswLabel, ui32DescSize);
 
        _Flags2Description(psDesc, uiBytesPerDesc + uLabelLen, asCswOpts2Description, ARRAY_SIZE(asCswOpts2Description), ui32RawFlags);
        _Flags2Description(psDesc, ui32DescSize, asMisc2Description, ARRAY_SIZE(asMisc2Description), ui32RawFlags);
@@ -3431,11 +3273,11 @@ static void _GetFwSysFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize,
 
 static void _GetFwOsFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, IMG_UINT32 ui32RawFlags)
 {
-       const IMG_CHAR *psCswLabel = "Ctx switch:";
-       size_t uLabelLen = OSStringLength(psCswLabel);
+       const IMG_CHAR szCswLabel[] = "Ctx switch:";
+       size_t uLabelLen = sizeof(szCswLabel) - 1;
        const size_t uiBytesPerDesc = (ui32DescSize - uLabelLen) / 2U - 1U;
 
-       OSStringLCopy(psDesc, psCswLabel, ui32DescSize);
+       OSStringLCopy(psDesc, szCswLabel, ui32DescSize);
 
        _Flags2Description(psDesc, uiBytesPerDesc + uLabelLen, asFwOsCfg2Description, ARRAY_SIZE(asFwOsCfg2Description), ui32RawFlags);
 }
@@ -3460,12 +3302,12 @@ static void _GetFwOsFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize,
 ******************************************************************************/
 static void _RGXDumpFWAssert(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        void *pvDumpDebugFile,
-                                       RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl)
+                                       const RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl)
 {
-       IMG_CHAR    *pszTraceAssertPath;
-       IMG_CHAR    *pszTraceAssertInfo;
-       IMG_INT32   ui32TraceAssertLine;
-       IMG_UINT32  i;
+       const IMG_CHAR *pszTraceAssertPath;
+       const IMG_CHAR *pszTraceAssertInfo;
+       IMG_INT32 ui32TraceAssertLine;
+       IMG_UINT32 i;
 
        for (i = 0; i < RGXFW_THREAD_NUM; i++)
        {
@@ -3501,7 +3343,7 @@ static void _RGXDumpFWAssert(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 ******************************************************************************/
 static void _RGXDumpFWFaults(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                              void *pvDumpDebugFile,
-                             RGXFWIF_SYSDATA *psFwSysData)
+                             const RGXFWIF_SYSDATA *psFwSysData)
 {
        if (psFwSysData->ui32FWFaults > 0)
        {
@@ -3516,8 +3358,8 @@ static void _RGXDumpFWFaults(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
                for (ui32Index = ui32StartFault; ui32Index <= ui32EndFault; ui32Index++)
                {
-                       RGX_FWFAULTINFO *psFaultInfo = &psFwSysData->sFaultInfo[ui32Index % RGXFWIF_FWFAULTINFO_MAX];
-                       IMG_UINT64      ui64Seconds, ui64Nanoseconds;
+                       const RGX_FWFAULTINFO *psFaultInfo = &psFwSysData->sFaultInfo[ui32Index % RGXFWIF_FWFAULTINFO_MAX];
+                       IMG_UINT64 ui64Seconds, ui64Nanoseconds;
 
                        /* Split OS timestamp in seconds and nanoseconds */
                        ConvertOSTimestampToSAndNS(psFaultInfo->ui64OSTimer, &ui64Seconds, &ui64Nanoseconds);
@@ -3536,7 +3378,7 @@ static void _RGXDumpFWFaults(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
 static void _RGXDumpFWPoll(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        void *pvDumpDebugFile,
-                                       RGXFWIF_SYSDATA *psFwSysData)
+                                       const RGXFWIF_SYSDATA *psFwSysData)
 {
        IMG_UINT32 i;
        for (i = 0; i < RGXFW_THREAD_NUM; i++)
@@ -3553,18 +3395,20 @@ static void _RGXDumpFWPoll(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
 }
 
-static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *pvDumpDebugFile,
-                                       RGXFWIF_SYSDATA *psFwSysData, RGXFWIF_HWRINFOBUF *psHWRInfoBuf, PVRSRV_RGXDEV_INFO *psDevInfo)
+static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                                         void *pvDumpDebugFile,
+                                                         const RGXFWIF_SYSDATA *psFwSysData,
+                                                         const RGXFWIF_HWRINFOBUF *psHWRInfoBuf,
+                                                         PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-       IMG_BOOL   bAnyLocked = IMG_FALSE;
-       IMG_UINT32 dm, i;
-       IMG_UINT32 ui32LineSize;
-       IMG_CHAR   *pszLine, *pszTemp;
-       const IMG_CHAR    *apszDmNames[RGXFWIF_DM_MAX] = {"GP", "TDM", "TA", "3D", "CDM", "RAY"};
+       IMG_BOOL          bAnyLocked = IMG_FALSE;
+       IMG_UINT32        dm, i;
+       IMG_UINT32        ui32LineSize;
+       IMG_CHAR          *pszLine, *pszTemp;
+       const IMG_CHAR    *apszDmNames[RGXFWIF_DM_MAX] = {"GP", "TDM", "TA", "3D", "CDM", "RAY", "TA2", "TA3", "TA4"};
        const IMG_CHAR    szMsgHeader[] = "Number of HWR: ";
        const IMG_CHAR    szMsgFalse[] = "FALSE(";
        IMG_CHAR          *pszLockupType = "";
-       RGX_HWRINFO       *psHWRInfo;
        const IMG_UINT32  ui32MsgHeaderCharCount = ARRAY_SIZE(szMsgHeader) - 1; /* size includes the null */
        const IMG_UINT32  ui32MsgFalseCharCount = ARRAY_SIZE(szMsgFalse) - 1;
        IMG_UINT32        ui32HWRRecoveryFlags;
@@ -3575,7 +3419,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                apszDmNames[RGXFWIF_DM_TDM] = "2D";
        }
 
-       for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
        {
                if (psHWRInfoBuf->aui32HwrDmLockedUpCount[dm] ||
                    psHWRInfoBuf->aui32HwrDmOverranCount[dm])
@@ -3595,7 +3439,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
        {
                IMG_BOOL bAnyHWROccured = IMG_FALSE;
 
-               for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+               for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
                {
                        if (psHWRInfoBuf->aui32HwrDmRecoveredCount[dm] != 0 ||
                                psHWRInfoBuf->aui32HwrDmLockedUpCount[dm] != 0 ||
@@ -3614,12 +3458,12 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
 
        ui32LineSize = sizeof(IMG_CHAR) * (
                        ui32MsgHeaderCharCount +
-                       (RGXFWIF_DM_MAX * (     4/*DM name + left parenthesis*/ +
+                       (psDevInfo->sDevFeatureCfg.ui32MAXDMCount*(     4/*DM name + left parenthesis*/ +
                                10/*UINT32 max num of digits*/ +
                                1/*slash*/ +
                                10/*UINT32 max num of digits*/ +
                                3/*right parenthesis + comma + space*/)) +
-                       ui32MsgFalseCharCount + 1 + (RGXFWIF_DM_MAX*6) + 1
+                       ui32MsgFalseCharCount + 1 + (psDevInfo->sDevFeatureCfg.ui32MAXDMCount*6) + 1
                                /* 'FALSE(' + ')' + (UINT16 max num + comma) per DM + \0 */
                        );
 
@@ -3636,7 +3480,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
        OSStringLCopy(pszLine, szMsgHeader, ui32LineSize);
        pszTemp = pszLine + ui32MsgHeaderCharCount;
 
-       for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
        {
                pszTemp += OSSNPrintf(pszTemp,
                                4 + 10 + 1 + 10 + 1 + 10 + 1 + 1 + 1 + 1
@@ -3651,11 +3495,11 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
        OSStringLCat(pszLine, szMsgFalse, ui32LineSize);
        pszTemp += ui32MsgFalseCharCount;
 
-       for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
        {
                pszTemp += OSSNPrintf(pszTemp,
                                10 + 1 + 1 /* UINT32 max num + comma + \0 */,
-                               (dm < RGXFWIF_DM_MAX-1 ? "%u," : "%u)"),
+                               (dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount-1 ? "%u," : "%u)"),
                                psHWRInfoBuf->aui32HwrDmFalseDetectCount[dm]);
        }
 
@@ -3664,7 +3508,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
        OSFreeMem(pszLine);
 
        /* Print out per HWR info */
-       for (dm = 0; dm < RGXFWIF_DM_MAX; dm++)
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
        {
                if (dm == RGXFWIF_DM_GP)
                {
@@ -3703,8 +3547,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                        IMG_UINT32 ui32PC;
                        IMG_UINT32 ui32PageSize = 0;
                        IMG_DEV_PHYADDR sPCDevPAddr = { 0 };
-
-                       psHWRInfo = &psHWRInfoBuf->sHWRInfo[ui32ReadIndex];
+                       const RGX_HWRINFO *psHWRInfo = &psHWRInfoBuf->sHWRInfo[ui32ReadIndex];
 
                        if ((psHWRInfo->eDM == dm) && (psHWRInfo->ui32HWRNumber != 0))
                        {
@@ -3755,7 +3598,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                                /* There's currently no time correlation for the Guest OSes on the Firmware so there's no point printing OS Timestamps on Guests */
                                if (!PVRSRV_VZ_MODE_IS(GUEST))
                                {
-                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECx", OSTimer = %" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC ", CyclesElapsed = %" IMG_INT64_FMTSPECd,
+                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECX", OSTimer = %" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC ", CyclesElapsed = %" IMG_INT64_FMTSPECd,
                                                                           aui8RecoveryNum,
                                                                           psHWRInfo->ui64CRTimer,
                                                                           ui64Seconds,
@@ -3764,7 +3607,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                                }
                                else
                                {
-                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECx", CyclesElapsed = %" IMG_INT64_FMTSPECd,
+                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECX", CyclesElapsed = %" IMG_INT64_FMTSPECd,
                                                                           aui8RecoveryNum,
                                                                           psHWRInfo->ui64CRTimer,
                                                                           (psHWRInfo->ui64CRTimer-psHWRInfo->ui64CRTimeOfKick)*256);
@@ -3880,6 +3723,7 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                                                }
                                        }
                                        break;
+
                                        case RGX_HWRTYPE_MMUMETAFAULT:
                                        {
                                                if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
@@ -3899,7 +3743,6 @@ static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, void *p
                                        }
                                        break;
 
-
                                        case RGX_HWRTYPE_POLLFAILURE:
                                        {
                                                PVR_DUMPDEBUG_LOG("    T%u polling %s (reg:0x%08X mask:0x%08X last:0x%08X)",
@@ -4103,10 +3946,10 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        IMG_BOOL bRGXPoweredON)
 {
        IMG_CHAR *pszState, *pszReason;
-       RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
-       RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       const RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
        IMG_UINT32 ui32OSid;
-       RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+       const RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
        /* space for the current clock speed and 3 previous */
        RGXFWIF_TIME_CORR asTimeCorrs[4];
        IMG_UINT32 ui32NumClockSpeedChanges;
@@ -4257,6 +4100,7 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 #endif /* (RGX_NUM_OS_SUPPORTED > 1) */
 
 #if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) || (defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1))
+       if (!PVRSRV_VZ_MODE_IS(NATIVE))
        {
                RGXFWIF_CONNECTION_FW_STATE eFwState = KM_GET_FW_CONNECTION(psDevInfo);
                RGXFWIF_CONNECTION_OS_STATE eOsState = KM_GET_OS_CONNECTION(psDevInfo);
@@ -4294,6 +4138,7 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                }
 
                sHwrStateDescription[0] = '\0';
+
                _Flags2Description(sHwrStateDescription, RGX_DEBUG_STR_SIZE,
                        asHwrState2Description, ARRAY_SIZE(asHwrState2Description),
                        psFwSysData->ui32HWRStateFlags);
@@ -4358,6 +4203,7 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
                        bOsIsolationEnabled |= sFwRunFlags.bfIsolatedOS;
                }
+
 #if defined(PVR_ENABLE_PHR)
                {
                        IMG_CHAR sPHRConfigDescription[RGX_DEBUG_STR_SIZE];
@@ -4371,6 +4217,14 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                }
 #endif
 
+               if (bRGXPoweredON && RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_MULTICORE_SUPPORT))
+               {
+                       if (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MULTICORE_SYSTEM) > 1U)
+                       {
+                               PVR_DUMPDEBUG_LOG("RGX MC Configuration: 0x%X (1:primary, 0:secondary)", psFwSysData->ui32McConfig);
+                       }
+               }
+
                if (bOsIsolationEnabled)
                {
                        PVR_DUMPDEBUG_LOG("RGX Hard Context Switch deadline: %u ms", psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS);
@@ -4392,7 +4246,7 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        /* Dump all non-zero values in lines of 8... */
        {
                IMG_CHAR    pszLine[(9*RGXFWIF_STATS_FRAMEWORK_LINESIZE)+1];
-               IMG_UINT32  *pui32FWStatsBuf = psFwSysData->aui32FWStatsBuf;
+               const IMG_UINT32 *pui32FWStatsBuf = psFwSysData->aui32FWStatsBuf;
                IMG_UINT32  ui32Index1, ui32Index2;
 
                PVR_DUMPDEBUG_LOG("STATS[START]: RGXFWIF_STATS_FRAMEWORK_MAX=%d", RGXFWIF_STATS_FRAMEWORK_MAX);
@@ -4663,6 +4517,8 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                IMG_UINT32  tid;
                IMG_UINT32  ui32TraceBufSizeInDWords = psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords;
 
+               PVR_DUMPDEBUG_LOG("Device ID: %u", psDevInfo->psDeviceNode->sDevId.ui32InternalID);
+
                /* Print the log type settings... */
                if (psRGXFWIfTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_GROUP_MASK)
                {
@@ -4679,9 +4535,12 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                /* Print the decoded log for each thread... */
                for (tid = 0;  tid < RGXFW_THREAD_NUM;  tid++)
                {
-                       IMG_UINT32  *pui32TraceBuf = psRGXFWIfTraceBufCtl->sTraceBuf[tid].pui32TraceBuffer;
-                       IMG_UINT32  ui32TracePtr  = psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer;
-                       IMG_UINT32  ui32Count     = 0;
+                       volatile IMG_UINT32  *pui32FWWrapCount = &(psRGXFWIfTraceBufCtl->sTraceBuf[tid].sAssertBuf.ui32LineNum);
+                       volatile IMG_UINT32  *pui32FWTracePtr  = &(psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer);
+                       IMG_UINT32           *pui32TraceBuf    = psRGXFWIfTraceBufCtl->sTraceBuf[tid].pui32TraceBuffer;
+                       IMG_UINT32           ui32HostWrapCount = *pui32FWWrapCount;
+                       IMG_UINT32           ui32HostTracePtr  = *pui32FWTracePtr;
+                       IMG_UINT32           ui32Count         = 0;
 
                        if (pui32TraceBuf == NULL)
                        {
@@ -4696,7 +4555,7 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                /* Find the first valid log ID, skipping whitespace... */
                                do
                                {
-                                       ui32Data     = pui32TraceBuf[ui32TracePtr];
+                                       ui32Data     = pui32TraceBuf[ui32HostTracePtr];
                                        ui32DataToId = idToStringID(ui32Data, SFs);
 
                                        /* If an unrecognized id is found it may be inconsistent data or a firmware trace error. */
@@ -4706,9 +4565,14 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        }
 
                                        /* Update the trace pointer... */
-                                       ui32TracePtr = (ui32TracePtr + 1) % ui32TraceBufSizeInDWords;
+                                       ui32HostTracePtr++;
+                                       if (ui32HostTracePtr >= ui32TraceBufSizeInDWords)
+                                       {
+                                               ui32HostTracePtr = 0;
+                                               ui32HostWrapCount++;
+                                       }
                                        ui32Count++;
-                               } while ((RGXFW_SF_LAST == ui32DataToId  ||  ui32DataToId >= RGXFW_SF_FIRST)  &&
+                               } while ((RGXFW_SF_LAST == ui32DataToId)  &&
                                         ui32Count < ui32TraceBufSizeInDWords);
 
                                if (ui32Count < ui32TraceBufSizeInDWords)
@@ -4728,8 +4592,8 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                break;
                                        }
 
-                                       ui64Timestamp = (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr + 0) % ui32TraceBufSizeInDWords]) << 32 |
-                                                       (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr + 1) % ui32TraceBufSizeInDWords]);
+                                       ui64Timestamp = (IMG_UINT64)(pui32TraceBuf[(ui32HostTracePtr + 0) % ui32TraceBufSizeInDWords]) << 32 |
+                                                       (IMG_UINT64)(pui32TraceBuf[(ui32HostTracePtr + 1) % ui32TraceBufSizeInDWords]);
 
                                        ui16DebugInfo = (IMG_UINT16) ((ui64Timestamp & ~RGXFWT_TIMESTAMP_DEBUG_INFO_CLRMSK) >> RGXFWT_TIMESTAMP_DEBUG_INFO_SHIFT);
                                        ui64Timestamp = (ui64Timestamp & ~RGXFWT_TIMESTAMP_TIME_CLRMSK) >> RGXFWT_TIMESTAMP_TIME_SHIFT;
@@ -4752,30 +4616,45 @@ void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                        }
 
                                        PVR_DUMPDEBUG_LOG(szBuffer, ui64Timestamp, tid, groups[RGXFW_SF_GID(ui32Data)],
-                                                                         pui32TraceBuf[(ui32TracePtr +  2) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  3) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  4) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  5) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  6) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  7) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  8) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr +  9) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 10) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 11) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 12) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 13) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 14) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 15) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 16) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 17) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 18) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 19) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 20) % ui32TraceBufSizeInDWords],
-                                                                         pui32TraceBuf[(ui32TracePtr + 21) % ui32TraceBufSizeInDWords]);
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  2) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  3) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  4) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  5) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  6) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  7) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  8) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  9) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 10) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 11) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 12) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 13) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 14) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 15) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 16) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 17) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 18) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 19) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 20) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 21) % ui32TraceBufSizeInDWords]);
 
                                        /* Update the trace pointer... */
-                                       ui32TracePtr = (ui32TracePtr + 2 + RGXFW_SF_PARAMNUM(ui32Data)) % ui32TraceBufSizeInDWords;
-                                       ui32Count    = (ui32Count    + 2 + RGXFW_SF_PARAMNUM(ui32Data));
+                                       ui32HostTracePtr = ui32HostTracePtr + 2 + RGXFW_SF_PARAMNUM(ui32Data);
+                                       if (ui32HostTracePtr >= ui32TraceBufSizeInDWords)
+                                       {
+                                               ui32HostTracePtr = ui32HostTracePtr % ui32TraceBufSizeInDWords;
+                                               ui32HostWrapCount++;
+                                       }
+                                       ui32Count = (ui32Count + 2 + RGXFW_SF_PARAMNUM(ui32Data));
+
+                                       /* Has the FW trace buffer overtaken the host pointer during the last line printed??? */
+                                       if ((*pui32FWWrapCount > ui32HostWrapCount) ||
+                                           ((*pui32FWWrapCount == ui32HostWrapCount) && (*pui32FWTracePtr > ui32HostTracePtr)))
+                                       {
+                                               /* Move forward to the oldest entry again... */
+                                               PVR_DUMPDEBUG_LOG(". . .");
+                                               ui32HostWrapCount = *pui32FWWrapCount;
+                                               ui32HostTracePtr  = *pui32FWTracePtr;
+                                       }
                                }
                        }
                }
@@ -4787,16 +4666,16 @@ void RGXDumpPowerMonitoring(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                void *pvDumpDebugFile,
                                PVRSRV_RGXDEV_INFO  *psDevInfo)
 {
-       RGXFWIF_SYSDATA  *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
 
        /* Print the power monitoring counters... */
        if (psFwSysData != NULL)
        {
-               IMG_UINT32  *pui32TraceBuf = psFwSysData->sPowerMonBuf.pui32TraceBuffer;
-               IMG_UINT32  ui32TracePtr  = 0; //psFwSysData->sPowerMonBuf.ui32TracePointer;
-               IMG_UINT32  ui32PowerMonBufSizeInDWords = psFwSysData->ui32PowerMonBufSizeInDWords;
-               IMG_UINT32  ui32Count     = 0;
-               IMG_UINT64  ui64Timestamp;
+               const IMG_UINT32 *pui32TraceBuf = psFwSysData->sPowerMonBuf.pui32TraceBuffer;
+               IMG_UINT32 ui32TracePtr = 0; //psFwSysData->sPowerMonBuf.ui32TracePointer;
+               IMG_UINT32 ui32PowerMonBufSizeInDWords = psFwSysData->ui32PowerMonBufSizeInDWords;
+               IMG_UINT32 ui32Count = 0;
+               IMG_UINT64 ui64Timestamp;
 
                if (pui32TraceBuf == NULL)
                {
@@ -4886,6 +4765,7 @@ static const IMG_CHAR* _RGXGetDebugDevPowerStateString(PVRSRV_DEV_POWER_STATE eP
 #define DDLOG64_DPX(R)  PVR_DUMPDEBUG_LOG(REG64_FMTSPEC, #R, OSReadHWReg64(pvRegsBaseKM, DPX_CR_##R));
 #define DDLOGVAL32(S,V) PVR_DUMPDEBUG_LOG(REG32_FMTSPEC, S, V);
 
+#if !defined(SUPPORT_TRUSTED_DEVICE)
 #if !defined(NO_HARDWARE)
 static void RGXDumpMIPSState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                         void *pvDumpDebugFile,
@@ -4977,7 +4857,7 @@ static void RGXDumpMIPSState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                /* Check FW code corruption in case of known errors */
                if (_IsFWCodeException(RGXMIPSFW_C0_CAUSE_EXCCODE(sMIPSState.ui32CauseRegister)))
                {
-                       eError = _ValidateFWImageForMIPS(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, "");
+                       eError = _ValidateFWImage(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
                        if (eError != PVRSRV_OK)
                        {
                                PVR_DUMPDEBUG_LOG("Failed to validate any FW code corruption");
@@ -4987,6 +4867,7 @@ static void RGXDumpMIPSState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        PVR_DUMPDEBUG_LOG("--------------------------------");
 }
 #endif
+#endif /* !defined(SUPPORT_TRUSTED_DEVICE) */
 
 static PVRSRV_ERROR RGXDumpRISCVState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                                                          void *pvDumpDebugFile,
@@ -4997,11 +4878,6 @@ static PVRSRV_ERROR RGXDumpRISCVState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        const IMG_CHAR *pszException;
        PVRSRV_ERROR eError;
 
-#if defined(NO_HARDWARE)
-       /* OSReadHWReg variants don't use params passed in NoHW builds */
-       PVR_UNREFERENCED_PARAMETER(pvRegsBaseKM);
-#endif
-
        DDLOG64(FWCORE_MEM_CAT_BASE0);
        DDLOG64(FWCORE_MEM_CAT_BASE1);
        DDLOG64(FWCORE_MEM_CAT_BASE2);
@@ -5027,6 +4903,16 @@ static PVRSRV_ERROR RGXDumpRISCVState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
        PVR_DUMPDEBUG_LOG("---- [ RISC-V internal state ] ----");
 
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+       if (RGXRiscvIsHalted(psDevInfo))
+       {
+               /* Avoid resuming the RISC-V FW as most operations
+                * on the debug module require a halted core */
+               PVR_DUMPDEBUG_LOG("(skipping as RISC-V found halted)");
+               return PVRSRV_OK;
+       }
+#endif
+
        eError = RGXRiscvHalt(psDevInfo);
        PVR_GOTO_IF_ERROR(eError, _RISCVDMError);
 
@@ -5046,7 +4932,7 @@ static PVRSRV_ERROR RGXDumpRISCVState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        {
                PVR_DUMPDEBUG_LOG("RISC-V FW hit an exception: %s", pszException);
 
-               eError = _ValidateFWImageForRISCV(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+               eError = _ValidateFWImage(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
                if (eError != PVRSRV_OK)
                {
                        PVR_DUMPDEBUG_LOG("Failed to validate any FW code corruption");
@@ -5081,11 +4967,6 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        /* Check if firmware perf was set at Init time */
        bFirmwarePerf = (psDevInfo->psRGXFWIfSysInit->eFirmwarePerf != FW_PERF_CONF_NONE);
 
-#if defined(NO_HARDWARE)
-       /* OSReadHWReg variants don't use params passed in NoHW builds */
-       PVR_UNREFERENCED_PARAMETER(pvRegsBaseKM);
-#endif
-
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, PBVNC_COREID_REG))
        {
                DDLOG64(CORE_ID);
@@ -5310,16 +5191,16 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                /* Forcing bit 6 of MslvCtrl1 to 0 to avoid internal reg read going through the core */
                OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0);
 
-               eError = RGXReadWithSP(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegVal);
-               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                DDLOGVAL32("T0 TXENABLE", ui32RegVal);
                if (ui32RegVal & META_CR_TXENABLE_ENABLE_BIT)
                {
                        bIsT0Enabled = IMG_TRUE;
                }
 
-               eError = RGXReadWithSP(psDevInfo, META_CR_T0STATUS_OFFSET, &ui32RegVal);
-               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0STATUS_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                DDLOGVAL32("T0 TXSTATUS", ui32RegVal);
 
                /* check for FW fault */
@@ -5328,8 +5209,8 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                        bIsFWFaulted = IMG_TRUE;
                }
 
-               eError = RGXReadWithSP(psDevInfo, META_CR_T0DEFR_OFFSET, &ui32RegVal);
-               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0DEFR_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                DDLOGVAL32("T0 TXDEFR", ui32RegVal);
 
                eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR0_PC, &ui32RegVal);
@@ -5344,19 +5225,18 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
                DDLOGVAL32("T0 SP", ui32RegVal);
 
-
                if ((ui32Meta == MTP218) || (ui32Meta == MTP219))
                {
-                       eError = RGXReadWithSP(psDevInfo, META_CR_T1ENABLE_OFFSET, &ui32RegVal);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1ENABLE_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                        DDLOGVAL32("T1 TXENABLE", ui32RegVal);
 
-                       eError = RGXReadWithSP(psDevInfo, META_CR_T1STATUS_OFFSET, &ui32RegVal);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1STATUS_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                        DDLOGVAL32("T1 TXSTATUS", ui32RegVal);
 
-                       eError = RGXReadWithSP(psDevInfo, META_CR_T1DEFR_OFFSET, &ui32RegVal);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1DEFR_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                        DDLOGVAL32("T1 TXDEFR", ui32RegVal);
 
                        eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR1_PC, &ui32RegVal);
@@ -5374,18 +5254,18 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
                if (bFirmwarePerf)
                {
-                       eError = RGXReadWithSP(psDevInfo, META_CR_PERF_COUNT0, &ui32RegVal);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_PERF_COUNT0, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                        DDLOGVAL32("PERF_COUNT0", ui32RegVal);
 
-                       eError = RGXReadWithSP(psDevInfo, META_CR_PERF_COUNT1, &ui32RegVal);
-                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadWithSP", _METASPError);
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_PERF_COUNT1, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
                        DDLOGVAL32("PERF_COUNT1", ui32RegVal);
                }
 
                if (bIsT0Enabled & bIsFWFaulted)
                {
-                       eError = _ValidateFWImageForMETA(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+                       eError = _ValidateFWImage(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
                        if (eError != PVRSRV_OK)
                        {
                                PVR_DUMPDEBUG_LOG("Failed to validate any FW code corruption");
@@ -5412,7 +5292,9 @@ PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                DDLOG64(MIPS_WRAPPER_CONFIG);
                DDLOG32(MIPS_EXCEPTION_STATUS);
 
-#if !defined(NO_HARDWARE)
+#if defined(SUPPORT_TRUSTED_DEVICE)
+               PVR_DUMPDEBUG_LOG("MIPS extra debug not available with SUPPORT_TRUSTED_DEVICE.");
+#elif !defined(NO_HARDWARE)
                RGXDumpMIPSState(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
 #endif
        }
@@ -5470,7 +5352,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        IMG_BOOL                bRGXPoweredON;
        IMG_UINT8               ui8FwOsCount;
        RGXFWIF_TRACEBUF        *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
-       RGXFWIF_OSDATA    *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
+       const RGXFWIF_OSDATA    *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
        IMG_BOOL                bPwrLockAlreadyHeld;
 
        bPwrLockAlreadyHeld = PVRSRVPwrLockIsLockedByMe(psDeviceNode);
@@ -5498,7 +5380,6 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                goto Exit;
        }
 
-
        if ((PVRSRV_VZ_MODE_IS(NATIVE) && (ui8FwOsCount > 1)) ||
                (PVRSRV_VZ_MODE_IS(HOST) && (ui8FwOsCount != RGX_NUM_OS_SUPPORTED)))
        {
@@ -5512,9 +5393,9 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
        PVR_DUMPDEBUG_LOG("------[ RGX Info ]------");
        PVR_DUMPDEBUG_LOG("Device Node (Info): %p (%p)", psDevInfo->psDeviceNode, psDevInfo);
-       PVR_DUMPDEBUG_LOG("RGX BVNC: %d.%d.%d.%d (%s)", psDevInfo->sDevFeatureCfg.ui32B, \
-                                                                                          psDevInfo->sDevFeatureCfg.ui32V,     \
-                                                                                          psDevInfo->sDevFeatureCfg.ui32N, \
+       PVR_DUMPDEBUG_LOG("RGX BVNC: %d.%d.%d.%d (%s)", psDevInfo->sDevFeatureCfg.ui32B,
+                                                                                          psDevInfo->sDevFeatureCfg.ui32V,
+                                                                                          psDevInfo->sDevFeatureCfg.ui32N,
                                                                                           psDevInfo->sDevFeatureCfg.ui32C,
                                                                                           PVR_ARCH_NAME);
        PVR_DUMPDEBUG_LOG("RGX Device State: %s", _RGXGetDebugDevStateString(psDeviceNode->eDevState));
@@ -5532,7 +5413,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
        /* Dump out the kernel CCB. */
        {
-               RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
+               const RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
 
                if (psKCCBCtl != NULL)
                {
@@ -5544,7 +5425,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
        /* Dump out the firmware CCB. */
        {
-               RGXFWIF_CCB_CTL *psFCCBCtl = psDevInfo->psFirmwareCCBCtl;
+               const RGXFWIF_CCB_CTL *psFCCBCtl = psDevInfo->psFirmwareCCBCtl;
 
                if (psFCCBCtl != NULL)
                {
@@ -5557,7 +5438,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
        /* Dump out the Workload estimation CCB. */
        {
-           RGXFWIF_CCB_CTL *psWorkEstCCBCtl = psDevInfo->psWorkEstFirmwareCCBCtl;
+           const RGXFWIF_CCB_CTL *psWorkEstCCBCtl = psDevInfo->psWorkEstFirmwareCCBCtl;
 
            if (psWorkEstCCBCtl != NULL)
            {
@@ -5660,7 +5541,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        /* Dump the FW Sys config flags on the Host */
        if (!PVRSRV_VZ_MODE_IS(GUEST))
        {
-               RGXFWIF_SYSDATA   *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
                IMG_CHAR sFwSysFlagsDescription[MAX_FW_DESCRIPTION_LENGTH];
 
                if (!psFwSysData)
@@ -5675,7 +5556,6 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
        /* Dump the FW OS config flags */
        {
-               RGXFWIF_OSDATA   *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
                IMG_CHAR sFwOsFlagsDescription[MAX_FW_DESCRIPTION_LENGTH];
 
                if (!psFwOsData)
@@ -5702,7 +5582,7 @@ void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
        }
        else
        {
-                       PVR_DUMPDEBUG_LOG(" (!) %s. No registers dumped", PVRSRV_VZ_MODE_IS(GUEST) ? "Guest Mode of operation" : "RGX power is down");
+               PVR_DUMPDEBUG_LOG(" (!) %s. No registers dumped", PVRSRV_VZ_MODE_IS(GUEST) ? "Guest Mode of operation" : "RGX power is down");
        }
 
        PVR_DUMPDEBUG_LOG("------[ RGX FW Trace Info ]------");
@@ -5882,18 +5762,18 @@ static void RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgRequestHandle,
 
 PVRSRV_ERROR RGXDebugInit(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-       return PVRSRVRegisterDbgRequestNotify(&psDevInfo->hDbgReqNotify,
-                                                  psDevInfo->psDeviceNode,
-                                                  RGXDebugRequestNotify,
-                                                                                  DEBUG_REQUEST_SYS,
-                                                  psDevInfo);
+       return PVRSRVRegisterDeviceDbgRequestNotify(&psDevInfo->hDbgReqNotify,
+                                                       psDevInfo->psDeviceNode,
+                                                       RGXDebugRequestNotify,
+                                                       DEBUG_REQUEST_RGX,
+                                                       psDevInfo);
 }
 
 PVRSRV_ERROR RGXDebugDeinit(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
        if (psDevInfo->hDbgReqNotify)
        {
-               return PVRSRVUnregisterDbgRequestNotify(psDevInfo->hDbgReqNotify);
+               return PVRSRVUnregisterDeviceDbgRequestNotify(psDevInfo->hDbgReqNotify);
        }
 
        /* No notifier registered */
index fb03c4d..f163997 100644 (file)
@@ -105,6 +105,9 @@ static inline void RGXDEBUG_PRINT_IRQ_COUNT(PVRSRV_RGXDEV_INFO* psRgxDevInfo)
 #endif /* PVRSRV_NEED_PVR_DPF */
 }
 
+extern const IMG_CHAR * const gapszMipsPermissionPTFlags[4];
+extern const IMG_CHAR * const gapszMipsCoherencyPTFlags[8];
+extern const IMG_CHAR * const gapszMipsDirtyGlobalValidPTFlags[8];
 /*!
 *******************************************************************************
 
@@ -153,51 +156,15 @@ void RGXDumpPowerMonitoring(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                PVRSRV_RGXDEV_INFO  *psDevInfo);
 #endif
 
-/*!
-*******************************************************************************
-
- @Function     RGXReadWithSP
-
- @Description
-
- Reads data from a memory location (FW memory map) using the META Slave Port
-
- @Input  psDevInfo  - Pointer to RGX DevInfo to be used while reading
- @Input  ui32FWAddr - 32 bit FW address
- @Input  pui32Value - When the read is successful, value at above FW address
-                      is returned at this location
-
- @Return PVRSRV_ERROR PVRSRV_OK if read success, error code otherwise.
-******************************************************************************/
-PVRSRV_ERROR RGXReadWithSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 *pui32Value);
-
-/*!
-*******************************************************************************
-
- @Function     RGXWriteWithSP
-
- @Description
-
- Writes data to a memory location (FW memory map) using the META Slave Port
-
- @Input  psDevInfo  - Pointer to RGX DevInfo to be used while writing
- @Input  ui32FWAddr - 32 bit FW address
-
- @Input  ui32Value  - 32 bit Value to write
-
- @Return PVRSRV_ERROR PVRSRV_OK if write success, error code otherwise.
-******************************************************************************/
-PVRSRV_ERROR RGXWriteWithSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 ui32Value);
-
-#if defined(SUPPORT_EXTRA_METASP_DEBUG)
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
 /*!
 *******************************************************************************
 
  @Function     ValidateFWOnLoad
 
  @Description  Compare the Firmware image as seen from the CPU point of view
-               against the same memory area as seen from the META point of view
-               after first power up.
+               against the same memory area as seen from the firmware point
+               of view after first power up.
 
  @Input        psDevInfo - Device Info
 
@@ -236,7 +203,7 @@ void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
 
  @Description
 
- Setup debug requests, calls into PVRSRVRegisterDbgRequestNotify
+ Setup debug requests, calls into PVRSRVRegisterDeviceDbgRequestNotify
 
  @Input          psDevInfo            RGX device info
  @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
@@ -251,7 +218,7 @@ PVRSRV_ERROR RGXDebugInit(PVRSRV_RGXDEV_INFO *psDevInfo);
 
  @Description
 
- Remove debug requests, calls into PVRSRVUnregisterDbgRequestNotify
+ Remove debug requests, calls into PVRSRVUnregisterDeviceDbgRequestNotify
 
  @Output         phNotify             Points to debug notifier handle
  @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
index 5f81c8b..4ebbd29 100644 (file)
@@ -198,6 +198,7 @@ typedef struct _PVRSRV_DEVICE_FEATURE_CONFIG_
        IMG_UINT32 ui32N;
        IMG_UINT32 ui32C;
        IMG_UINT32 ui32FeaturesValues[RGX_FEATURE_WITH_VALUES_MAX_IDX];
+       IMG_UINT32 ui32MAXDMCount;
        IMG_UINT32 ui32MAXDustCount;
        IMG_UINT32 ui32SLCSizeInBytes;
        IMG_PCHAR  pszBVNCString;
@@ -240,11 +241,11 @@ typedef struct _PVRSRV_DEVICE_FEATURE_CONFIG_
  * all corner cases
  */
 #define RETURN_DATA_ARRAY_SIZE_LOG2 (9)
-#define RETURN_DATA_ARRAY_SIZE      ((1UL) << RETURN_DATA_ARRAY_SIZE_LOG2)
+#define RETURN_DATA_ARRAY_SIZE      ((1U) << RETURN_DATA_ARRAY_SIZE_LOG2)
 #define RETURN_DATA_ARRAY_WRAP_MASK (RETURN_DATA_ARRAY_SIZE - 1)
 
 #define WORKLOAD_HASH_SIZE_LOG2                6
-#define WORKLOAD_HASH_SIZE                     ((1UL) << WORKLOAD_HASH_SIZE_LOG2)
+#define WORKLOAD_HASH_SIZE                     ((1U) << WORKLOAD_HASH_SIZE_LOG2)
 #define WORKLOAD_HASH_WRAP_MASK                (WORKLOAD_HASH_SIZE - 1)
 
 /*!
@@ -500,6 +501,8 @@ typedef struct _PVRSRV_RGXDEV_INFO_
 
        DEVMEM_MEMDESC                  *psRGXFWIfHWRInfoBufCtlMemDesc;
        RGXFWIF_HWRINFOBUF              *psRGXFWIfHWRInfoBufCtl;
+       IMG_UINT32                              ui32ClockSource;
+       IMG_UINT32                              ui32LastClockSource;
 
        DEVMEM_MEMDESC                  *psRGXFWIfGpuUtilFWCbCtlMemDesc;
        RGXFWIF_GPU_UTIL_FWCB   *psRGXFWIfGpuUtilFWCb;
@@ -515,6 +518,7 @@ typedef struct _PVRSRV_RGXDEV_INFO_
        DEVMEM_MEMDESC                  *psRGXFWIfConnectionCtlMemDesc;
        RGXFWIF_CONNECTION_CTL  *psRGXFWIfConnectionCtl;
 
+       DEVMEM_MEMDESC                  *psRGXFWHeapGuardPageReserveMemDesc;
        DEVMEM_MEMDESC                  *psRGXFWIfSysInitMemDesc;
        RGXFWIF_SYSINIT                 *psRGXFWIfSysInit;
 
@@ -727,6 +731,15 @@ typedef struct _PVRSRV_RGXDEV_INFO_
        IMG_UINT32                              ui32FirmwareGcovSize;
 #endif
 
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+       struct
+       {
+               IMG_UINT64 ui64timerGray;
+               IMG_UINT64 ui64timerBinary;
+               IMG_UINT64 *pui64uscTimers;
+       } sRGXTimerValues;
+#endif
+
 #if defined(SUPPORT_VALIDATION)
        struct
        {
index 69be089..2e98cd2 100644 (file)
@@ -61,10 +61,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "devicemem_pdump.h"
 #include "devicemem_server.h"
 
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
-
 #include "pvr_debug.h"
 #include "pvr_notifier.h"
 #include "rgxfwutils.h"
@@ -86,6 +82,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dc_server.h"
 #endif
 #include "rgxmem.h"
+#include "rgxmmudefs_km.h"
+#include "rgxmipsmmuinit.h"
 #include "rgxta3d.h"
 #include "rgxkicksync.h"
 #include "rgxutils.h"
@@ -122,6 +120,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxpdvfs.h"
 #endif
 
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+#include "rgxsoctimer.h"
+#endif
+
 #include "vz_vmm_pvz.h"
 #include "rgx_heaps.h"
 
@@ -135,20 +137,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RGXFW_HWPERF_L1_SIZE_DEFAULT    PVRSRV_APPHINT_HWPERFFWBUFSIZEINKB
 #define RGXFW_HWPERF_L1_SIZE_MAX        (12288U)
 
-/* Kernel CCB length */
-#define RGXFW_KCCB_SIZE_MIN_LOG2 (4)
-#define RGXFW_KCCB_SIZE_MAX_LOG2 (16)
-
-#if PVRSRV_APPHINT_KCCB_SIZE_LOG2 > RGXFW_KCCB_SIZE_MAX_LOG2
-#define RGXFWIF_KCCB_NUMCMDS_LOG2 RGXFW_KCCB_SIZE_MAX_LOG2
-#warning PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too high.
-#elif PVRSRV_APPHINT_KCCB_SIZE_LOG2 < RGXFW_KCCB_SIZE_MIN_LOG2
-#define RGXFWIF_KCCB_NUMCMDS_LOG2 RGXFW_KCCB_SIZE_MIN_LOG2
-#warning PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too low.
-#else
-#define RGXFWIF_KCCB_NUMCMDS_LOG2    PVRSRV_APPHINT_KCCB_SIZE_LOG2
-#endif
-
 /* Firmware CCB length */
 #if defined(NO_HARDWARE) && defined(PDUMP)
 #define RGXFWIF_FWCCB_NUMCMDS_LOG2   (10)
@@ -171,9 +159,8 @@ const IMG_UINT32 gaui32FwOsIrqCntRegAddr[RGXFW_MAX_NUM_OS] = {IRQ_COUNTER_STORAG
  * are often run on EMU, FPGA or in CSim.
  */
 #if defined(FPGA) || defined(EMULATOR) || defined(VIRTUAL_PLATFORM) || defined(PDUMP)
-/*#warning "Using FPGA WORKLOAD_DEADLINE!!!!!!!!!!!!!!!!!!"*/
-#define RGXFWIF_MAX_WORKLOAD_DEADLINE_MS     (800000)//(80000)
-#define RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS (2500000)//(1000000)
+#define RGXFWIF_MAX_WORKLOAD_DEADLINE_MS     (480000)
+#define RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS (1000000)
 #else
 #define RGXFWIF_MAX_WORKLOAD_DEADLINE_MS     (40000)
 #define RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS (90000)
@@ -190,7 +177,7 @@ typedef struct
 {
        RGXFWIF_KCCB_CMD        sKCCBcmd;
        DLLIST_NODE             sListNode;
-       PDUMP_FLAGS_T           uiPdumpFlags;
+       PDUMP_FLAGS_T           uiPDumpFlags;
        PVRSRV_RGXDEV_INFO      *psDevInfo;
 } RGX_DEFERRED_KCCB_CMD;
 
@@ -206,6 +193,7 @@ static_assert(sizeof(IMG_PID) == sizeof(IMG_UINT32),
 static void RGXFreeFwOsData(PVRSRV_RGXDEV_INFO *psDevInfo);
 static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo);
 
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
 static PVRSRV_ERROR _AllocateSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo, RGXFWIF_SYSINIT* psFwSysInit)
 {
        PVRSRV_ERROR eError;
@@ -252,16 +240,21 @@ static void _FreeSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo)
                DevmemFree(psSLC3FenceMemDesc);
        }
 }
+#endif
 
 static void __MTSScheduleWrite(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Value)
 {
        /* ensure memory is flushed before kicking MTS */
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(NULL);
 
        OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_SCHEDULE, ui32Value);
 
        /* ensure the MTS kick goes through before continuing */
-       OSMemoryBarrier();
+#if !defined(NO_HARDWARE) && !defined(INTEGRITY_OS)
+       OSWriteMemoryBarrier((IMG_BYTE*) psDevInfo->pvRegsBaseKM + RGX_CR_MTS_SCHEDULE);
+#else
+       OSWriteMemoryBarrier(NULL);
+#endif
 }
 
 /*************************************************************************/ /*!
@@ -309,7 +302,7 @@ PVRSRV_ERROR RGXSetupFwAllocation(PVRSRV_RGXDEV_INFO*  psDevInfo,
        }
 #endif
 
-       PDUMPCOMMENT("Allocate %s", pszName);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate %s", pszName);
        eError = DevmemFwAllocate(psDevInfo,
                                                          ui32Size,
                                                          uiAllocFlags,
@@ -387,10 +380,10 @@ PVRSRV_ERROR RGXSetupFwAllocation(PVRSRV_RGXDEV_INFO*  psDevInfo,
 #endif
        }
 
-       PVR_DPF((PVR_DBG_MESSAGE, "%s: %s set up at Fw VA 0x%x and CPU VA 0x%llx with alloc flags 0x%" IMG_UINT64_FMTSPECX,
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: %s set up at Fw VA 0x%x and CPU VA 0x%p with alloc flags 0x%" IMG_UINT64_FMTSPECX,
                         __func__, pszName,
                         (psFwPtr)   ? (psFwPtr->ui32Addr) : (0),
-                        (ppvCpuPtr) ? (long long unsigned int)(*ppvCpuPtr) : (long long unsigned int)(NULL),
+                        (ppvCpuPtr) ? (*ppvCpuPtr)        : (NULL),
                         uiAllocFlags));
 
        return eError;
@@ -524,7 +517,7 @@ static PVRSRV_ERROR RGXFWSetupFirmwareGcovBuffer(PVRSRV_RGXDEV_INFO*                        psDevInfo
                                                                  &psFirmwareGcovCtl->sBuffer,
                                                                  NULL,
                                                                  RFW_FWADDR_NOREF_FLAG);
-       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXSetupFwAllocation");
 
        psFirmwareGcovCtl->ui32Size = ui32FirmwareGcovBufferSize;
 
@@ -604,8 +597,8 @@ static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        /* Allocate memory for the checks */
        eError = RGXSetupFwAllocation(psDevInfo,
-                                                                 (RGX_FWINITDATA_WC_ALLOCFLAGS &
-                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp)),
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
                                                                  ui32RGXFWAlignChecksTotal,
                                                                  "FwAlignmentChecks",
                                                                  &psDevInfo->psRGXFWAlignChecksMemDesc,
@@ -625,7 +618,7 @@ static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_DEVICE_NODE *psDeviceNode,
                *paui32AlignChecks = 0;
        }
 
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(paui32AlignChecks);
 
        DevmemPDumpLoadMem(psDevInfo->psRGXFWAlignChecksMemDesc,
                                                0,
@@ -662,6 +655,7 @@ PVRSRV_ERROR RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR     *ppDest,
        psDeviceNode = (PVRSRV_DEVICE_NODE *) DevmemGetConnection(psSrc);
        psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
                IMG_UINT32          ui32Offset;
@@ -706,7 +700,9 @@ PVRSRV_ERROR RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR     *ppDest,
                }
                ppDest->ui32Addr = ui32Offset;
        }
-       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       else
+#endif
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
                eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
                PVR_GOTO_IF_ERROR(eError, failDevVAAcquire);
@@ -762,8 +758,10 @@ PVRSRV_ERROR RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR    *ppDest,
 
        return PVRSRV_OK;
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 failDevCacheMode:
        DevmemReleaseDevVirtAddr(psSrc);
+#endif
 failDevVAAcquire:
        return eError;
 }
@@ -808,7 +806,7 @@ struct _RGX_SERVER_COMMON_CONTEXT_ {
        DLLIST_NODE sListNode;
        RGX_CONTEXT_RESET_REASON eLastResetReason;
        IMG_UINT32 ui32LastResetJobRef;
-       IMG_UINT32 ui32Priority;
+       IMG_INT32 i32Priority;
        RGX_CCB_REQUESTOR_TYPE eRequestor;
 };
 
@@ -816,16 +814,16 @@ struct _RGX_SERVER_COMMON_CONTEXT_ {
 @Function       _CheckPriority
 @Description    Check if priority is allowed for requestor type
 @Input          psDevInfo    pointer to DevInfo struct
-@Input          ui32Priority Requested priority
+@Input          i32Priority Requested priority
 @Input          eRequestor   Requestor type specifying data master
 @Return         PVRSRV_ERROR PVRSRV_OK on success
 */ /**************************************************************************/
 static PVRSRV_ERROR _CheckPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
-                                                                  IMG_UINT32 ui32Priority,
+                                                                  IMG_INT32 i32Priority,
                                                                   RGX_CCB_REQUESTOR_TYPE eRequestor)
 {
        /* Only one context allowed with real time priority (highest priority) */
-       if (ui32Priority == RGX_CTX_PRIORITY_REALTIME)
+       if (i32Priority == RGX_CTX_PRIORITY_REALTIME)
        {
                DLLIST_NODE *psNode, *psNext;
 
@@ -834,7 +832,7 @@ static PVRSRV_ERROR _CheckPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
                        RGX_SERVER_COMMON_CONTEXT *psThisContext =
                                IMG_CONTAINER_OF(psNode, RGX_SERVER_COMMON_CONTEXT, sListNode);
 
-                       if (psThisContext->ui32Priority == RGX_CTX_PRIORITY_REALTIME &&
+                       if (psThisContext->i32Priority == RGX_CTX_PRIORITY_REALTIME &&
                                psThisContext->eRequestor == eRequestor)
                        {
                                PVR_LOG(("Only one context with real time priority allowed"));
@@ -864,15 +862,12 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
                RGX_COMMON_CONTEXT_INFO *psInfo,
                RGX_SERVER_COMMON_CONTEXT **ppsServerCommonContext)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
        RGXFWIF_FWCOMMONCONTEXT *psFWCommonContext;
        IMG_UINT32 ui32FWCommonContextOffset;
        IMG_UINT8 *pui8Ptr;
+       IMG_INT32 i32Priority = (IMG_INT32)ui32Priority;
        PVRSRV_ERROR eError;
 
        /*
@@ -890,7 +885,8 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
 
        if (psAllocatedMemDesc)
        {
-               PDUMPCOMMENT("Using existing MemDesc for Rogue firmware %s context (offset = %d)",
+               PDUMPCOMMENT(psDeviceNode,
+                                        "Using existing MemDesc for Rogue firmware %s context (offset = %d)",
                                aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
                                ui32AllocatedOffset);
                ui32FWCommonContextOffset = ui32AllocatedOffset;
@@ -900,7 +896,8 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
        else
        {
                /* Allocate device memory for the firmware context */
-               PDUMPCOMMENT("Allocate Rogue firmware %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
+               PDUMPCOMMENT(psDeviceNode,
+                                        "Allocate Rogue firmware %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
                eError = DevmemFwAllocate(psDevInfo,
                                sizeof(*psFWCommonContext),
                                RGX_FWCOMCTX_ALLOCFLAGS,
@@ -974,6 +971,7 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
                        0, RFW_FWADDR_FLAG_NONE);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", fail_cccbctrlfwaddr);
 
+#if defined(RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
        {
                RGXSetMetaDMAAddress(&psFWCommonContext->sCCBMetaDMAAddr,
@@ -981,6 +979,7 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
                                &psFWCommonContext->psCCB,
                                0);
        }
+#endif
 
        /* Set the memory context device address */
        psServerCommonContext->psFWMemContextMemDesc = psFWMemContextMemDesc;
@@ -1006,13 +1005,13 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
                psFWCommonContext->psRFCmd.ui32Addr = 0;
        }
 
-       eError = _CheckPriority(psDevInfo, ui32Priority, eRGXCCBRequestor);
+       eError = _CheckPriority(psDevInfo, i32Priority, eRGXCCBRequestor);
        PVR_LOG_GOTO_IF_ERROR(eError, "_CheckPriority", fail_checkpriority);
 
-       psServerCommonContext->ui32Priority = ui32Priority;
+       psServerCommonContext->i32Priority = i32Priority;
        psServerCommonContext->eRequestor = eRGXCCBRequestor;
 
-       psFWCommonContext->ui32Priority = ui32Priority;
+       psFWCommonContext->i32Priority = i32Priority;
        psFWCommonContext->ui32PrioritySeqNum = 0;
        psFWCommonContext->ui32MaxDeadlineMS = MIN(ui32MaxDeadlineMS,
                                                                                           (eDM == RGXFWIF_DM_CDM ?
@@ -1038,24 +1037,13 @@ PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
        /*
         * Dump the created context
         */
-       PDUMPCOMMENT("Dump %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
+       PDUMPCOMMENT(psDeviceNode,
+                                "Dump %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
        DevmemPDumpLoadMem(psServerCommonContext->psFWCommonContextMemDesc,
                        ui32FWCommonContextOffset,
                        sizeof(*psFWCommonContext),
                        PDUMP_FLAGS_CONTINUOUS);
 
-
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psServerCommonContext->psFWCommonContextMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               printk("called by %pS, the psAllocatedMemDesc:%llx\n", __builtin_return_address(0), (unsigned long long)psAllocatedMemDesc);
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                       printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                       BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pui8Ptr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
-
        /* We've finished the setup so release the CPU mapping */
        DevmemReleaseCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc);
 
@@ -1234,8 +1222,21 @@ PVRSRV_ERROR RGXGetFWCommonContextAddrFromServerMMUCtx(PVRSRV_RGXDEV_INFO *psDev
 PVRSRV_ERROR FWCommonContextSetFlags(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
                                      IMG_UINT32 ui32ContextFlags)
 {
-       return RGXSetCCBFlags(psServerCommonContext->psClientCCB,
-                             ui32ContextFlags);
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (BITMASK_ANY(ui32ContextFlags, ~RGX_CONTEXT_FLAGS_WRITEABLE_MASK))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Context flag(s) invalid or not writeable (%d)",
+                                __func__, ui32ContextFlags));
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       else
+       {
+               RGXSetCCBFlags(psServerCommonContext->psClientCCB,
+                                          ui32ContextFlags);
+       }
+
+       return eError;
 }
 
 /*!
@@ -1343,12 +1344,21 @@ static PVRSRV_ERROR RGXSetupCCB(PVRSRV_RGXDEV_INFO      *psDevInfo,
 
        if (unlikely(iStrLen < 0))
        {
-               szCCBCtlName[0] = '\0';
+               OSStringLCopy(szCCBCtlName, "FwCCBControl", DEVMEM_ANNOTATION_MAX_LEN);
        }
 
        /* Allocate memory for the CCB control.*/
        eError = RGXSetupFwAllocation(psDevInfo,
-                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
+                                                                 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                 PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                                                 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                                 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED |
+                                                                 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                                 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                 PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
                                                                  sizeof(RGXFWIF_CCB_CTL),
                                                                  szCCBCtlName,
                                                                  ppsCCBCtlMemDesc,
@@ -1381,7 +1391,7 @@ static PVRSRV_ERROR RGXSetupCCB(PVRSRV_RGXDEV_INFO        *psDevInfo,
        psCCBCtl->ui32CmdSize = ui32CmdSize;
 
        /* Pdump the CCB control */
-       PDUMPCOMMENT("Initialise %s", szCCBCtlName);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Initialise %s", szCCBCtlName);
        DevmemPDumpLoadMem(*ppsCCBCtlMemDesc,
                                           0,
                                           sizeof(RGXFWIF_CCB_CTL),
@@ -1430,7 +1440,7 @@ static PVRSRV_ERROR RGXSetupFaultReadRegister(PVRSRV_DEVICE_NODE  *psDeviceNode,
        eError = DevmemFwAllocateExportable(psDeviceNode,
                        ui32PageSize,
                        ui32PageSize,
-                       RGX_FWINITDATA_WC_ALLOCFLAGS & ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+                       RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS & ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
                        "FwExFaultAddress",
                        &psDevInfo->psRGXFaultAddressMemDesc);
 
@@ -1461,7 +1471,7 @@ static PVRSRV_ERROR RGXSetupFaultReadRegister(PVRSRV_DEVICE_NODE  *psDeviceNode,
                }
        }
 
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(pui32MemoryVirtAddr);
 
        DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
 
@@ -1646,7 +1656,7 @@ PVRSRV_ERROR RGXTBIBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO *psDevInfo)
        }
 
        /* flush write buffers for psFW_SFs */
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(psFW_SFs);
 
        /* Set size of TBI buffer */
        psDevInfo->ui32FWIfTBIBufferSize = ui32FWTBIBufsize;
@@ -1748,8 +1758,9 @@ PVRSRV_ERROR RGXTraceBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO* psDevInfo,
        /* Check AppHint value for module-param FWTraceBufSizeInDWords */
        OSCreateKMAppHintState(&pvAppHintState);
        ui32DefaultTraceBufSize = RGXFW_TRACE_BUF_DEFAULT_SIZE_IN_DWORDS;
-       OSGetKMAppHintUINT32(pvAppHintState,
-                            FWTraceBufSizeInDWords,
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                                pvAppHintState,
+                                                FWTraceBufSizeInDWords,
                                                 &ui32DefaultTraceBufSize,
                                                 &psTraceBufCtl->ui32TraceBufSizeInDWords);
        OSFreeKMAppHintState(pvAppHintState);
@@ -1803,48 +1814,55 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
        IMG_UINT32 ui32ConfigFlags    = psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags;
        IMG_UINT32 ui32FwOsCfgFlags   = psDevInfo->psRGXFWIfFwOsData->ui32FwOsConfigFlags;
 
-       PDUMPCOMMENT("Dump RGXFW Init data");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Dump RGXFW Init data");
        if (!bEnableSignatureChecks)
        {
-               PDUMPCOMMENT("(to enable rgxfw signatures place the following line after the RTCONF line)");
+               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                        "(to enable rgxfw signatures place the following line after the RTCONF line)");
                DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
                                                   offsetof(RGXFWIF_SYSINIT, asSigBufCtl),
                                                   sizeof(RGXFWIF_SIGBUF_CTL)*(RGXFWIF_DM_MAX),
                                                   PDUMP_FLAGS_CONTINUOUS);
        }
 
-       PDUMPCOMMENT("Dump initial state of FW runtime configuration");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump initial state of FW runtime configuration");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
                                           0,
                                           sizeof(RGXFWIF_RUNTIME_CFG),
                                           PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Dump rgxfw hwperfctl structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw hwperfctl structure");
        DevmemPDumpLoadZeroMem(psDevInfo->psRGXFWIfHWPerfCountersMemDesc,
                                                   0,
                                                   ui32HWPerfCountersDataSize,
                                                   PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Dump rgxfw trace control structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw trace control structure");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
                                           0,
                                           sizeof(RGXFWIF_TRACEBUF),
                                           PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Dump firmware system data structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump firmware system data structure");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfFwSysDataMemDesc,
                                           0,
                                           sizeof(RGXFWIF_SYSDATA),
                                           PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Dump firmware OS data structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump firmware OS data structure");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfFwOsDataMemDesc,
                                           0,
                                           sizeof(RGXFWIF_OSDATA),
                                           PDUMP_FLAGS_CONTINUOUS);
 
 #if defined(SUPPORT_TBI_INTERFACE)
-       PDUMPCOMMENT("Dump rgx TBI buffer");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgx TBI buffer");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfTBIBufferMemDesc,
                                           0,
                                           psDevInfo->ui32FWIfTBIBufferSize,
@@ -1852,88 +1870,116 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
 #endif /* defined(SUPPORT_TBI_INTERFACE) */
 
 #if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
-       PDUMPCOMMENT("Dump rgxfw register configuration buffer");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw register configuration buffer");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfRegCfgMemDesc,
                                           0,
                                           sizeof(RGXFWIF_REG_CFG),
                                           PDUMP_FLAGS_CONTINUOUS);
 #endif /* defined(SUPPORT_USER_REGISTER_CONFIGURATION) */
-       PDUMPCOMMENT("Dump rgxfw system init structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw system init structure");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
                                           0,
                                           sizeof(RGXFWIF_SYSINIT),
                                           PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Dump rgxfw os init structure");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw os init structure");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWIfOsInitMemDesc,
                                           0,
                                           sizeof(RGXFWIF_OSINIT),
                                           PDUMP_FLAGS_CONTINUOUS);
 
        /* RGXFW Init structure needs to be loaded before we overwrite FaultPhysAddr, else this address patching won't have any effect */
-       PDUMPCOMMENT("Overwrite FaultPhysAddr of FwSysInit in pdump with actual physical address");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Overwrite FaultPhysAddr of FwSysInit in pdump with actual physical address");
        RGXPDumpFaultReadRegister(psDevInfo);
 
-       PDUMPCOMMENT("RTCONF: run-time configuration");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "RTCONF: run-time configuration");
 
 
        /* Dump the config options so they can be edited.
         *
         */
-       PDUMPCOMMENT("(Set the FW system config options here)");
-       PDUMPCOMMENT("( Ctx Switch Rand mode:                      0x%08x)", RGXFWIF_INICFG_CTXSWITCH_MODE_RAND);
-       PDUMPCOMMENT("( Ctx Switch Soft Reset Enable:              0x%08x)", RGXFWIF_INICFG_CTXSWITCH_SRESET_EN);
-       PDUMPCOMMENT("( Enable HWPerf:                             0x%08x)", RGXFWIF_INICFG_HWPERF_EN);
-       PDUMPCOMMENT("( Enable generic DM Killing Rand mode:       0x%08x)", RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN);
-       PDUMPCOMMENT("( Rascal+Dust Power Island:                  0x%08x)", RGXFWIF_INICFG_POW_RASCALDUST);
-       PDUMPCOMMENT("( FBCDC Version 3.1 Enable:                  0x%08x)", RGXFWIF_INICFG_FBCDC_V3_1_EN);
-       PDUMPCOMMENT("( Check MList:                               0x%08x)", RGXFWIF_INICFG_CHECK_MLIST_EN);
-       PDUMPCOMMENT("( Disable Auto Clock Gating:                 0x%08x)", RGXFWIF_INICFG_DISABLE_CLKGATING_EN);
-       PDUMPCOMMENT("( Enable HWPerf Polling Perf Counter:        0x%08x)", RGXFWIF_INICFG_POLL_COUNTERS_EN);
-
-       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, VDM_OBJECT_LEVEL_LLS))
-       {
-       PDUMPCOMMENT("( Ctx Switch Object mode Index:              0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INDEX);
-       PDUMPCOMMENT("( Ctx Switch Object mode Instance:           0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_INSTANCE);
-       PDUMPCOMMENT("( Ctx Switch Object mode List:               0x%08x)", RGXFWIF_INICFG_VDM_CTX_STORE_MODE_LIST);
-       }
-
-       PDUMPCOMMENT("( Enable register configuration:             0x%08x)", RGXFWIF_INICFG_REGCONFIG_EN);
-       PDUMPCOMMENT("( Assert on TA Out-of-Memory:                0x%08x)", RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY);
-       PDUMPCOMMENT("( Disable HWPerf custom counter filter:      0x%08x)", RGXFWIF_INICFG_HWP_DISABLE_FILTER);
-       PDUMPCOMMENT("( Enable HWPerf custom performance timer:    0x%08x)", RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN);
-       PDUMPCOMMENT("( Enable Ctx Switch profile mode: 0x%08x (none=b'000, fast=b'001, medium=b'010, slow=b'011, nodelay=b'100))", RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK);
-       PDUMPCOMMENT("( Disable DM overlap (except TA during SPM): 0x%08x)", RGXFWIF_INICFG_DISABLE_DM_OVERLAP);
-       PDUMPCOMMENT("( Assert on HWR trigger (page fault, lockup, overrun or poll failure): 0x%08x)", RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER);
-       PDUMPCOMMENT("( Enable coherent memory accesses:           0x%08x)", RGXFWIF_INICFG_FABRIC_COHERENCY_ENABLED);
-       PDUMPCOMMENT("( Enable IRQ validation:                     0x%08x)", RGXFWIF_INICFG_VALIDATE_IRQ);
-       PDUMPCOMMENT("( SPU power state mask change Enable:        0x%08x)", RGXFWIF_INICFG_SPU_POWER_STATE_MASK_CHANGE_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the FW system config options here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch Rand mode:                      0x%08x)", RGXFWIF_INICFG_CTXSWITCH_MODE_RAND);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch Soft Reset Enable:              0x%08x)", RGXFWIF_INICFG_CTXSWITCH_SRESET_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable HWPerf:                             0x%08x)", RGXFWIF_INICFG_HWPERF_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable generic DM Killing Rand mode:       0x%08x)", RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Rascal+Dust Power Island:                  0x%08x)", RGXFWIF_INICFG_POW_RASCALDUST);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( FBCDC Version 3.1 Enable:                  0x%08x)", RGXFWIF_INICFG_FBCDC_V3_1_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Check MList:                               0x%08x)", RGXFWIF_INICFG_CHECK_MLIST_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable Auto Clock Gating:                 0x%08x)", RGXFWIF_INICFG_DISABLE_CLKGATING_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable register configuration:             0x%08x)", RGXFWIF_INICFG_REGCONFIG_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Assert on TA Out-of-Memory:                0x%08x)", RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable HWPerf custom counter filter:      0x%08x)", RGXFWIF_INICFG_HWP_DISABLE_FILTER);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Ctx Switch profile mode: 0x%08x (none=b'000, fast=b'001, medium=b'010, slow=b'011, nodelay=b'100))", RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable DM overlap (except TA during SPM): 0x%08x)", RGXFWIF_INICFG_DISABLE_DM_OVERLAP);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Assert on HWR trigger (page fault, lockup, overrun or poll failure): 0x%08x)", RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable coherent memory accesses:           0x%08x)", RGXFWIF_INICFG_FABRIC_COHERENCY_ENABLED);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable IRQ validation:                     0x%08x)", RGXFWIF_INICFG_VALIDATE_IRQ);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( SPU power state mask change Enable:        0x%08x)", RGXFWIF_INICFG_SPU_POWER_STATE_MASK_CHANGE_EN);
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-       PDUMPCOMMENT("( Enable Workload Estimation:                0x%08x)", RGXFWIF_INICFG_WORKEST);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Workload Estimation:                0x%08x)", RGXFWIF_INICFG_WORKEST);
 #if defined(SUPPORT_PDVFS)
-       PDUMPCOMMENT("( Enable Proactive DVFS:                     0x%08x)", RGXFWIF_INICFG_PDVFS);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Proactive DVFS:                     0x%08x)", RGXFWIF_INICFG_PDVFS);
 #endif /* defined(SUPPORT_PDVFS) */
 #endif /* defined(SUPPORT_WORKLOAD_ESTIMATION) */
-       PDUMPCOMMENT("( CDM Arbitration Mode (task demand=b'01, round robin=b'10): 0x%08x)", RGXFWIF_INICFG_CDM_ARBITRATION_MASK);
-       PDUMPCOMMENT("( ISP Scheduling Mode (v1=b'01, v2=b'10):    0x%08x)", RGXFWIF_INICFG_ISPSCHEDMODE_MASK);
-       PDUMPCOMMENT("( Validate SOC & USC timers:                 0x%08x)", RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CDM Arbitration Mode (task demand=b'01, round robin=b'10): 0x%08x)", RGXFWIF_INICFG_CDM_ARBITRATION_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( ISP Scheduling Mode (v1=b'01, v2=b'10):    0x%08x)", RGXFWIF_INICFG_ISPSCHEDMODE_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Validate SOC & USC timers:                 0x%08x)", RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER);
 
        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwSysDataMemDesc,
                                                        offsetof(RGXFWIF_SYSDATA, ui32ConfigFlags),
                                                        ui32ConfigFlags,
                                                        PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("( Extended FW system config options not used.)");
-
-       PDUMPCOMMENT("(Set the FW OS config options here)");
-       PDUMPCOMMENT("( Ctx Switch TDM Enable:                     0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN);
-       PDUMPCOMMENT("( Ctx Switch TA Enable:                      0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN);
-       PDUMPCOMMENT("( Ctx Switch 3D Enable:                      0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN);
-       PDUMPCOMMENT("( Ctx Switch CDM Enable:                     0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN);
-       PDUMPCOMMENT("( Lower Priority Ctx Switch  2D Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_TDM);
-       PDUMPCOMMENT("( Lower Priority Ctx Switch  TA Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_GEOM);
-       PDUMPCOMMENT("( Lower Priority Ctx Switch  3D Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_3D);
-       PDUMPCOMMENT("( Lower Priority Ctx Switch CDM Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_CDM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Extended FW system config options not used.)");
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the FW OS config options here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch TDM Enable:                     0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch TA Enable:                      0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch 3D Enable:                      0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch CDM Enable:                     0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  2D Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_TDM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  TA Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_GEOM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  3D Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_3D);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch CDM Enable:      0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_CDM);
 
        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwOsDataMemDesc,
                                                          offsetof(RGXFWIF_OSDATA, ui32FwOsConfigFlags),
@@ -1942,11 +1988,16 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 
 #if defined(SUPPORT_SECURITY_VALIDATION)
-       PDUMPCOMMENT("(Select one or more security tests here)");
-       PDUMPCOMMENT("( Read/write FW private data from non-FW contexts: 0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_DATA);
-       PDUMPCOMMENT("( Read/write FW code from non-FW contexts:         0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_CODE);
-       PDUMPCOMMENT("( Execute FW code from non-secure memory:          0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_NONSECURE);
-       PDUMPCOMMENT("( Execute FW code from secure (non-FW) memory:     0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_SECURE);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Select one or more security tests here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Read/write FW private data from non-FW contexts: 0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_DATA);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Read/write FW code from non-FW contexts:         0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_CODE);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Execute FW code from non-secure memory:          0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_NONSECURE);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Execute FW code from secure (non-FW) memory:     0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_SECURE);
 
        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
                                  offsetof(RGXFWIF_SYSINIT, ui32SecurityTestFlags),
@@ -1954,17 +2005,19 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
                                  PDUMP_FLAGS_CONTINUOUS);
 #endif
 
-       PDUMPCOMMENT("( PID filter type: %X=INCLUDE_ALL_EXCEPT, %X=EXCLUDE_ALL_EXCEPT)",
-                       RGXFW_PID_FILTER_INCLUDE_ALL_EXCEPT,
-                       RGXFW_PID_FILTER_EXCLUDE_ALL_EXCEPT);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PID filter type: %X=INCLUDE_ALL_EXCEPT, %X=EXCLUDE_ALL_EXCEPT)",
+                                RGXFW_PID_FILTER_INCLUDE_ALL_EXCEPT,
+                                RGXFW_PID_FILTER_EXCLUDE_ALL_EXCEPT);
 
        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
                        offsetof(RGXFWIF_SYSINIT, sPIDFilter.eMode),
                        psDevInfo->psRGXFWIfSysInit->sPIDFilter.eMode,
                        PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("( PID filter PID/OSID list (Up to %u entries. Terminate with a zero PID))",
-                       RGXFWIF_PID_FILTER_MAX_NUM_PIDS);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PID filter PID/OSID list (Up to %u entries. Terminate with a zero PID))",
+                                RGXFWIF_PID_FILTER_MAX_NUM_PIDS);
        {
                IMG_UINT32 i;
 
@@ -1982,15 +2035,16 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
                        const IMG_DEVMEM_OFFSET_T uiOSIDOff
                        = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_SYSINIT *)0)->sPIDFilter.asItems[i].ui32OSID);
 
-                       PDUMPCOMMENT("(PID and OSID pair %u)", i);
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                                "(PID and OSID pair %u)", i);
 
-                       PDUMPCOMMENT("(PID)");
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(PID)");
                        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
                                                                          uiPIDOff,
                                                                          0,
                                                                          PDUMP_FLAGS_CONTINUOUS);
 
-                       PDUMPCOMMENT("(OSID)");
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(OSID)");
                        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
                                                                          uiOSIDOff,
                                                                          0,
@@ -2001,40 +2055,60 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
        /*
         * Dump the log config so it can be edited.
         */
-       PDUMPCOMMENT("(Set the log config here)");
-       PDUMPCOMMENT("( Log Type: set bit 0 for TRACE, reset for TBI)");
-       PDUMPCOMMENT("( MAIN Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MAIN);
-       PDUMPCOMMENT("( MTS Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MTS);
-       PDUMPCOMMENT("( CLEANUP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CLEANUP);
-       PDUMPCOMMENT("( CSW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CSW);
-       PDUMPCOMMENT("( BIF Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_BIF);
-       PDUMPCOMMENT("( PM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_PM);
-       PDUMPCOMMENT("( RTD Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_RTD);
-       PDUMPCOMMENT("( SPM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_SPM);
-       PDUMPCOMMENT("( POW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_POW);
-       PDUMPCOMMENT("( HWR Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWR);
-       PDUMPCOMMENT("( HWP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWP);
-
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the log config here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Log Type: set bit 0 for TRACE, reset for TBI)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MAIN Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MAIN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MTS Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MTS);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CLEANUP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CLEANUP);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CSW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CSW);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( BIF Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_BIF);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_PM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( RTD Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_RTD);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( SPM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_SPM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( POW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_POW);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( HWR Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWR);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( HWP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWP);
+
+#if defined(RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
        {
-               PDUMPCOMMENT("( DMA Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DMA);
+               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                        "( DMA Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DMA);
        }
+#endif
 
-       PDUMPCOMMENT("( MISC Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MISC);
-       PDUMPCOMMENT("( DEBUG Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DEBUG);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MISC Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MISC);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( DEBUG Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DEBUG);
        DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
                                                          offsetof(RGXFWIF_TRACEBUF, ui32LogType),
                                                          psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType,
                                                          PDUMP_FLAGS_CONTINUOUS);
 
-       PDUMPCOMMENT("Set the HWPerf Filter config here");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Set the HWPerf Filter config here, see \"hwperfbin2jsont -h\"");
        DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfSysInitMemDesc,
                                                          offsetof(RGXFWIF_SYSINIT, ui64HWPerfFilter),
                                                          psDevInfo->psRGXFWIfSysInit->ui64HWPerfFilter,
                                                          PDUMP_FLAGS_CONTINUOUS);
 
 #if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
-       PDUMPCOMMENT("(Number of registers configurations for types(byte index): pow on(%d), dust change(%d), ta(%d), 3d(%d), cdm(%d), tla(%d), TDM(%d))",
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Number of registers configurations for types(byte index): pow on(%d), dust change(%d), ta(%d), 3d(%d), cdm(%d), tla(%d), TDM(%d))",
                                 RGXFWIF_REG_CFG_TYPE_PWR_ON,
                                 RGXFWIF_REG_CFG_TYPE_DUST_CHANGE,
                                 RGXFWIF_REG_CFG_TYPE_TA,
@@ -2056,7 +2130,7 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
                }
        }
 
-       PDUMPCOMMENT("(Set registers here: address, mask, value)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(Set registers here: address, mask, value)");
        DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
                                                          offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Addr),
                                                          0,
@@ -2075,9 +2149,36 @@ static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 /*!
 *******************************************************************************
+ @Function    RGXSetupFwGuardPage
+
+ @Description Allocate a Guard Page at the start of a Guest's Main Heap
+
+ @Input       psDevceNode
+
+ @Return      PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupFwGuardPage(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       PVRSRV_ERROR eError;
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 (RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS |
+                                                                  PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN)),
+                                                                 OSGetPageSize(),
+                                                                 "FwGuardPage",
+                                                                 &psDevInfo->psRGXFWHeapGuardPageReserveMemDesc,
+                                                                 NULL,
+                                                                 NULL,
+                                                                 RFW_FWADDR_FLAG_NONE);
+
+       return eError;
+}
+
+/*!
+*******************************************************************************
  @Function    RGXSetupFwSysData
 
- @Description Setups all system-wide firmware related data
+ @Description Sets up all system-wide firmware related data
 
  @Input       psDevInfo
 
@@ -2122,6 +2223,10 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
        eError = RGXSetupFaultReadRegister(psDeviceNode, psFwSysInitScratch);
        PVR_LOG_GOTO_IF_ERROR(eError, "Fault read register setup", fail);
 
+#if defined(SUPPORT_AUTOVZ)
+       psFwSysInitScratch->ui32VzWdgPeriod = PVR_AUTOVZ_WDG_PERIOD_MS;
+#endif
+
        /* RD Power Island */
        {
                RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
@@ -2171,7 +2276,7 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 
        /* FW trace control structure */
        eError = RGXSetupFwAllocation(psDevInfo,
-                                                                 RGX_FWINITDATA_WC_ALLOCFLAGS &
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
                                                                  RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
                                                                  sizeof(RGXFWIF_TRACEBUF),
                                                                  "FwTraceCtlStruct",
@@ -2237,7 +2342,8 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                /* Check AppHint for GPIO validation mode */
                OSCreateKMAppHintState(&pvAppHintState);
                ui32AppHintDefault = PVRSRV_APPHINT_GPIOVALIDATIONMODE;
-               OSGetKMAppHintUINT32(pvAppHintState,
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                                        pvAppHintState,
                                                         GPIOValidationMode,
                                                         &ui32AppHintDefault,
                                                         &ui32GPIOValidationMode);
@@ -2273,12 +2379,22 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 #if defined(SUPPORT_VALIDATION)
        {
                IMG_UINT32 ui32EnablePollOnChecksumErrorStatus;
+               IMG_UINT32 ui32ApphintDefault = 0;
+               void      *pvAppHintState = NULL;
 
                /* Check AppHint for polling on GPU Checksum status */
-               pvr_apphint_get_uint32(APPHINT_ID_EnablePollOnChecksumErrorStatus, &ui32EnablePollOnChecksumErrorStatus);
+               OSCreateKMAppHintState(&pvAppHintState);
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                                        pvAppHintState,
+                                                        EnablePollOnChecksumErrorStatus,
+                                                        &ui32ApphintDefault,
+                                                        &ui32EnablePollOnChecksumErrorStatus);
+               OSFreeKMAppHintState(pvAppHintState);
+               pvAppHintState = NULL;
 
                switch (ui32EnablePollOnChecksumErrorStatus)
                {
+                       case 0: /* no checking */ break;
                        case 3: psDevInfo->ui32ValidationFlags |= RGX_VAL_KZ_SIG_CHECK_NOERR_EN; break;
                        case 4: psDevInfo->ui32ValidationFlags |= RGX_VAL_KZ_SIG_CHECK_ERR_EN; break;
                        default:
@@ -2320,6 +2436,10 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
        PVR_LOG_GOTO_IF_ERROR(eError, "3D Signature check setup", fail);
        psDevInfo->ui32Sig3DChecksSize = ui32SignatureChecksBufSize;
 
+       psDevInfo->psRGXFWSigTDM2DChecksMemDesc = NULL;
+       psDevInfo->ui32SigTDM2DChecksSize = 0;
+
+#if defined(RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TDM_PDS_CHECKSUM))
        {
                /* Buffer allocated only when feature present because, all known TDM
@@ -2331,11 +2451,6 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                PVR_LOG_GOTO_IF_ERROR(eError, "TDM Signature check setup", fail);
                psDevInfo->ui32SigTDM2DChecksSize = ui32SignatureChecksBufSize;
        }
-       else
-       {
-               psDevInfo->psRGXFWSigTDM2DChecksMemDesc = NULL;
-               psDevInfo->ui32SigTDM2DChecksSize = 0;
-       }
 #endif
 
        if (!bEnableSignatureChecks)
@@ -2344,6 +2459,7 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_GEOM].sBuffer.ui32Addr = 0x0;
                psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_3D].sBuffer.ui32Addr = 0x0;
        }
+#endif /* defined(PDUMP) */
 
        eError = RGXFWSetupAlignChecks(psDeviceNode,
                                                                   &psFwSysInitScratch->sAlignChecks);
@@ -2351,34 +2467,39 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 
        psFwSysInitScratch->ui32FilterFlags = ui32FilterFlags;
 
+       /* Fill the remaining bits of fw the init data */
+       psFwSysInitScratch->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
+       psFwSysInitScratch->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
+       psFwSysInitScratch->sFBCDCStateTableBase.uiAddr = RGX_FBCDC_HEAP_BASE;
+       psFwSysInitScratch->sFBCDCLargeStateTableBase.uiAddr = RGX_FBCDC_LARGE_HEAP_BASE;
+       psFwSysInitScratch->sTextureHeapBase.uiAddr = RGX_TEXTURE_STATE_HEAP_BASE;
+
+#if defined(FIX_HW_BRN_65273_BIT_MASK)
        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 65273))
        {
                /* Fill the remaining bits of fw the init data */
                psFwSysInitScratch->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_BRN_65273_HEAP_BASE;
                psFwSysInitScratch->sUSCExecBase.uiAddr = RGX_USCCODE_BRN_65273_HEAP_BASE;
        }
-       else
-       {
-               /* Fill the remaining bits of fw the init data */
-               psFwSysInitScratch->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
-               psFwSysInitScratch->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
-       }
+#endif
 
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                psFwSysInitScratch->ui32JonesDisableMask = ui32JonesDisableMask;
        }
-
+#endif
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, SLC_VIVT))
        {
                eError = _AllocateSLC3Fence(psDevInfo, psFwSysInitScratch);
                PVR_LOG_GOTO_IF_ERROR(eError, "SLC3Fence memory allocation", fail);
        }
-
+#endif
 #if defined(SUPPORT_PDVFS)
        /* Core clock rate */
        eError = RGXSetupFwAllocation(psDevInfo,
-                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                                                 RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS &
                                                                  RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
                                                                  sizeof(IMG_UINT32),
                                                                  "FwPDVFSCoreClkRate",
@@ -2389,25 +2510,26 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
        PVR_LOG_GOTO_IF_ERROR(eError, "PDVFS core clock rate memory setup", fail);
 #endif
        {
-       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags;
        /* Timestamps */
-       uiMemAllocFlags =
+       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags =
                PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) |
                PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
                PVRSRV_MEMALLOCFLAG_GPU_READABLE | /* XXX ?? */
+               PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
                PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
                PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
                PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-               PVRSRV_MEMALLOCFLAG_UNCACHED |
                PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
 
        /*
          the timer query arrays
        */
-       PDUMPCOMMENT("Allocate timer query arrays (FW)");
+       PDUMPCOMMENT(psDeviceNode, "Allocate timer query arrays (FW)");
        eError = DevmemFwAllocate(psDevInfo,
                                  sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
-                                 uiMemAllocFlags,
+                                 uiMemAllocFlags |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
                                  "FwStartTimesArray",
                                  &psDevInfo->psStartTimeMemDesc);
        if (eError != PVRSRV_OK)
@@ -2431,7 +2553,8 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 
        eError = DevmemFwAllocate(psDevInfo,
                                  sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
-                                 uiMemAllocFlags,
+                                 uiMemAllocFlags |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
                                  "FwEndTimesArray",
                                  & psDevInfo->psEndTimeMemDesc);
        if (eError != PVRSRV_OK)
@@ -2568,10 +2691,8 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfInitOnDemandResources", fail);
        }
 
-       RGXHWPerfInitAppHintCallbacks(psDeviceNode);
-
        eError = RGXSetupFwAllocation(psDevInfo,
-                                                                 RGX_FWINITDATA_WC_ALLOCFLAGS &
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
                                                                  RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
                                                                  ui32HWPerfCountersDataSize,
                                                                  "FwHWPerfControlStructure",
@@ -2606,10 +2727,10 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 
 #if defined(SUPPORT_SECURITY_VALIDATION)
        {
-               PVRSRV_MEMALLOCFLAGS_T uiFlags = RGX_FWSHAREDMEM_ALLOCFLAGS;
+               PVRSRV_MEMALLOCFLAGS_T uiFlags = RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS;
                PVRSRV_SET_PHYS_HEAP_HINT(GPU_SECURE, uiFlags);
 
-               PDUMPCOMMENT("Allocate non-secure buffer for security validation test");
+               PDUMPCOMMENT(psDeviceNode, "Allocate non-secure buffer for security validation test");
                eError = DevmemFwAllocateExportable(psDeviceNode,
                                                                                        OSGetPageSize(),
                                                                                        OSGetPageSize(),
@@ -2623,7 +2744,7 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                                                                           0, RFW_FWADDR_NOREF_FLAG);
                PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", fail);
 
-               PDUMPCOMMENT("Allocate secure buffer for security validation test");
+               PDUMPCOMMENT(psDeviceNode, "Allocate secure buffer for security validation test");
                eError = DevmemFwAllocateExportable(psDeviceNode,
                                                                                        OSGetPageSize(),
                                                                                        OSGetPageSize(),
@@ -2639,6 +2760,14 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
        }
 #endif /* SUPPORT_SECURITY_VALIDATION */
 
+#if defined(RGX_FEATURE_TFBC_LOSSY_37_PERCENT_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_LOSSY_37_PERCENT) || RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_DELTA_CORRELATION))
+       {
+               psFwSysInitScratch->ui32TFBCCompressionControl =
+                       (ui32ConfigFlagsExt & RGXFWIF_INICFG_EXT_TFBC_CONTROL_MASK) >> RGXFWIF_INICFG_EXT_TFBC_CONTROL_SHIFT;
+       }
+#endif
+
        /* Initialize FW started flag */
        psFwSysInitScratch->bFirmwareStarted = IMG_FALSE;
        psFwSysInitScratch->ui32MarkerVal = 1;
@@ -2661,14 +2790,21 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                psRuntimeCfg->ui32WdgPeriodUs = RGXFW_SAFETY_WATCHDOG_PERIOD_IN_US;
                psRuntimeCfg->ui32HCSDeadlineMS = RGX_HCS_DEFAULT_DEADLINE_MS;
 
-               for (ui32OSIndex = 0; ui32OSIndex < RGX_NUM_OS_SUPPORTED; ui32OSIndex++)
+               if (PVRSRV_VZ_MODE_IS(NATIVE))
+               {
+                       psRuntimeCfg->aui32OSidPriority[RGXFW_HOST_OS] = 0;
+               }
+               else
                {
-                       const IMG_INT32 ai32DefaultOsPriority[RGXFW_MAX_NUM_OS] =
-                               {RGX_OSID_0_DEFAULT_PRIORITY, RGX_OSID_1_DEFAULT_PRIORITY, RGX_OSID_2_DEFAULT_PRIORITY, RGX_OSID_3_DEFAULT_PRIORITY,
-                                RGX_OSID_4_DEFAULT_PRIORITY, RGX_OSID_5_DEFAULT_PRIORITY, RGX_OSID_6_DEFAULT_PRIORITY, RGX_OSID_7_DEFAULT_PRIORITY};
+                       for (ui32OSIndex = 0; ui32OSIndex < RGX_NUM_OS_SUPPORTED; ui32OSIndex++)
+                       {
+                               const IMG_INT32 ai32DefaultOsPriority[RGXFW_MAX_NUM_OS] =
+                                       {RGX_OSID_0_DEFAULT_PRIORITY, RGX_OSID_1_DEFAULT_PRIORITY, RGX_OSID_2_DEFAULT_PRIORITY, RGX_OSID_3_DEFAULT_PRIORITY,
+                                        RGX_OSID_4_DEFAULT_PRIORITY, RGX_OSID_5_DEFAULT_PRIORITY, RGX_OSID_6_DEFAULT_PRIORITY, RGX_OSID_7_DEFAULT_PRIORITY};
 
-                       /* Set up initial priorities between different OSes */
-                       psRuntimeCfg->aui32OSidPriority[ui32OSIndex] = (IMG_UINT32)ai32DefaultOsPriority[ui32OSIndex];
+                               /* Set up initial priorities between different OSes */
+                               psRuntimeCfg->aui32OSidPriority[ui32OSIndex] = (IMG_UINT32)ai32DefaultOsPriority[ui32OSIndex];
+                       }
                }
 
 #if defined(PVR_ENABLE_PHR) && defined(PDUMP)
@@ -2681,22 +2817,22 @@ static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                psRuntimeCfg->ui32DefaultDustsNumInit = psDevInfo->sDevFeatureCfg.ui32MAXDustCount;
 
                /* flush write buffers for psDevInfo->psRGXFWIfRuntimeCfg */
-               OSWriteMemoryBarrier();
+               OSWriteMemoryBarrier(psDevInfo->psRGXFWIfRuntimeCfg);
 
                /* Setup FW coremem data */
                if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
                {
-                       IMG_BOOL bMetaDMA = RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA);
-
                        psFwSysInitScratch->sCorememDataStore.pbyFWAddr = psDevInfo->sFWCorememDataStoreFWAddr;
 
-                       if (bMetaDMA)
+#if defined(RGX_FEATURE_META_DMA_CHANNEL_COUNT_MAX_VALUE_IDX)
+                       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
                        {
                                RGXSetMetaDMAAddress(&psFwSysInitScratch->sCorememDataStore,
                                                psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
                                                &psFwSysInitScratch->sCorememDataStore.pbyFWAddr,
                                                0);
                        }
+#endif
                }
 
                psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags    = ui32ConfigFlags    & RGXFWIF_INICFG_ALL;
@@ -2751,6 +2887,7 @@ fail:
  @Return      PVRSRV_ERROR
 ******************************************************************************/
 static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                                        IMG_UINT32               ui32KCCBSizeLog2,
                                                                         IMG_UINT32               ui32HWRDebugDumpLimit,
                                                                         IMG_UINT32               ui32FwOsCfgFlags)
 {
@@ -2760,6 +2897,12 @@ static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
 
        OSCachedMemSet(&sFwOsInitScratch, 0, sizeof(RGXFWIF_OSINIT));
 
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = RGXSetupFwGuardPage(psDevInfo);
+               PVR_LOG_GOTO_IF_ERROR(eError, "Setting up firmware heap guard pages", fail);
+       }
+
        /* Memory tracking the connection state should be non-volatile and
         * is not cleared on allocation to prevent loss of pre-reset information */
        eError = RGXSetupFwAllocation(psDevInfo,
@@ -2814,7 +2957,7 @@ static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
                                                 &psDevInfo->psKernelCCBMemDesc,
                                                 &sFwOsInitScratch.psKernelCCBCtl,
                                                 &sFwOsInitScratch.psKernelCCB,
-                                                RGXFWIF_KCCB_NUMCMDS_LOG2,
+                                                ui32KCCBSizeLog2,
                                                 sizeof(RGXFWIF_KCCB_CMD),
                                                 (RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS |
                                                 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED)),
@@ -2826,7 +2969,7 @@ static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
         */
        eError = RGXSetupFwAllocation(psDevInfo,
                                                                  RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
-                                                                 (1U << RGXFWIF_KCCB_NUMCMDS_LOG2) * sizeof(IMG_UINT32),
+                                                                 (1U << ui32KCCBSizeLog2) * sizeof(IMG_UINT32),
                                                                  "FwKernelCCBRtnSlots",
                                                                  &psDevInfo->psKernelCCBRtnSlotsMemDesc,
                                                                  &sFwOsInitScratch.psKernelCCBRtnSlots,
@@ -2863,6 +3006,9 @@ static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
        eError = SyncPrimGetFirmwareAddr(psDevInfo->psPowSyncPrim, &psDevInfo->psRGXFWIfFwOsData->sPowerSync.ui32Addr);
        PVR_LOG_GOTO_IF_ERROR(eError, "Get Sync Prim FW address", fail);
 
+       /* flush write buffers for psRGXFWIfFwOsData */
+       OSWriteMemoryBarrier(psDevInfo->psRGXFWIfFwOsData);
+
        sFwOsInitScratch.ui32HWRDebugDumpLimit = ui32HWRDebugDumpLimit;
 
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
@@ -2901,7 +3047,7 @@ fail:
 *******************************************************************************
  @Function    RGXSetupFirmware
 
- @Description Setups all firmware related data
+ @Description Sets up all firmware related data
 
  @Input       psDevInfo
 
@@ -2922,12 +3068,16 @@ PVRSRV_ERROR RGXSetupFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
                                                          IMG_UINT32               ui32HWPerfCountersDataSize,
                                                          IMG_UINT32               *pui32TPUTrilinearFracMask,
                                                          RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
-                                                         FW_PERF_CONF             eFirmwarePerf)
+                                                         FW_PERF_CONF             eFirmwarePerf,
+                                                         IMG_UINT32               ui32KCCBSizeLog2)
 {
        PVRSRV_ERROR eError;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
-       eError = RGXSetupFwOsData(psDeviceNode, ui32HWRDebugDumpLimit, ui32FwOsCfgFlags);
+       eError = RGXSetupFwOsData(psDeviceNode,
+                                                         ui32KCCBSizeLog2,
+                                                         ui32HWRDebugDumpLimit,
+                                                         ui32FwOsCfgFlags);
        PVR_LOG_GOTO_IF_ERROR(eError, "Setting up firmware os data", fail);
 
        if (PVRSRV_VZ_MODE_IS(GUEST))
@@ -2985,12 +3135,14 @@ static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo)
        }
 
 #if defined(PDUMP)
+#if defined(RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TDM_PDS_CHECKSUM) &&
            psDevInfo->psRGXFWSigTDM2DChecksMemDesc)
        {
                DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSigTDM2DChecksMemDesc);
                psDevInfo->psRGXFWSigTDM2DChecksMemDesc = NULL;
        }
+#endif
 
        if (psDevInfo->psRGXFWSigTAChecksMemDesc)
        {
@@ -3034,8 +3186,6 @@ static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo)
                psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc = NULL;
        }
 
-       RGXHWPerfDeinit(psDevInfo);
-
        if (psDevInfo->psRGXFWIfRuntimeCfgMemDesc)
        {
                if (psDevInfo->psRGXFWIfRuntimeCfg != NULL)
@@ -3112,11 +3262,12 @@ static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo)
        }
 #endif
 
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, SLC_VIVT))
        {
                _FreeSLC3Fence(psDevInfo);
        }
-
+#endif
 #if defined(SUPPORT_PDVFS)
        if (psDevInfo->psRGXFWIFCoreClkRateMemDesc)
        {
@@ -3238,6 +3389,11 @@ static void RGXFreeFwOsData(PVRSRV_RGXDEV_INFO *psDevInfo)
                psDevInfo->hTimerQueryLock = NULL;
        }
 #endif
+
+       if (psDevInfo->psRGXFWHeapGuardPageReserveMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWHeapGuardPageReserveMemDesc);
+       }
 }
 
 /*!
@@ -3300,27 +3456,22 @@ void RGXFreeFirmware(PVRSRV_RGXDEV_INFO *psDevInfo)
 
  RETURNS       : PVRSRV_ERROR
 ******************************************************************************/
-static PVRSRV_ERROR RGXAcquireKernelCCBSlot(DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
-                                                                                       RGXFWIF_CCB_CTL *psKCCBCtl,
+static PVRSRV_ERROR RGXAcquireKernelCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                       const RGXFWIF_CCB_CTL *psKCCBCtl,
                                                                                        IMG_UINT32              *pui32Offset)
 {
        IMG_UINT32      ui32OldWriteOffset, ui32NextWriteOffset;
+#if defined(PDUMP)
+       const DEVMEM_MEMDESC *psKCCBCtrlMemDesc = psDevInfo->psKernelCCBCtlMemDesc;
+#endif
 
        ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
        ui32NextWriteOffset = (ui32OldWriteOffset + 1) & psKCCBCtl->ui32WrapMask;
 
-       /*
-        * KCCB size is determined by the log2size as the MSB rounded up to the (next power of 2) -1
-        * The MTS can queue up to (next power of 2) -1 kicks
-        * i.e. RGXFWIF_KCCB_NUMCMDS_LOG2=7, 2^7 = 128, next power of 2= 256, Max Kicks = 255
-        * (254 pending kicks and 1 executing kick),
-        * hence the kernel CCB should not queue more than (1<<(RGXFWIF_KCCB_NUMCMDS_LOG2+1))-1 commands.
-        */
-       PVR_ASSERT(psKCCBCtl->ui32WrapMask < ((1<<(RGXFWIF_KCCB_NUMCMDS_LOG2+1))-1));
-
 #if defined(PDUMP)
        /* Wait for sufficient CCB space to become available */
-       PDUMPCOMMENTWITHFLAGS(0, "Wait for kCCB woff=%u", ui32NextWriteOffset);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, 0,
+                             "Wait for kCCB woff=%u", ui32NextWriteOffset);
        DevmemPDumpCBP(psKCCBCtrlMemDesc,
                       offsetof(RGXFWIF_CCB_CTL, ui32ReadOffset),
                       ui32NextWriteOffset,
@@ -3346,23 +3497,14 @@ static PVRSRV_ERROR RGXAcquireKernelCCBSlot(DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
 
  RETURNS       : PVRSRV_ERROR
 ******************************************************************************/
-static PVRSRV_ERROR RGXPollKernelCCBSlot(DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
-                                                                                RGXFWIF_CCB_CTL        *psKCCBCtl)
+static PVRSRV_ERROR RGXPollKernelCCBSlot(const DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
+                                                                                const RGXFWIF_CCB_CTL *psKCCBCtl)
 {
        IMG_UINT32      ui32OldWriteOffset, ui32NextWriteOffset;
 
        ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
        ui32NextWriteOffset = (ui32OldWriteOffset + 1) & psKCCBCtl->ui32WrapMask;
 
-       /*
-        * KCCB size is determined by the log2size as the MSB rounded up to the (next power of 2) -1
-        * The MTS can queue up to (next power of 2) -1 kicks
-        * i.e. RGXFWIF_KCCB_NUMCMDS_LOG2=7, 2^7 = 128, next power of 2= 256, Max Kicks = 255
-        * (254 pending kicks and 1 executing kick),
-        * hence the kernel CCB should not queue more than (1<<(RGXFWIF_KCCB_NUMCMDS_LOG2+1))-1 commands.
-        */
-       PVR_ASSERT(psKCCBCtl->ui32WrapMask < ((1<<(RGXFWIF_KCCB_NUMCMDS_LOG2+1))-1));
-
        LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
        {
 
@@ -3450,10 +3592,6 @@ static IMG_UINT32 RGXGetCmdMemCopySize(RGXFWIF_KCCB_CMD_TYPE eCmdType)
                {
                        return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_FREELISTS_RECONSTRUCTION_DATA);
                }
-               case RGXFWIF_KCCB_CMD_NOTIFY_SIGNAL_UPDATE:
-               {
-                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_SIGNAL_UPDATE_DATA);
-               }
                case RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE:
                {
                        return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_WRITE_OFFSET_UPDATE_DATA);
@@ -3494,6 +3632,10 @@ static IMG_UINT32 RGXGetCmdMemCopySize(RGXFWIF_KCCB_CMD_TYPE eCmdType)
                {
                        return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS);
                }
+               case RGXFWIF_KCCB_CMD_HWPERF_CONFIG_BLKS:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CONFIG_DA_BLKS);
+               }
                case RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS:
                {
                        return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CTRL_BLKS);
@@ -3517,6 +3659,10 @@ static IMG_UINT32 RGXGetCmdMemCopySize(RGXFWIF_KCCB_CMD_TYPE eCmdType)
                {
                        return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_RGXREG_DATA);
                }
+               case RGXFWIF_KCCB_CMD_GPUMAP:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_GPUMAP_DATA);
+               }
 #endif
                default:
                {
@@ -3540,25 +3686,18 @@ PVRSRV_ERROR RGXWaitForKCCBSlotUpdate(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 #if defined(PDUMP)
        /* PDumping conditions same as RGXSendCommandRaw for the actual command and poll command to go in harmony */
-       if (PDumpIsContCaptureOn())
+       if (PDumpCheckFlagsWrite(psDevInfo->psDeviceNode, ui32PDumpFlags))
        {
-               IMG_BOOL bIsInCaptureRange;
+               PDUMPCOMMENT(psDevInfo->psDeviceNode, "Poll on KCCB slot %u for value %u (mask: 0x%x)", ui32SlotNum,
+                                        RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED, RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED);
 
-               PDumpIsCaptureFrameKM(&bIsInCaptureRange);
-
-               if ((bIsInCaptureRange || PDUMP_IS_CONTINUOUS(ui32PDumpFlags)) && !PDUMPPOWCMDINTRANS())
-               {
-                       PDUMPCOMMENT("Poll on KCCB slot %u for value %u (mask: 0x%x)", ui32SlotNum,
-                                    RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED, RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED);
-
-                       eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBRtnSlotsMemDesc,
-                                                                                       ui32SlotNum * sizeof(IMG_UINT32),
-                                                                                       RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
-                                                                                       RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
-                                                                                       PDUMP_POLL_OPERATOR_EQUAL,
-                                                                                       ui32PDumpFlags);
-                       PVR_LOG_IF_ERROR(eError, "DevmemPDumpDevmemPol32");
-               }
+               eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBRtnSlotsMemDesc,
+                                                                               ui32SlotNum * sizeof(IMG_UINT32),
+                                                                               RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
+                                                                               RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
+                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                               ui32PDumpFlags);
+               PVR_LOG_IF_ERROR(eError, "DevmemPDumpDevmemPol32");
        }
 #else
        PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
@@ -3569,7 +3708,7 @@ PVRSRV_ERROR RGXWaitForKCCBSlotUpdate(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
                                                                          RGXFWIF_KCCB_CMD    *psKCCBCmd,
-                                                                         IMG_UINT32          uiPdumpFlags,
+                                                                         IMG_UINT32          uiPDumpFlags,
                                                                          IMG_UINT32          *pui32CmdKCCBSlot)
 {
        PVRSRV_ERROR            eError;
@@ -3581,21 +3720,15 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
        IMG_UINT32                      ui32CmdMemCopySize;
 
 #if !defined(PDUMP)
-       PVR_UNREFERENCED_PARAMETER(uiPdumpFlags);
+       PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
 #else
-       IMG_BOOL bPdumpEnabled = IMG_FALSE;
-       IMG_BOOL bPDumpPowTrans = PDUMPPOWCMDINTRANS();
-       IMG_BOOL bContCaptureOn = PDumpIsContCaptureOn(); /* client connected or in pdump init phase */
+       IMG_BOOL bContCaptureOn = PDumpCheckFlagsWrite(psDeviceNode, PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER); /* client connected or in pdump init phase */
+       IMG_BOOL bPDumpEnabled = PDumpCheckFlagsWrite(psDeviceNode, uiPDumpFlags); /* Are we in capture range or continuous and not in a power transition */
 
        if (bContCaptureOn)
        {
-               IMG_BOOL bIsInCaptureRange;
-
-               PDumpIsCaptureFrameKM(&bIsInCaptureRange);
-               bPdumpEnabled = (bIsInCaptureRange || PDUMP_IS_CONTINUOUS(uiPdumpFlags)) && !bPDumpPowTrans;
-
                /* in capture range */
-               if (bPdumpEnabled)
+               if (bPDumpEnabled)
                {
                        if (!psDevInfo->bDumpedKCCBCtlAlready)
                        {
@@ -3606,19 +3739,20 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
                                PVR_DPF((PVR_DBG_MESSAGE, "%s: waiting on fw to catch-up, roff: %d, woff: %d",
                                                __func__,
                                                psKCCBCtl->ui32ReadOffset, ui32OldWriteOffset));
-                               PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                               PVRSRVPollForValueKM(psDeviceNode,
                                                     (IMG_UINT32 __iomem *)&psKCCBCtl->ui32ReadOffset,
-                                                                        ui32OldWriteOffset, 0xFFFFFFFF,
-                                                                        POLL_FLAG_LOG_ERROR | POLL_FLAG_DEBUG_DUMP);
+                                                    ui32OldWriteOffset, 0xFFFFFFFF,
+                                                    POLL_FLAG_LOG_ERROR | POLL_FLAG_DEBUG_DUMP);
 
                                /* Dump Init state of Kernel CCB control (read and write offset) */
-                               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Initial state of kernel CCB Control, roff: %d, woff: %d",
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags,
+                                               "Initial state of kernel CCB Control, roff: %d, woff: %d",
                                                psKCCBCtl->ui32ReadOffset, psKCCBCtl->ui32WriteOffset);
 
                                DevmemPDumpLoadMem(psDevInfo->psKernelCCBCtlMemDesc,
                                                0,
                                                sizeof(RGXFWIF_CCB_CTL),
-                                               PDUMP_FLAGS_CONTINUOUS);
+                                               uiPDumpFlags);
                        }
                }
        }
@@ -3626,7 +3760,8 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
 
 #if defined(SUPPORT_AUTOVZ)
        if (!((KM_FW_CONNECTION_IS(READY, psDevInfo) && KM_OS_CONNECTION_IS(READY, psDevInfo)) ||
-               (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) && KM_OS_CONNECTION_IS(ACTIVE, psDevInfo))))
+               (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) && KM_OS_CONNECTION_IS(ACTIVE, psDevInfo))) &&
+               !PVRSRV_VZ_MODE_IS(NATIVE))
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: The firmware-driver connection is invalid:"
                                                                "driver state = %u / firmware state = %u;"
@@ -3649,7 +3784,7 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
        }
 
        /* Acquire a slot in the CCB */
-       eError = RGXAcquireKernelCCBSlot(psDevInfo->psKernelCCBCtlMemDesc, psKCCBCtl, &ui32NewWriteOffset);
+       eError = RGXAcquireKernelCCBSlot(psDevInfo, psKCCBCtl, &ui32NewWriteOffset);
        if (eError != PVRSRV_OK)
        {
                goto _RGXSendCommandRaw_Exit;
@@ -3660,9 +3795,8 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
        PVR_LOG_RETURN_IF_FALSE(ui32CmdMemCopySize !=0, "RGXGetCmdMemCopySize failed", PVRSRV_ERROR_INVALID_CCB_COMMAND);
 
        /* Copy the command into the CCB */
-       OSCachedMemCopy(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
+       OSCachedMemCopyWMB(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
                        psKCCBCmd, ui32CmdMemCopySize);
-       OSWriteMemoryBarrier();
 
        /* If non-NULL pui32CmdKCCBSlot passed-in, return the kCCB slot in which the command was enqueued */
        if (pui32CmdKCCBSlot)
@@ -3671,48 +3805,48 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
 
                /* Each such command enqueue needs to reset the slot value first. This is so that a caller
                 * doesn't get to see stale/false value in allotted slot */
-               psDevInfo->pui32KernelCCBRtnSlots[ui32OldWriteOffset] = RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE;
+               OSWriteDeviceMem32WithWMB(&psDevInfo->pui32KernelCCBRtnSlots[ui32OldWriteOffset],
+                                         RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE);
 #if defined(PDUMP)
-               PDUMPCOMMENTWITHFLAGS(uiPdumpFlags, "Reset kCCB slot number %u", ui32OldWriteOffset);
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags,
+                                                         "Reset kCCB slot number %u", ui32OldWriteOffset);
                DevmemPDumpLoadMem(psDevInfo->psKernelCCBRtnSlotsMemDesc,
                                   ui32OldWriteOffset * sizeof(IMG_UINT32),
                                                   sizeof(IMG_UINT32),
-                                                  uiPdumpFlags);
+                                                  uiPDumpFlags);
 #endif
                PVR_DPF((PVR_DBG_MESSAGE, "%s: Device (%p) KCCB slot %u reset with value %u for command type %x",
                         __func__, psDevInfo, ui32OldWriteOffset, RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE, psKCCBCmd->eCmdType));
        }
 
-       /* ensure kCCB data is written before the offsets */
-       OSWriteMemoryBarrier();
-
        /* Move past the current command */
        psKCCBCtl->ui32WriteOffset = ui32NewWriteOffset;
-       /* Force a read-back to memory to avoid posted writes on certain buses */
-       (void) psKCCBCtl->ui32WriteOffset;
 
+       OSWriteMemoryBarrier(&psKCCBCtl->ui32WriteOffset);
 
 #if defined(PDUMP)
        if (bContCaptureOn)
        {
                /* in capture range */
-               if (bPdumpEnabled)
+               if (bPDumpEnabled)
                {
                        /* Dump new Kernel CCB content */
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump kCCB cmd woff = %d",
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                       uiPDumpFlags, "Dump kCCB cmd woff = %d",
                                        ui32OldWriteOffset);
                        DevmemPDumpLoadMem(psDevInfo->psKernelCCBMemDesc,
                                        ui32OldWriteOffset * psKCCBCtl->ui32CmdSize,
                                        ui32CmdMemCopySize,
-                                       PDUMP_FLAGS_CONTINUOUS);
+                                       uiPDumpFlags);
 
                        /* Dump new kernel CCB write offset */
-                       PDUMPCOMMENTWITHFLAGS(uiPdumpFlags, "Dump kCCBCtl woff: %d",
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                       uiPDumpFlags, "Dump kCCBCtl woff: %d",
                                        ui32NewWriteOffset);
                        DevmemPDumpLoadMem(psDevInfo->psKernelCCBCtlMemDesc,
                                        offsetof(RGXFWIF_CCB_CTL, ui32WriteOffset),
                                        sizeof(IMG_UINT32),
-                                       uiPdumpFlags);
+                                       uiPDumpFlags);
 
                        /* mimic the read-back of the write from above */
                        DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBCtlMemDesc,
@@ -3720,8 +3854,7 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
                                        ui32NewWriteOffset,
                                        0xFFFFFFFF,
                                        PDUMP_POLL_OPERATOR_EQUAL,
-                                       uiPdumpFlags);
-
+                                       uiPDumpFlags);
                }
                /* out of capture range */
                else
@@ -3733,13 +3866,14 @@ static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
 #endif
 
 
-       PDUMPCOMMENTWITHFLAGS(uiPdumpFlags, "MTS kick for kernel CCB");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags, "MTS kick for kernel CCB");
        /*
         * Kick the MTS to schedule the firmware.
         */
        __MTSScheduleWrite(psDevInfo, RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK);
 
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE, RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK, uiPdumpFlags);
+       PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE,
+                  RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK, uiPDumpFlags);
 
 #if defined(SUPPORT_AUTOVZ)
        RGXUpdateAutoVzWdgToken(psDevInfo);
@@ -3762,13 +3896,13 @@ _RGXSendCommandRaw_Exit:
  PARAMETERS    : psDevInfo     RGX device info
                        : eKCCBType             Firmware Command type
                        : psKCCBCmd             Firmware Command
-                       : uiPdumpFlags  Pdump flags
+                       : uiPDumpFlags  Pdump flags
 
  RETURNS       : PVRSRV_OK     If all went good, PVRSRV_ERROR_RETRY otherwise.
 ******************************************************************************/
 static PVRSRV_ERROR _AllocDeferredCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
                                           RGXFWIF_KCCB_CMD   *psKCCBCmd,
-                                          IMG_UINT32         uiPdumpFlags)
+                                          IMG_UINT32         uiPDumpFlags)
 {
        RGX_DEFERRED_KCCB_CMD *psDeferredCommand;
        OS_SPINLOCK_FLAGS uiFlags;
@@ -3783,7 +3917,7 @@ static PVRSRV_ERROR _AllocDeferredCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
        }
 
        psDeferredCommand->sKCCBcmd = *psKCCBCmd;
-       psDeferredCommand->uiPdumpFlags = uiPdumpFlags;
+       psDeferredCommand->uiPDumpFlags = uiPDumpFlags;
        psDeferredCommand->psDevInfo = psDevInfo;
 
        OSSpinLockAcquire(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
@@ -3868,7 +4002,7 @@ PVRSRV_ERROR RGXSendCommandsFromDeferredList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_
                        psTempDeferredKCCBCmd = IMG_CONTAINER_OF(psNode, RGX_DEFERRED_KCCB_CMD, sListNode);
                        eError = RGXSendCommandRaw(psTempDeferredKCCBCmd->psDevInfo,
                                                   &psTempDeferredKCCBCmd->sKCCBcmd,
-                                                  psTempDeferredKCCBCmd->uiPdumpFlags,
+                                                  psTempDeferredKCCBCmd->uiPDumpFlags,
                                                   NULL /* We surely aren't interested in kCCB slot number of deferred command */);
                        if (eError != PVRSRV_OK)
                        {
@@ -3912,7 +4046,7 @@ cleanup_:
 
 PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
                                                                                  RGXFWIF_KCCB_CMD    *psKCCBCmd,
-                                                                                 IMG_UINT32          uiPdumpFlags,
+                                                                                 IMG_UINT32          uiPDumpFlags,
                                                                                  IMG_UINT32          *pui32CmdKCCBSlot)
 {
        IMG_BOOL     bPoll = (pui32CmdKCCBSlot != NULL);
@@ -3931,7 +4065,7 @@ PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
        {
                eError = RGXSendCommandRaw(psDevInfo,
                                                                   psKCCBCmd,
-                                                                  uiPdumpFlags,
+                                                                  uiPDumpFlags,
                                                                   pui32CmdKCCBSlot);
        }
 
@@ -3946,16 +4080,15 @@ PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
        {
                if (pui32CmdKCCBSlot == NULL)
                {
-                       eError = _AllocDeferredCommand(psDevInfo, psKCCBCmd, uiPdumpFlags);
+                       eError = _AllocDeferredCommand(psDevInfo, psKCCBCmd, uiPDumpFlags);
                }
                else
                {
                        /* Let the caller retry. Otherwise if we deferred the command and returned OK,
                         * the caller can end up looking in a stale CCB slot.
                         */
-                       PVR_DPF((PVR_DBG_ERROR, "%s: Couldn't flush the deferred queue for a command (Type:%d) "
-                                               "that needed the kCCB command slot number! Returning kCCB FULL",
-                                               __func__, psKCCBCmd->eCmdType));
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Couldn't flush the deferred queue for a command (Type:%d) "
+                                               "- will be retried", __func__, psKCCBCmd->eCmdType));
                }
        }
 
@@ -3983,11 +4116,11 @@ PVRSRV_ERROR RGXSendCommandWithPowLockAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevIn
                goto _PVRSRVPowerLock_Exit;
        }
 
-       PDUMPPOWCMDSTART();
+       PDUMPPOWCMDSTART(psDeviceNode);
        eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                                                 PVRSRV_DEV_POWER_STATE_ON,
-                                                                                IMG_FALSE);
-       PDUMPPOWCMDEND();
+                                                                                PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDeviceNode);
 
        if (eError != PVRSRV_OK)
        {
@@ -4050,10 +4183,10 @@ PVRSRV_ERROR RGXScheduleRgxRegCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
        eError =  RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                                                           RGXFWIF_DM_GP,
                                                                                           &sRgxRegsCmd,
-                                                                                          0,
                                                                                           PDUMP_FLAGS_CONTINUOUS,
                                                                                           &ui32kCCBCommandSlot);
        PVR_LOG_RETURN_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot");
+
        if (bWriteOp)
        {
                eError = RGXWaitForKCCBSlotUpdate(psDevInfo,
@@ -4093,14 +4226,14 @@ static void RGX_MISRHandler_ScheduleProcessQueues(void *pvData)
        eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 
        if (!PVRSRV_VZ_MODE_IS(GUEST) &&
-                       (eError == PVRSRV_OK) && (ePowerState == PVRSRV_DEV_POWER_STATE_OFF))
+               (eError == PVRSRV_OK) && (ePowerState == PVRSRV_DEV_POWER_STATE_OFF))
        {
                /* For now, guest drivers will always wake-up the GPU */
                RGXFWIF_GPU_UTIL_FWCB  *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
                IMG_BOOL               bGPUHasWorkWaiting;
 
                bGPUHasWorkWaiting =
-                               (RGXFWIF_GPU_UTIL_GET_STATE(psUtilFWCb->ui64LastWord) == RGXFWIF_GPU_UTIL_STATE_BLOCKED);
+                   (RGXFWIF_GPU_UTIL_GET_STATE(psUtilFWCb->ui64LastWord) == RGXFWIF_GPU_UTIL_STATE_BLOCKED);
 
                if (!bGPUHasWorkWaiting)
                {
@@ -4110,12 +4243,12 @@ static void RGX_MISRHandler_ScheduleProcessQueues(void *pvData)
                }
        }
 
-       PDUMPPOWCMDSTART();
+       PDUMPPOWCMDSTART(psDeviceNode);
        /* wake up the GPU */
        eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                                                 PVRSRV_DEV_POWER_STATE_ON,
-                                                                                IMG_FALSE);
-       PDUMPPOWCMDEND();
+                                                                                PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDeviceNode);
 
        if (eError != PVRSRV_OK)
        {
@@ -4143,10 +4276,9 @@ PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE
 
 PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
                                               RGXFWIF_DM          eKCCBType,
-                                                                                         RGXFWIF_KCCB_CMD    *psKCCBCmd,
-                                                                                         IMG_UINT32          ui32CacheOpFence,
-                                                                                         IMG_UINT32          ui32PDumpFlags,
-                                                                                         IMG_UINT32          *pui32CmdKCCBSlot)
+                                              RGXFWIF_KCCB_CMD    *psKCCBCmd,
+                                              IMG_UINT32          ui32PDumpFlags,
+                                              IMG_UINT32          *pui32CmdKCCBSlot)
 {
        PVRSRV_ERROR eError;
        IMG_UINT32 uiMMUSyncUpdate;
@@ -4162,9 +4294,6 @@ PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
                return PVRSRV_ERROR_INVALID_DEVICE;
        }
 
-       eError = CacheOpFence(eKCCBType, ui32CacheOpFence);
-       if (unlikely(eError != PVRSRV_OK)) goto RGXScheduleCommand_exit;
-
 #if defined(SUPPORT_VALIDATION)
        /* For validation, force the core to different dust count states with each kick */
        if ((eKCCBType == RGXFWIF_DM_GEOM) || (eKCCBType == RGXFWIF_DM_CDM))
@@ -4200,13 +4329,23 @@ PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
                        }
                        else if (psDevInfo->ui32ECCRAMErrInjModule == RGXKM_ECC_ERR_INJ_TPU)
                        {
+#if defined(RGX_FEATURE_MAX_TPU_PER_SPU)
+                               PVR_LOG(("ECC RAM Error Inject Swift TPU"));
+                               ui64ECCRegVal = RGX_CR_ECC_RAM_ERR_INJ_SWIFT_EN;
+#else
                                PVR_LOG(("ECC RAM Error Inject TPU MCU L0"));
                                ui64ECCRegVal = RGX_CR_ECC_RAM_ERR_INJ_TPU_MCU_L0_EN;
+#endif
                        }
                        else if (psDevInfo->ui32ECCRAMErrInjModule == RGXKM_ECC_ERR_INJ_RASCAL)
                        {
+#if defined(RGX_CR_ECC_RAM_ERR_INJ_RASCAL_EN)
                                PVR_LOG(("ECC RAM Error Inject RASCAL"));
                                ui64ECCRegVal = RGX_CR_ECC_RAM_ERR_INJ_RASCAL_EN;
+#else
+                               PVR_LOG(("ECC RAM Error Inject USC"));
+                               ui64ECCRegVal = RGX_CR_ECC_RAM_ERR_INJ_USC_EN;
+#endif
                        }
                        else if (psDevInfo->ui32ECCRAMErrInjModule == RGXKM_ECC_ERR_INJ_MARS)
                        {
@@ -4217,11 +4356,11 @@ PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
                        {
                        }
 
-                       OSWriteMemoryBarrier();
+                       OSWriteMemoryBarrier(NULL);
                        OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_ECC_RAM_ERR_INJ, ui64ECCRegVal);
-                       PDUMPCOMMENT("Write reg ECC_RAM_ERR_INJ");
-                       PDUMPREG64(RGX_PDUMPREG_NAME, RGX_CR_ECC_RAM_ERR_INJ, ui64ECCRegVal, PDUMP_FLAGS_CONTINUOUS);
-                       OSWriteMemoryBarrier();
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Write reg ECC_RAM_ERR_INJ");
+                       PDUMPREG64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_ECC_RAM_ERR_INJ, ui64ECCRegVal, PDUMP_FLAGS_CONTINUOUS);
+                       OSWriteMemoryBarrier(NULL);
                }
        }
 #endif
@@ -4252,11 +4391,11 @@ PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
        }
 
        /* Ensure device is powered up before sending any commands */
-       PDUMPPOWCMDSTART();
+       PDUMPPOWCMDSTART(psDevInfo->psDeviceNode);
        eError = PVRSRVSetDevicePowerStateKM(psDevInfo->psDeviceNode,
-                       PVRSRV_DEV_POWER_STATE_ON,
-                       IMG_FALSE);
-       PDUMPPOWCMDEND();
+                                            PVRSRV_DEV_POWER_STATE_ON,
+                                            PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDevInfo->psDeviceNode);
        if (unlikely(eError != PVRSRV_OK))
        {
                PVR_DPF((PVR_DBG_WARNING, "%s: failed to transition RGX to ON (%s)",
@@ -4282,15 +4421,20 @@ RGXScheduleCommand_exit:
  */
 void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-       RGXFWIF_FWCCB_CMD *psFwCCBCmd;
-
        RGXFWIF_CCB_CTL *psFWCCBCtl = psDevInfo->psFirmwareCCBCtl;
        IMG_UINT8 *psFWCCB = psDevInfo->psFirmwareCCB;
 
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       PVR_LOG_RETURN_VOID_IF_FALSE(PVRSRV_VZ_MODE_IS(NATIVE) ||
+                                                                (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) &&
+                                                                 KM_OS_CONNECTION_IS(ACTIVE, psDevInfo)),
+                                                                "FW-KM connection is down");
+#endif
+
        while (psFWCCBCtl->ui32ReadOffset != psFWCCBCtl->ui32WriteOffset)
        {
                /* Point to the next command */
-               psFwCCBCmd = ((RGXFWIF_FWCCB_CMD *)psFWCCB) + psFWCCBCtl->ui32ReadOffset;
+               const RGXFWIF_FWCCB_CMD *psFwCCBCmd = ((RGXFWIF_FWCCB_CMD *)psFWCCB) + psFWCCBCtl->ui32ReadOffset;
 
                HTBLOGK(HTB_SF_MAIN_FWCCB_CMD, psFwCCBCmd->eCmdType);
                switch (psFwCCBCmd->eCmdType)
@@ -4299,7 +4443,8 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                {
                        if (psDevInfo->bPDPEnabled)
                        {
-                               PDUMP_PANIC(ZSBUFFER_BACKING, "Request to add backing to ZSBuffer");
+                               PDUMP_PANIC(psDevInfo->psDeviceNode, ZSBUFFER_BACKING,
+                                           "Request to add backing to ZSBuffer");
                        }
                        RGXProcessRequestZSBufferBacking(psDevInfo,
                                        psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
@@ -4310,7 +4455,8 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                {
                        if (psDevInfo->bPDPEnabled)
                        {
-                               PDUMP_PANIC(ZSBUFFER_UNBACKING, "Request to remove backing from ZSBuffer");
+                               PDUMP_PANIC(psDevInfo->psDeviceNode, ZSBUFFER_UNBACKING,
+                                           "Request to remove backing from ZSBuffer");
                        }
                        RGXProcessRequestZSBufferUnbacking(psDevInfo,
                                        psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
@@ -4321,7 +4467,8 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                {
                        if (psDevInfo->bPDPEnabled)
                        {
-                               PDUMP_PANIC(FREELIST_GROW, "Request to grow the free list");
+                               PDUMP_PANIC(psDevInfo->psDeviceNode, FREELIST_GROW,
+                                           "Request to grow the free list");
                        }
                        RGXProcessRequestGrow(psDevInfo,
                                        psFwCCBCmd->uCmdData.sCmdFreeListGS.ui32FreelistID);
@@ -4332,7 +4479,8 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                {
                        if (psDevInfo->bPDPEnabled)
                        {
-                               PDUMP_PANIC(FREELISTS_RECONSTRUCTION, "Request to reconstruct free lists");
+                               PDUMP_PANIC(psDevInfo->psDeviceNode, FREELISTS_RECONSTRUCTION,
+                                           "Request to reconstruct free lists");
                        }
 
                        if (PVRSRV_VZ_MODE_IS(GUEST))
@@ -4369,7 +4517,7 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                        {
                                PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
                                PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
-                               RGXFWIF_FWCCB_CMD_FW_PAGEFAULT_DATA *psCmdFwPagefault =
+                               const RGXFWIF_FWCCB_CMD_FW_PAGEFAULT_DATA *psCmdFwPagefault =
                                                &psFwCCBCmd->uCmdData.sCmdFWPagefault;
 
                                if (psDevConfig->pfnSysDevErrorNotify)
@@ -4389,7 +4537,7 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                case RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION:
                {
                        DLLIST_NODE *psNode, *psNext;
-                       RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA *psCmdContextResetNotification =
+                       const RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA *psCmdContextResetNotification =
                                        &psFwCCBCmd->uCmdData.sCmdContextResetNotification;
                        RGX_SERVER_COMMON_CONTEXT *psServerCommonContext = NULL;
                        IMG_UINT32 ui32ErrorPid = 0;
@@ -4583,7 +4731,7 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
 
                                /* Power down... */
                                eError = PVRSRVSetDeviceSystemPowerState(psDevInfo->psDeviceNode,
-                                               PVRSRV_SYS_POWER_STATE_OFF);
+                                               PVRSRV_SYS_POWER_STATE_OFF, PVRSRV_POWER_FLAGS_NONE);
                                if (eError == PVRSRV_OK)
                                {
                                        /* Clear the FW faulted flags... */
@@ -4591,7 +4739,7 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
 
                                        /* Power back up again... */
                                        eError = PVRSRVSetDeviceSystemPowerState(psDevInfo->psDeviceNode,
-                                                       PVRSRV_SYS_POWER_STATE_ON);
+                                                       PVRSRV_SYS_POWER_STATE_ON, PVRSRV_POWER_FLAGS_NONE);
 
                                        /* Send a dummy KCCB command to ensure the FW wakes up and checks the queues... */
                                        if (eError == PVRSRV_OK)
@@ -4643,6 +4791,28 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
                        complete(&psDevInfo->sFwRegs.sRegComp);
                        break;
                }
+#if defined(SUPPORT_SOC_TIMER)
+               case RGXFWIF_FWCCB_CMD_SAMPLE_TIMERS:
+               {
+                       if (psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER)
+                       {
+                               PVRSRV_ERROR eSOCtimerErr = RGXValidateSOCUSCTimer(psDevInfo,
+                                                                                     PDUMP_NONE,
+                                                                                     psFwCCBCmd->uCmdData.sCmdTimers.ui64timerGray,
+                                                                                     psFwCCBCmd->uCmdData.sCmdTimers.ui64timerBinary,
+                                                                                     psFwCCBCmd->uCmdData.sCmdTimers.aui64uscTimers);
+                               if (PVRSRV_OK == eSOCtimerErr)
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "SoC or USC Timers have increased over time"));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "SoC or USC Timers have NOT increased over time"));
+                               }
+                       }
+                       break;
+               }
+#endif
 #endif
                default:
                {
@@ -4662,7 +4832,8 @@ void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
 /*
  * PVRSRVRGXFrameworkCopyCommand
 */
-PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC      *psFWFrameworkMemDesc,
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+               DEVMEM_MEMDESC  *psFWFrameworkMemDesc,
                IMG_PBYTE               pbyGPUFRegisterList,
                IMG_UINT32              ui32FrameworkRegisterSize)
 {
@@ -4688,8 +4859,10 @@ PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC        *psFWFrameworkMemDesc,
         * Dump the FW framework buffer
         */
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump FWFramework buffer");
+       PDUMPCOMMENT(psDeviceNode, "Dump FWFramework buffer");
        DevmemPDumpLoadMem(psFWFrameworkMemDesc, 0, ui32FrameworkRegisterSize, PDUMP_FLAGS_CONTINUOUS);
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 #endif
 
        return PVRSRV_OK;
@@ -4709,7 +4882,7 @@ PVRSRV_ERROR PVRSRVRGXFrameworkCreateKM(PVRSRV_DEVICE_NODE        *psDeviceNode,
                Allocate device memory for the firmware GPU framework state.
                Sufficient info to kick one or more DMs should be contained in this buffer
         */
-       PDUMPCOMMENT("Allocate Rogue firmware framework state");
+       PDUMPCOMMENT(psDeviceNode, "Allocate Rogue firmware framework state");
 
        eError = DevmemFwAllocate(psDevInfo,
                        ui32FrameworkCommandSize,
@@ -4734,11 +4907,10 @@ PVRSRV_ERROR RGXPollForGPCommandCompletion(PVRSRV_DEVICE_NODE  *psDevNode,
                                                                                                IMG_UINT32                      ui32Mask)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
-       RGXFWIF_CCB_CTL *psKCCBCtl;
        IMG_UINT32 ui32CurrentQueueLength, ui32MaxRetries;
        PVRSRV_RGXDEV_INFO      *psDevInfo = psDevNode->pvDevice;
+       const RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
 
-       psKCCBCtl = psDevInfo->psKernelCCBCtl;
        ui32CurrentQueueLength = (psKCCBCtl->ui32WrapMask+1 +
                                        psKCCBCtl->ui32WriteOffset -
                                        psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
@@ -4786,6 +4958,8 @@ PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
        IMG_UINT32 ui32kCCBCommandSlot;
        IMG_BOOL bWaitForFwUpdate = IMG_FALSE;
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        if (!psDevInfo)
        {
                return PVRSRV_ERROR_INVALID_PARAMS;
@@ -4819,7 +4993,7 @@ PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
                *pui32ConfigState = psSysData->ui32ConfigFlags;
        }
 
-       OSMemoryBarrier();
+       OSMemoryBarrier(&psSysData->ui32ConfigFlags);
 
        eError = PVRSRVPowerLock(psDeviceNode);
        PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVPowerLock");
@@ -4858,14 +5032,17 @@ unlock:
 
 static
 PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO      *psDevInfo,
-               RGXFWIF_DM                      eDM,
-               RGXFWIF_KCCB_CMD                *psKCCBCmd,
-               RGXFWIF_CLEANUP_TYPE    eCleanupType,
-               IMG_UINT32                              ui32PDumpFlags)
+                                                                          RGXFWIF_DM                   eDM,
+                                                                          RGXFWIF_KCCB_CMD             *psKCCBCmd,
+                                                                          RGXFWIF_CLEANUP_TYPE eCleanupType,
+                                                                          IMG_UINT32                   ui32PDumpFlags)
 {
        PVRSRV_ERROR eError;
        IMG_UINT32 ui32kCCBCommandSlot;
 
+       /* Clean-up commands sent during frame capture intervals must be dumped even when not in capture range... */
+       ui32PDumpFlags |= PDUMP_FLAGS_INTERVAL;
+
        psKCCBCmd->eCmdType = RGXFWIF_KCCB_CMD_CLEANUP;
        psKCCBCmd->uCmdData.sCleanupData.eCleanupType = eCleanupType;
 
@@ -4874,15 +5051,25 @@ PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO       *psDevInfo,
                the firmware will tell us and we'll drop out with a retry.
        */
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
-                                                 eDM,
+                                                                                         eDM,
                                                                                          psKCCBCmd,
-                                                                                         0,
                                                                                          ui32PDumpFlags,
                                                                                          &ui32kCCBCommandSlot);
-       PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", fail_command);
+       if (eError != PVRSRV_OK)
+       {
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR ,"RGXScheduleCommandAndGetKCCBSlot() failed (%s) in %s()",
+                                PVRSRVGETERRORSTRING(eError), __func__));
+               }
+               goto fail_command;
+       }
 
        /* Wait for command kCCB slot to be updated by FW */
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Wait for the firmware to reply to the cleanup command");
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                                 "Wait for the firmware to reply to the cleanup command");
        eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot,
                                                                          ui32PDumpFlags);
        /*
@@ -4919,7 +5106,8 @@ PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
         * If this is not the case, the following poll will block infinitely, making sure
         * the issue doesn't go unnoticed.
         */
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Cleanup: If this poll fails, the following resource is still in use (DM=%u, type=%u, address=0x%08x), which is incorrect in pdumps",
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                       "Cleanup: If this poll fails, the following resource is still in use (DM=%u, type=%u, address=0x%08x), which is incorrect in pdumps",
                        eDM,
                        psKCCBCmd->uCmdData.sCleanupData.eCleanupType,
                        psKCCBCmd->uCmdData.sCleanupData.uCleanupData.psContext.ui32Addr);
@@ -4982,9 +5170,9 @@ PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        psFWCommonContextFWAddr = FWCommonContextGetFWAddress(psServerCommonContext);
 #if defined(PDUMP)
-       PDUMPCOMMENT("Common ctx cleanup Request DM%d [context = 0x%08x]",
+       PDUMPCOMMENT(psDeviceNode, "Common ctx cleanup Request DM%d [context = 0x%08x]",
                        eDM, psFWCommonContextFWAddr.ui32Addr);
-       PDUMPCOMMENT("Wait for CCB to be empty before common ctx cleanup");
+       PDUMPCOMMENT(psDeviceNode, "Wait for CCB to be empty before common ctx cleanup");
 
        RGXCCBPDumpDrainCCB(FWCommonContextGetClientCCB(psServerCommonContext), ui32PDumpFlags);
 #endif
@@ -4994,10 +5182,10 @@ PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        /* Request cleanup of the firmware resource */
        eError = RGXScheduleCleanupCommand(psDeviceNode->pvDevice,
-                       eDM,
-                       &sRCCleanUpCmd,
-                       RGXFWIF_CLEANUP_FWCOMMONCONTEXT,
-                       ui32PDumpFlags);
+                                                                          eDM,
+                                                                          &sRCCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_FWCOMMONCONTEXT,
+                                                                          ui32PDumpFlags);
 
        if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
        {
@@ -5014,26 +5202,31 @@ PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
  */
 
 PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
-               PRGXFWIF_HWRTDATA psHWRTData)
+                                         PRGXFWIF_HWRTDATA psHWRTData)
 {
        RGXFWIF_KCCB_CMD                        sHWRTDataCleanUpCmd = {0};
        PVRSRV_ERROR                            eError;
 
-       PDUMPCOMMENT("HW RTData cleanup Request [HWRTData = 0x%08x]", psHWRTData.ui32Addr);
+       PDUMPCOMMENT(psDeviceNode, "HW RTData cleanup Request [HWRTData = 0x%08x]", psHWRTData.ui32Addr);
 
        sHWRTDataCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psHWRTData = psHWRTData;
 
        eError = RGXScheduleCleanupCommand(psDeviceNode->pvDevice,
-                       RGXFWIF_DM_GP,
-                       &sHWRTDataCleanUpCmd,
-                       RGXFWIF_CLEANUP_HWRTDATA,
-                       PDUMP_FLAGS_NONE);
+                                          RGXFWIF_DM_GP,
+                                          &sHWRTDataCleanUpCmd,
+                                          RGXFWIF_CLEANUP_HWRTDATA,
+                                          PDUMP_FLAGS_NONE);
 
-       if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+       if (eError != PVRSRV_OK)
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                        "%s: Failed to schedule a HWRTData cleanup with error (%u)",
-                        __func__, eError));
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to schedule a HWRTData cleanup with error (%u)",
+                                __func__, eError));
+               }
        }
 
        return eError;
@@ -5043,28 +5236,33 @@ PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
        RGXFWRequestFreeListCleanUp
 */
 PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
-               PRGXFWIF_FREELIST psFWFreeList)
+                                                                                PRGXFWIF_FREELIST psFWFreeList)
 {
        RGXFWIF_KCCB_CMD                        sFLCleanUpCmd = {0};
        PVRSRV_ERROR                            eError;
 
-       PDUMPCOMMENT("Free list cleanup Request [FreeList = 0x%08x]", psFWFreeList.ui32Addr);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Free list cleanup Request [FreeList = 0x%08x]", psFWFreeList.ui32Addr);
 
        /* Setup our command data, the cleanup call will fill in the rest */
        sFLCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psFreelist = psFWFreeList;
 
        /* Request cleanup of the firmware resource */
        eError = RGXScheduleCleanupCommand(psDevInfo,
-                       RGXFWIF_DM_GP,
-                       &sFLCleanUpCmd,
-                       RGXFWIF_CLEANUP_FREELIST,
-                       PDUMP_FLAGS_NONE);
+                                                                          RGXFWIF_DM_GP,
+                                                                          &sFLCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_FREELIST,
+                                                                          PDUMP_FLAGS_NONE);
 
-       if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+       if (eError != PVRSRV_OK)
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                        "%s: Failed to schedule a memory context cleanup with error (%u)",
-                        __func__, eError));
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to schedule a memory context cleanup with error (%u)",
+                                __func__, eError));
+               }
        }
 
        return eError;
@@ -5074,22 +5272,22 @@ PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
        RGXFWRequestZSBufferCleanUp
 */
 PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
-               PRGXFWIF_ZSBUFFER psFWZSBuffer)
+                                                                                PRGXFWIF_ZSBUFFER psFWZSBuffer)
 {
        RGXFWIF_KCCB_CMD                        sZSBufferCleanUpCmd = {0};
        PVRSRV_ERROR                            eError;
 
-       PDUMPCOMMENT("ZS Buffer cleanup Request [ZS Buffer = 0x%08x]", psFWZSBuffer.ui32Addr);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "ZS Buffer cleanup Request [ZS Buffer = 0x%08x]", psFWZSBuffer.ui32Addr);
 
        /* Setup our command data, the cleanup call will fill in the rest */
        sZSBufferCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psZSBuffer = psFWZSBuffer;
 
        /* Request cleanup of the firmware resource */
        eError = RGXScheduleCleanupCommand(psDevInfo,
-                       RGXFWIF_DM_3D,
-                       &sZSBufferCleanUpCmd,
-                       RGXFWIF_CLEANUP_ZSBUFFER,
-                       PDUMP_FLAGS_NONE);
+                                                                          RGXFWIF_DM_3D,
+                                                                          &sZSBufferCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_ZSBUFFER,
+                                                                          PDUMP_FLAGS_NONE);
 
        if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
        {
@@ -5104,8 +5302,19 @@ PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
 PVRSRV_ERROR RGXFWSetHCSDeadline(PVRSRV_RGXDEV_INFO *psDevInfo,
                IMG_UINT32 ui32HCSDeadlineMs)
 {
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS = ui32HCSDeadlineMs;
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the Hard Context Switching deadline inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32HCSDeadlineMS),
+                                                         ui32HCSDeadlineMs,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
 
        return PVRSRV_OK;
 }
@@ -5119,7 +5328,6 @@ PVRSRV_ERROR RGXFWHealthCheckCmd(PVRSRV_RGXDEV_INFO *psDevInfo)
        return  RGXScheduleCommand(psDevInfo,
                                                           RGXFWIF_DM_GP,
                                                           &sCmpKCCBCmd,
-                                                          0,
                                                           PDUMP_FLAGS_CONTINUOUS);
 }
 
@@ -5129,20 +5337,73 @@ PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32OSi
        PVRSRV_ERROR             eError = PVRSRV_OK;
        RGXFWIF_KCCB_CMD         sOSOnlineStateCmd = { 0 };
        RGXFWIF_SYSDATA          *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
        sOSOnlineStateCmd.eCmdType = RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE;
        sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.ui32OSid = ui32OSid;
        sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = eOSOnlineState;
 
-       if (eOSOnlineState == RGXFWIF_OS_ONLINE)
+#if defined(SUPPORT_AUTOVZ)
+       {
+               IMG_BOOL bConnectionDown = IMG_FALSE;
+
+               PVR_UNREFERENCED_PARAMETER(psFwSysData);
+               sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = RGXFWIF_OS_OFFLINE;
+
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       /* Send the offline command regardless if power lock is held or not.
+                        * Under AutoVz this is done during regular driver deinit, store-to-ram suspend
+                        * or (optionally) from a kernel panic callback. Deinit and suspend operations
+                        * take the lock in the rgx pre/post power functions as expected.
+                        * The kernel panic callback is a last resort way of letting the firmware know that
+                        * the VM is unrecoverable and the vz connection must be disabled. It cannot wait
+                        * on other kernel threads to finish and release the lock. */
+                       eError = RGXSendCommand(psDevInfo,
+                                                                       &sOSOnlineStateCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                       if (eError != PVRSRV_ERROR_RETRY)
+                       {
+                               break;
+                       }
+
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               /* Guests and Host going offline should wait for confirmation
+                * from the Firmware of the state change. If this fails, break
+                * the connection on the OS Driver's end as backup. */
+               if (PVRSRV_VZ_MODE_IS(GUEST) || (ui32OSid == RGXFW_HOST_OS))
+               {
+                       LOOP_UNTIL_TIMEOUT(SECONDS_TO_MICROSECONDS/2)
+                       {
+                               if (KM_FW_CONNECTION_IS(READY, psDevInfo))
+                               {
+                                       bConnectionDown = IMG_TRUE;
+                                       break;
+                               }
+                       } END_LOOP_UNTIL_TIMEOUT();
+
+                       if (!bConnectionDown)
+                       {
+                               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+                       }
+               }
+       }
+#else
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               /* no reason for Guests to update their state or any other VM's.
+                * This is the Hypervisor and Host driver's responsibility. */
+               return PVRSRV_OK;
+       }
+       else if (eOSOnlineState == RGXFWIF_OS_ONLINE)
        {
                LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
                {
                        eError = RGXScheduleCommand(psDevInfo,
                                        RGXFWIF_DM_GP,
                                        &sOSOnlineStateCmd,
-                                       0,
                                        PDUMP_FLAGS_CONTINUOUS);
                        if (eError != PVRSRV_ERROR_RETRY) break;
 
@@ -5151,18 +5412,18 @@ PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32OSi
        }
        else if (psFwSysData)
        {
-               IMG_UINT32 ui32kCCBCommandSlot;
-               volatile RGXFWIF_OS_RUNTIME_FLAGS *psFwRunFlags;
+               const volatile RGXFWIF_OS_RUNTIME_FLAGS *psFwRunFlags =
+                        (const volatile RGXFWIF_OS_RUNTIME_FLAGS*) &psFwSysData->asOsRuntimeFlagsMirror[ui32OSid];
 
-               psFwRunFlags = (volatile RGXFWIF_OS_RUNTIME_FLAGS*) &psFwSysData->asOsRuntimeFlagsMirror[ui32OSid];
                /* Attempt several times until the FW manages to offload the OS */
                LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
                {
+                       IMG_UINT32 ui32kCCBCommandSlot;
+
                        /* Send request */
                        eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
                                                                  RGXFWIF_DM_GP,
                                                                                                          &sOSOnlineStateCmd,
-                                                                                                         0,
                                                                                                          PDUMP_FLAGS_CONTINUOUS,
                                                                                                          &ui32kCCBCommandSlot);
                        if (unlikely(eError == PVRSRV_ERROR_RETRY)) continue;
@@ -5173,7 +5434,7 @@ PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32OSi
                        PVR_LOG_GOTO_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate", return_);
 
                        /* read the OS state */
-                       OSMemoryBarrier();
+                       OSMemoryBarrier(NULL);
                        /* check if FW finished offloading the OSID and is stopped */
                        if (psFwRunFlags->bfOsState == RGXFW_CONNECTION_FW_OFFLINE)
                        {
@@ -5194,6 +5455,7 @@ PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32OSi
        }
 
 return_ :
+#endif
        return eError;
 }
 
@@ -5204,15 +5466,26 @@ PVRSRV_ERROR RGXFWChangeOSidPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
        PVRSRV_ERROR eError;
        RGXFWIF_KCCB_CMD        sOSidPriorityCmd = { 0 };
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        sOSidPriorityCmd.eCmdType = RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE;
        psDevInfo->psRGXFWIfRuntimeCfg->aui32OSidPriority[ui32OSid] = ui32Priority;
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->aui32OSidPriority[ui32OSid]);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the priority of OSID%u inside RGXFWIfRuntimeCfg", ui32OSid);
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, aui32OSidPriority) + (ui32OSid * sizeof(ui32Priority)),
+                                                         ui32Priority ,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
 
        LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
        {
                eError = RGXScheduleCommand(psDevInfo,
                                RGXFWIF_DM_GP,
                                &sOSidPriorityCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -5236,9 +5509,10 @@ PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
        RGXFWIF_CCB_CMD_HEADER  *psCmdHeader;
        RGXFWIF_CMD_PRIORITY    *psCmd;
        PVRSRV_ERROR                    eError;
+       IMG_INT32 i32Priority = (IMG_INT32)ui32Priority;
        RGX_CLIENT_CCB *psClientCCB = FWCommonContextGetClientCCB(psContext);
 
-       eError = _CheckPriority(psDevInfo, ui32Priority, psContext->eRequestor);
+       eError = _CheckPriority(psDevInfo, i32Priority, psContext->eRequestor);
        PVR_LOG_GOTO_IF_ERROR(eError, "_CheckPriority", fail_checkpriority);
 
        /*
@@ -5268,7 +5542,7 @@ PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
        pui8CmdPtr += sizeof(*psCmdHeader);
 
        psCmd = (RGXFWIF_CMD_PRIORITY *) pui8CmdPtr;
-       psCmd->ui32Priority = ui32Priority;
+       psCmd->i32Priority = i32Priority;
        pui8CmdPtr += sizeof(*psCmd);
 
        /*
@@ -5304,7 +5578,6 @@ PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
                eError = RGXScheduleCommand(psDevInfo,
                                eDM,
                                &sPriorityCmd,
-                               0,
                                PDUMP_FLAGS_CONTINUOUS);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -5319,14 +5592,16 @@ PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
                                "%s: Failed to submit set priority command with error (%u)",
                                __func__,
                                eError));
+               goto fail_cmdacquire;
        }
 
-       psContext->ui32Priority = ui32Priority;
+       psContext->i32Priority = i32Priority;
 
        return PVRSRV_OK;
 
 fail_ccbacquire:
 fail_checkpriority:
+fail_cmdacquire:
        PVR_ASSERT(eError != PVRSRV_OK);
        return eError;
 }
@@ -5337,16 +5612,26 @@ PVRSRV_ERROR RGXFWConfigPHR(PVRSRV_RGXDEV_INFO *psDevInfo,
        PVRSRV_ERROR eError;
        RGXFWIF_KCCB_CMD sCfgPHRCmd = { 0 };
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        sCfgPHRCmd.eCmdType = RGXFWIF_KCCB_CMD_PHR_CFG;
        psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode = ui32PHRMode;
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the Periodic Hardware Reset Mode inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32PHRMode),
+                                                         ui32PHRMode,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
 
        LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
        {
                eError = RGXScheduleCommand(psDevInfo,
                                            RGXFWIF_DM_GP,
                                            &sCfgPHRCmd,
-                                           0,
                                            PDUMP_FLAGS_CONTINUOUS);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -5364,16 +5649,26 @@ PVRSRV_ERROR RGXFWConfigWdg(PVRSRV_RGXDEV_INFO *psDevInfo,
        PVRSRV_ERROR eError;
        RGXFWIF_KCCB_CMD sCfgWdgCmd = { 0 };
 
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
        sCfgWdgCmd.eCmdType = RGXFWIF_KCCB_CMD_WDG_CFG;
        psDevInfo->psRGXFWIfRuntimeCfg->ui32WdgPeriodUs = ui32WdgPeriodUs;
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32WdgPeriodUs);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the firmware watchdog period inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32WdgPeriodUs),
+                                                         ui32WdgPeriodUs,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
 
        LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
        {
                eError = RGXScheduleCommand(psDevInfo,
                                                                        RGXFWIF_DM_GP,
                                                                        &sCfgWdgCmd,
-                                                                       0,
                                                                        PDUMP_FLAGS_CONTINUOUS);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -5385,72 +5680,7 @@ PVRSRV_ERROR RGXFWConfigWdg(PVRSRV_RGXDEV_INFO *psDevInfo,
        return eError;
 }
 
-/*
-       RGXReadMETAAddr
-*/
-PVRSRV_ERROR RGXReadMETAAddr(PVRSRV_RGXDEV_INFO        *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 *pui32Value)
-{
-       IMG_UINT8 __iomem  *pui8RegBase = psDevInfo->pvRegsBaseKM;
-       IMG_UINT32 ui32Value;
 
-       /* Wait for Slave Port to be Ready */
-       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
-                       (IMG_UINT32 __iomem *) (pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
-       {
-               return PVRSRV_ERROR_TIMEOUT;
-       }
-
-       /* Issue the Read */
-       OSWriteHWReg32(
-                       psDevInfo->pvRegsBaseKM,
-                       RGX_CR_META_SP_MSLVCTRL0,
-                       ui32METAAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN);
-       (void) OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0);
-
-       /* Wait for Slave Port to be Ready: read complete */
-       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
-                       (IMG_UINT32 __iomem *) (pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
-       {
-               return PVRSRV_ERROR_TIMEOUT;
-       }
-
-       /* Read the value */
-       ui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAX);
-
-       *pui32Value = ui32Value;
-
-       return PVRSRV_OK;
-}
-
-/*
-       RGXWriteMETAAddr
-*/
-PVRSRV_ERROR RGXWriteMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 ui32Value)
-{
-       IMG_UINT8 __iomem *pui8RegBase = psDevInfo->pvRegsBaseKM;
-
-       /* Wait for Slave Port to be Ready */
-       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
-                       (IMG_UINT32 __iomem *)(pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
-                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
-       {
-               return PVRSRV_ERROR_TIMEOUT;
-       }
-
-       /* Issue the Write */
-       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0, ui32METAAddr);
-       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAT, ui32Value);
-
-       return PVRSRV_OK;
-}
 
 void RGXCheckForStalledClientContexts(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bIgnorePrevious)
 {
@@ -5527,14 +5757,14 @@ void RGXCheckForStalledClientContexts(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bI
 PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
                                    IMG_BOOL bCheckAfterTimePassed)
 {
-       PVRSRV_DATA*                 psPVRSRVData = PVRSRVGetPVRSRVData();
+       const PVRSRV_DATA*           psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_HEALTH_STATUS  eNewStatus   = PVRSRV_DEVICE_HEALTH_STATUS_OK;
        PVRSRV_DEVICE_HEALTH_REASON  eNewReason   = PVRSRV_DEVICE_HEALTH_REASON_NONE;
        PVRSRV_RGXDEV_INFO*          psDevInfo;
-       RGXFWIF_TRACEBUF*            psRGXFWIfTraceBufCtl;
-       RGXFWIF_SYSDATA*             psFwSysData;
-       RGXFWIF_OSDATA*              psFwOsData;
-       RGXFWIF_CCB_CTL              *psKCCBCtl;
+       const RGXFWIF_TRACEBUF*      psRGXFWIfTraceBufCtl;
+       const RGXFWIF_SYSDATA*       psFwSysData;
+       const RGXFWIF_OSDATA*        psFwOsData;
+       const RGXFWIF_CCB_CTL*       psKCCBCtl;
        IMG_UINT32                   ui32ThreadCount;
        IMG_BOOL                     bKCCBCmdsWaiting;
 
@@ -5575,7 +5805,7 @@ PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
                         */
                        for (ui32ThreadCount = 0; ui32ThreadCount < RGXFW_THREAD_NUM; ui32ThreadCount++)
                        {
-                               IMG_CHAR* pszTraceAssertInfo = psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szInfo;
+                               const IMG_CHAR* pszTraceAssertInfo = psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szInfo;
 
                                /*
                                Check if the FW has hit an assert...
@@ -6062,7 +6292,6 @@ PVRSRV_ERROR RGXGetPhyAddr(PMR *psPMR,
 #if defined(PDUMP)
 PVRSRV_ERROR RGXPdumpDrainKCCB(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32WriteOffset)
 {
-       RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
        PVRSRV_ERROR eError = PVRSRV_OK;
 
        if (psDevInfo->bDumpedKCCBCtlAlready)
@@ -6071,9 +6300,10 @@ PVRSRV_ERROR RGXPdumpDrainKCCB(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Wri
                psDevInfo->bDumpedKCCBCtlAlready = IMG_FALSE;
 
                /* make sure previous cmd is drained in pdump in case we will 'jump' over some future cmds */
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER,
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                               PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER,
                                "kCCB(%p): Draining rgxfw_roff (0x%x) == woff (0x%x)",
-                               psKCCBCtl,
+                               psDevInfo->psKernelCCBCtl,
                                ui32WriteOffset,
                                ui32WriteOffset);
                eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBCtlMemDesc,
@@ -6145,7 +6375,7 @@ PVRSRV_ERROR RGXClientConnectCompatCheck_ClientAgainstFW(PVRSRV_DEVICE_NODE *psD
        {
                PVRSRV_ERROR eError;
 
-               PDUMPCOMMENT("Compatibility check: client and FW build options");
+               PDUMPCOMMENT(psDeviceNode, "Compatibility check: client and FW build options");
                eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                                offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                                offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
@@ -6218,7 +6448,7 @@ PVRSRV_ERROR RGXFwRawHeapAllocMap(PVRSRV_DEVICE_NODE *psDeviceNode,
        PVRSRV_ERROR eError;
        IMG_CHAR szRegionRAName[RA_MAX_NAME_LENGTH];
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       PVRSRV_MEMALLOCFLAGS_T uiRawFwHeapAllocFlags = (RGX_FWSHAREDMEM_ALLOCFLAGS |
+       PVRSRV_MEMALLOCFLAGS_T uiRawFwHeapAllocFlags = (RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS |
                                                                                                        PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_PREMAP0 + ui32OSID));
        PHYS_HEAP_CONFIG *psFwMainConfig = FindPhysHeapConfig(psDeviceNode->psDevConfig,
                                                                                                                   PHYS_HEAP_USAGE_FW_MAIN);
@@ -6257,7 +6487,7 @@ PVRSRV_ERROR RGXFwRawHeapAllocMap(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_PREMAP0 + ui32OSID] = psDeviceNode->apsFWPremapPhysHeap[ui32OSID];
 
-       PDUMPCOMMENT("Allocate and map raw firmware heap for OSID: [%d]", ui32OSID);
+       PDUMPCOMMENT(psDeviceNode, "Allocate and map raw firmware heap for OSID: [%d]", ui32OSID);
 
 #if (RGX_NUM_OS_SUPPORTED > 1)
        /* don't clear the heap of other guests on allocation */
@@ -6336,18 +6566,19 @@ void RGXFwRawHeapUnmapFree(PVRSRV_DEVICE_NODE *psDeviceNode,
 PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PVR_UNREFERENCED_PARAMETER(psDevInfo);
-
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Halt RISC-V FW");
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Halt RISC-V FW");
 
        /* Send halt request (no need to select one or more harts on this RISC-V core) */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
                   RGX_CR_FWCORE_DMI_DMCONTROL_HALTREQ_EN |
                   RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until hart is halted */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_DMSTATUS,
                    RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
                    RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
@@ -6355,7 +6586,8 @@ PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo)
                    PDUMP_POLL_OPERATOR_EQUAL);
 
        /* Clear halt request */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
                   RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
                   PDUMP_FLAGS_CONTINUOUS);
 #else
@@ -6388,6 +6620,29 @@ PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo)
 
 /*!
 *******************************************************************************
+@Function       RGXRiscvIsHalted
+
+@Description    Check if the RISC-V FW is halted
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         IMG_BOOL
+******************************************************************************/
+IMG_BOOL RGXRiscvIsHalted(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(NO_HARDWARE)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       /* Assume the core is always halted in nohw */
+       return IMG_TRUE;
+#else
+
+       return (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMSTATUS) &
+               RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN) != 0U;
+#endif
+}
+
+/*!
+*******************************************************************************
 @Function       RGXRiscvResume
 
 @Description    Resume the RISC-V FW core
@@ -6399,18 +6654,19 @@ PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo)
 PVRSRV_ERROR RGXRiscvResume(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PVR_UNREFERENCED_PARAMETER(psDevInfo);
-
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Resume RISC-V FW");
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Resume RISC-V FW");
 
        /* Send resume request (no need to select one or more harts on this RISC-V core) */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
                   RGX_CR_FWCORE_DMI_DMCONTROL_RESUMEREQ_EN |
                   RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until hart is resumed */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_DMSTATUS,
                    RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
                    RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
@@ -6418,7 +6674,8 @@ PVRSRV_ERROR RGXRiscvResume(PVRSRV_RGXDEV_INFO *psDevInfo)
                    PDUMP_POLL_OPERATOR_EQUAL);
 
        /* Clear resume request */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
                   RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
                   PDUMP_FLAGS_CONTINUOUS);
 #else
@@ -6455,26 +6712,28 @@ PVRSRV_ERROR RGXRiscvResume(PVRSRV_RGXDEV_INFO *psDevInfo)
 
 @Description    Check for RISC-V abstract command errors and clear them
 
-@Input          pvRegsBaseKM    Pointer to GPU register base
+@Input          psDevInfo    Pointer to GPU device info
 
 @Return         RGXRISCVFW_ABSTRACT_CMD_ERR
 ******************************************************************************/
-static RGXRISCVFW_ABSTRACT_CMD_ERR RGXRiscvCheckAbstractCmdError(void __iomem *pvRegsBaseKM)
+static RGXRISCVFW_ABSTRACT_CMD_ERR RGXRiscvCheckAbstractCmdError(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
        RGXRISCVFW_ABSTRACT_CMD_ERR eCmdErr;
 
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PVR_UNREFERENCED_PARAMETER(pvRegsBaseKM);
        eCmdErr = RISCV_ABSTRACT_CMD_NO_ERROR;
 
        /* Check error status */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS,
                    RISCV_ABSTRACT_CMD_NO_ERROR << RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_SHIFT,
                    ~RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_CLRMSK,
                    PDUMP_FLAGS_CONTINUOUS,
                    PDUMP_POLL_OPERATOR_EQUAL);
 #else
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+
        /* Check error status */
        eCmdErr = (OSReadHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)
                  & ~RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_CLRMSK)
@@ -6540,7 +6799,7 @@ PVRSRV_ERROR RGXRiscvReadReg(PVRSRV_RGXDEV_INFO *psDevInfo,
                return PVRSRV_ERROR_TIMEOUT;
        }
 
-       if (RGXRiscvCheckAbstractCmdError(psDevInfo->pvRegsBaseKM) == RISCV_ABSTRACT_CMD_NO_ERROR)
+       if (RGXRiscvCheckAbstractCmdError(psDevInfo) == RISCV_ABSTRACT_CMD_NO_ERROR)
        {
                /* Read register value */
                *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0);
@@ -6571,14 +6830,12 @@ PVRSRV_ERROR RGXRiscvPollReg(PVRSRV_RGXDEV_INFO *psDevInfo,
                              IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
-
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Poll RISC-V register 0x%x (expected 0x%08x)",
                              ui32RegAddr, ui32Value);
 
        /* Send abstract register read command */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
                   (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
                   RGXRISCVFW_DMI_COMMAND_READ |
                   RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
@@ -6586,17 +6843,19 @@ PVRSRV_ERROR RGXRiscvPollReg(PVRSRV_RGXDEV_INFO *psDevInfo,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until abstract command is completed */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS,
                    0U,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
                    PDUMP_FLAGS_CONTINUOUS,
                    PDUMP_POLL_OPERATOR_EQUAL);
 
-       RGXRiscvCheckAbstractCmdError(pvRegsBaseKM);
+       RGXRiscvCheckAbstractCmdError(psDevInfo);
 
        /* Check read value */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_DATA0,
                    ui32Value,
                    0xFFFFFFFF,
@@ -6631,15 +6890,16 @@ PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
                               IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Write RISC-V register 0x%x (value 0x%08x)",
                              ui32RegAddr, ui32Value);
 
        /* Prepare data to be written to register */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0, ui32Value, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
 
        /* Send abstract register write command */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
                   (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
                   RGXRISCVFW_DMI_COMMAND_WRITE |
                   RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
@@ -6647,7 +6907,8 @@ PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until abstract command is completed */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS,
                    0U,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
@@ -6689,25 +6950,27 @@ PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 @Description    Check for RISC-V system bus errors and clear them
 
-@Input          pvRegsBaseKM    Pointer to GPU register base
+@Input          psDevInfo    Pointer to GPU device info
 
 @Return         RGXRISCVFW_SYSBUS_ERR
 ******************************************************************************/
-static RGXRISCVFW_SYSBUS_ERR RGXRiscvCheckSysBusError(void __iomem *pvRegsBaseKM)
+static __maybe_unused RGXRISCVFW_SYSBUS_ERR RGXRiscvCheckSysBusError(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
        RGXRISCVFW_SYSBUS_ERR eSBError;
 
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PVR_UNREFERENCED_PARAMETER(pvRegsBaseKM);
        eSBError = RISCV_SYSBUS_NO_ERROR;
 
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_SBCS,
                    RISCV_SYSBUS_NO_ERROR << RGX_CR_FWCORE_DMI_SBCS_SBERROR_SHIFT,
                    ~RGX_CR_FWCORE_DMI_SBCS_SBERROR_CLRMSK,
                    PDUMP_FLAGS_CONTINUOUS,
                    PDUMP_POLL_OPERATOR_EQUAL);
 #else
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+
        eSBError = (OSReadHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBCS)
                 & ~RGX_CR_FWCORE_DMI_SBCS_SBERROR_CLRMSK)
                 >> RGX_CR_FWCORE_DMI_SBCS_SBERROR_SHIFT;
@@ -6725,6 +6988,7 @@ static RGXRISCVFW_SYSBUS_ERR RGXRiscvCheckSysBusError(void __iomem *pvRegsBaseKM
        return eSBError;
 }
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
 /*!
 *******************************************************************************
 @Function       RGXRiscvReadAbstractMem
@@ -6774,7 +7038,7 @@ RGXRiscvReadAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_
                return PVRSRV_ERROR_TIMEOUT;
        }
 
-       if (RGXRiscvCheckAbstractCmdError(psDevInfo->pvRegsBaseKM) == RISCV_ABSTRACT_CMD_NO_ERROR)
+       if (RGXRiscvCheckAbstractCmdError(psDevInfo) == RISCV_ABSTRACT_CMD_NO_ERROR)
        {
                /* Read memory value */
                *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0);
@@ -6787,6 +7051,7 @@ RGXRiscvReadAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_
        return PVRSRV_OK;
 #endif
 }
+#endif /* !defined(EMULATOR) */
 
 /*!
 *******************************************************************************
@@ -6805,34 +7070,35 @@ static PVRSRV_ERROR
 RGXRiscvPollAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
-
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Poll RISC-V address 0x%x (expected 0x%08x)",
                              ui32Addr, ui32Value);
 
        /* Prepare read address  */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1, ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
 
        /* Send abstract memory read command */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
                   (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
                   RGXRISCVFW_DMI_COMMAND_READ |
                   RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until abstract command is completed */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS,
                    0U,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
                    PDUMP_FLAGS_CONTINUOUS,
                    PDUMP_POLL_OPERATOR_EQUAL);
 
-       RGXRiscvCheckAbstractCmdError(pvRegsBaseKM);
+       RGXRiscvCheckAbstractCmdError(psDevInfo);
 
        /* Check read value */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_DATA0,
                    ui32Value,
                    0xFFFFFFFF,
@@ -6850,6 +7116,7 @@ RGXRiscvPollAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_
 #endif
 }
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
 /*!
 *******************************************************************************
 @Function       RGXRiscvReadSysBusMem
@@ -6898,7 +7165,7 @@ RGXRiscvReadSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UI
                return PVRSRV_ERROR_TIMEOUT;
        }
 
-       if (RGXRiscvCheckSysBusError(psDevInfo->pvRegsBaseKM) == RISCV_SYSBUS_NO_ERROR)
+       if (RGXRiscvCheckSysBusError(psDevInfo) == RISCV_SYSBUS_NO_ERROR)
        {
                /* Read value from debug system bus */
                *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBDATA0);
@@ -6911,6 +7178,7 @@ RGXRiscvReadSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UI
        return PVRSRV_OK;
 #endif
 }
+#endif /* !defined(EMULATOR) */
 
 /*!
 *******************************************************************************
@@ -6929,35 +7197,36 @@ static PVRSRV_ERROR
 RGXRiscvPollSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
-
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Poll RISC-V address 0x%x (expected 0x%08x)",
                              ui32Addr, ui32Value);
 
        /* Configure system bus to read 32 bit every time a new address is provided */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
                   (RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT) |
                   RGX_CR_FWCORE_DMI_SBCS_SBREADONADDR_EN,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Perform read */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0,
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0,
                   ui32Addr,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until system bus is idle */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_SBCS,
                    0U,
                    RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
                    PDUMP_FLAGS_CONTINUOUS,
                    PDUMP_POLL_OPERATOR_EQUAL);
 
-       RGXRiscvCheckSysBusError(pvRegsBaseKM);
+       RGXRiscvCheckSysBusError(psDevInfo);
 
        /* Check read value */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_SBDATA0,
                    ui32Value,
                    0xFFFFFFFF,
@@ -6975,6 +7244,7 @@ RGXRiscvPollSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UI
 #endif
 }
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
 /*!
 *******************************************************************************
 @Function       RGXRiscvReadMem
@@ -6988,7 +7258,7 @@ RGXRiscvPollSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UI
 
 @Return         PVRSRV_ERROR
 ******************************************************************************/
-PVRSRV_ERROR RGXRiscvReadMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+static PVRSRV_ERROR RGXRiscvReadMem(PVRSRV_RGXDEV_INFO *psDevInfo,
                              IMG_UINT32 ui32Addr,
                              IMG_UINT32 *pui32Value)
 {
@@ -6999,6 +7269,7 @@ PVRSRV_ERROR RGXRiscvReadMem(PVRSRV_RGXDEV_INFO *psDevInfo,
 
        return RGXRiscvReadSysBusMem(psDevInfo, ui32Addr, pui32Value);
 }
+#endif /* !defined(EMULATOR) */
 
 /*!
 *******************************************************************************
@@ -7024,6 +7295,7 @@ PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
        return RGXRiscvPollSysBusMem(psDevInfo, ui32Addr, ui32Value);
 }
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
 /*!
 *******************************************************************************
 @Function       RGXRiscvWriteAbstractMem
@@ -7041,25 +7313,28 @@ static PVRSRV_ERROR
 RGXRiscvWriteAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Write RISC-V address 0x%x (value 0x%08x)",
                              ui32Addr, ui32Value);
 
        /* Prepare write address */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1, ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
 
        /* Prepare write data */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0, ui32Value, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
 
        /* Send abstract register write command */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
                   (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
                   RGXRISCVFW_DMI_COMMAND_WRITE |
                   RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until abstract command is completed */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS,
                    0U,
                    RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
@@ -7114,23 +7389,26 @@ static PVRSRV_ERROR
 RGXRiscvWriteSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
 {
 #if defined(NO_HARDWARE) && defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
                              "Write RISC-V address 0x%x (value 0x%08x)",
                              ui32Addr, ui32Value);
 
        /* Configure system bus to read 32 bit every time a new address is provided */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
                   RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT,
                   PDUMP_FLAGS_CONTINUOUS);
 
        /* Prepare write address */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0, ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
 
        /* Prepare write data and initiate write */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBDATA0, ui32Value, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBDATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
 
        /* Wait until system bus is idle */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
                    RGX_CR_FWCORE_DMI_SBCS,
                    0U,
                    RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
@@ -7178,7 +7456,7 @@ RGXRiscvWriteSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_U
 
 @Return         PVRSRV_ERROR
 ******************************************************************************/
-PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+static PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
                               IMG_UINT32 ui32Addr,
                               IMG_UINT32 ui32Value)
 {
@@ -7189,6 +7467,358 @@ PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
 
        return RGXRiscvWriteSysBusMem(psDevInfo, ui32Addr, ui32Value);
 }
+#endif /* !defined(EMULATOR) */
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvDmiOp
+
+@Description    Acquire the powerlock and perform an operation on the RISC-V
+                Debug Module Interface, but only if the GPU is powered on.
+
+@Input          psDevInfo       Pointer to device info
+@InOut          pui64DMI        Encoding of a request for the RISC-V Debug
+                                Module with same format as the 'dmi' register
+                                from the RISC-V debug specification (v0.13+).
+                                On return, this is updated with the result of
+                                the request, encoded the same way.
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvDmiOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                           IMG_UINT64 *pui64DMI)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(pui64DMI);
+
+       /* Accessing DM registers is not supported in nohw/pdump */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#else
+#define DMI_BASE     RGX_CR_FWCORE_DMI_RESERVED00
+#define DMI_STRIDE  (RGX_CR_FWCORE_DMI_RESERVED01 - RGX_CR_FWCORE_DMI_RESERVED00)
+#define DMI_REG(r)  ((DMI_BASE) + (DMI_STRIDE) * (r))
+
+#define DMI_OP_SHIFT            0U
+#define DMI_OP_MASK             0x3ULL
+#define DMI_DATA_SHIFT          2U
+#define DMI_DATA_MASK           0x3FFFFFFFCULL
+#define DMI_ADDRESS_SHIFT       34U
+#define DMI_ADDRESS_MASK        0xFC00000000ULL
+
+#define DMI_OP_NOP                 0U
+#define DMI_OP_READ                1U
+#define DMI_OP_WRITE           2U
+#define DMI_OP_RESERVED                3U
+
+#define DMI_OP_STATUS_SUCCESS  0U
+#define DMI_OP_STATUS_RESERVED 1U
+#define DMI_OP_STATUS_FAILED   2U
+#define DMI_OP_STATUS_BUSY         3U
+
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       PVRSRV_DEV_POWER_STATE ePowerState;
+       PVRSRV_ERROR eError;
+       IMG_UINT64 ui64Op, ui64Address, ui64Data;
+
+       ui64Op      = (*pui64DMI & DMI_OP_MASK) >> DMI_OP_SHIFT;
+       ui64Address = (*pui64DMI & DMI_ADDRESS_MASK) >> DMI_ADDRESS_SHIFT;
+       ui64Data    = (*pui64DMI & DMI_DATA_MASK) >> DMI_DATA_SHIFT;
+
+       eError = PVRSRVPowerLock(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire powerlock (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               ui64Op = DMI_OP_STATUS_FAILED;
+               goto dmiop_update;
+       }
+
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to retrieve RGX power state (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               ui64Op = DMI_OP_STATUS_FAILED;
+               goto dmiop_release_lock;
+       }
+
+       if (ePowerState == PVRSRV_DEV_POWER_STATE_ON)
+       {
+               switch (ui64Op)
+               {
+                       case DMI_OP_NOP:
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       case DMI_OP_WRITE:
+                               OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                                               DMI_REG(ui64Address),
+                                               (IMG_UINT32)ui64Data);
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       case DMI_OP_READ:
+                               ui64Data = (IMG_UINT64)OSReadHWReg32(psDevInfo->pvRegsBaseKM,
+                                               DMI_REG(ui64Address));
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       default:
+                               PVR_DPF((PVR_DBG_ERROR, "%s: unknown op %u", __func__, (IMG_UINT32)ui64Op));
+                               ui64Op = DMI_OP_STATUS_FAILED;
+                               break;
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: Accessing RISC-V Debug Module is not "
+                                       "possible while the GPU is powered off", __func__));
+
+               ui64Op = DMI_OP_STATUS_FAILED;
+       }
+
+dmiop_release_lock:
+       PVRSRVPowerUnlock(psDeviceNode);
+
+dmiop_update:
+       *pui64DMI = (ui64Op << DMI_OP_SHIFT) |
+               (ui64Address << DMI_ADDRESS_SHIFT) |
+               (ui64Data << DMI_DATA_SHIFT);
+
+       return eError;
+#endif
+}
+
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+/*
+       RGXReadMETAAddr
+*/
+static PVRSRV_ERROR RGXReadMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 *pui32Value)
+{
+       IMG_UINT8 __iomem  *pui8RegBase = psDevInfo->pvRegsBaseKM;
+       IMG_UINT32 ui32Value;
+
+       /* Wait for Slave Port to be Ready */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                       (IMG_UINT32 __iomem *) (pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Issue the Read */
+       OSWriteHWReg32(
+                       psDevInfo->pvRegsBaseKM,
+                       RGX_CR_META_SP_MSLVCTRL0,
+                       ui32METAAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN);
+       (void) OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0);
+
+       /* Wait for Slave Port to be Ready: read complete */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                       (IMG_UINT32 __iomem *) (pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Read the value */
+       ui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAX);
+
+       *pui32Value = ui32Value;
+
+       return PVRSRV_OK;
+}
+
+/*
+       RGXWriteMETAAddr
+*/
+static PVRSRV_ERROR RGXWriteMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 ui32Value)
+{
+       IMG_UINT8 __iomem *pui8RegBase = psDevInfo->pvRegsBaseKM;
+
+       /* Wait for Slave Port to be Ready */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                       (IMG_UINT32 __iomem *)(pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                       POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Issue the Write */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0, ui32METAAddr);
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAT, ui32Value);
+
+       return PVRSRV_OK;
+}
+#endif
+
+PVRSRV_ERROR RGXReadFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 *pui32Value)
+{
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               return RGXReadMETAAddr(psDevInfo, ui32FWAddr, pui32Value);
+       }
+#endif
+
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               return RGXRiscvReadMem(psDevInfo, ui32FWAddr, pui32Value);
+       }
+#endif
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR RGXWriteFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 ui32Value)
+{
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               return RGXWriteMETAAddr(psDevInfo, ui32FWAddr, ui32Value);
+       }
+#endif
+
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               return RGXRiscvWriteMem(psDevInfo, ui32FWAddr, ui32Value);
+       }
+#endif
+
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+PVRSRV_ERROR RGXGetFwMapping(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32FwVA,
+                             IMG_CPU_PHYADDR *psCpuPA,
+                             IMG_DEV_PHYADDR *psDevPA,
+                             IMG_UINT64 *pui64RawPTE)
+{
+       PVRSRV_ERROR eError       = PVRSRV_OK;
+       IMG_CPU_PHYADDR sCpuPA    = {0U};
+       IMG_DEV_PHYADDR sDevPA    = {0U};
+       IMG_UINT64 ui64RawPTE     = 0U;
+       MMU_FAULT_DATA sFaultData = {0U};
+       MMU_CONTEXT *psFwMMUCtx   = psDevInfo->psKernelMMUCtx;
+       IMG_UINT32 ui32FwHeapBase = (IMG_UINT32) (RGX_FIRMWARE_RAW_HEAP_BASE & UINT_MAX);
+       IMG_UINT32 ui32FwHeapEnd  = ui32FwHeapBase + (RGX_NUM_OS_SUPPORTED * RGX_FIRMWARE_RAW_HEAP_SIZE);
+       IMG_UINT32 ui32OSID       = (ui32FwVA - ui32FwHeapBase) / RGX_FIRMWARE_RAW_HEAP_SIZE;
+       IMG_UINT32 ui32HeapId;
+       PHYS_HEAP *psPhysHeap;
+
+       /* MIPS uses the same page size as the OS, while others default to 4K pages */
+       IMG_UINT32 ui32FwPageSize = RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) ?
+                                    OSGetPageSize() : BIT(RGX_MMUCTRL_PAGE_4KB_RANGE_SHIFT);
+       IMG_UINT32 ui32PageOffset = (ui32FwVA & (ui32FwPageSize - 1));
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM((ui32OSID < RGX_NUM_OS_SUPPORTED),
+                                     eError, ErrorExit);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(((psCpuPA != NULL) ||
+                                      (psDevPA != NULL) ||
+                                      (pui64RawPTE != NULL)),
+                                     eError, ErrorExit);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(((ui32FwVA >= ui32FwHeapBase) &&
+                                     (ui32FwVA < ui32FwHeapEnd)),
+                                     eError, ErrorExit);
+
+       ui32HeapId = (ui32OSID == RGXFW_HOST_OS) ?
+                     PVRSRV_PHYS_HEAP_FW_MAIN : (PVRSRV_PHYS_HEAP_FW_PREMAP0 + ui32OSID);
+       psPhysHeap = psDevInfo->psDeviceNode->apsPhysHeap[ui32HeapId];
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       {
+               /* MIPS is equipped with a dedicated MMU  */
+               RGXMipsCheckFaultAddress(psFwMMUCtx, ui32FwVA, &sFaultData);
+       }
+       else
+       {
+               IMG_UINT64 ui64FwDataBaseMask;
+               IMG_DEV_VIRTADDR sDevVAddr;
+
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       ui64FwDataBaseMask = ~(RGXFW_SEGMMU_DATA_META_CACHE_MASK |
+                                                RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK |
+                                                RGXFW_SEGMMU_DATA_BASE_ADDRESS);
+               }
+               else
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK) && !defined(EMULATOR)
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+               {
+                       ui64FwDataBaseMask = ~(RGXRISCVFW_GET_REGION_BASE(0xF));
+               }
+               else
+#endif
+               {
+                       PVR_LOG_GOTO_WITH_ERROR("RGXGetFwMapping", eError, PVRSRV_ERROR_NOT_IMPLEMENTED, ErrorExit);
+               }
+
+               sDevVAddr.uiAddr = (ui32FwVA & ui64FwDataBaseMask) | RGX_FIRMWARE_RAW_HEAP_BASE;
+
+               /* Fw CPU shares a subset of the GPU's VA space */
+               MMU_CheckFaultAddress(psFwMMUCtx, &sDevVAddr, &sFaultData);
+       }
+
+       ui64RawPTE = sFaultData.sLevelData[MMU_LEVEL_1].ui64Address;
+
+       if (eError == PVRSRV_OK)
+       {
+               IMG_BOOL bValidPage = (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS)) ?
+                                      BITMASK_HAS(ui64RawPTE, RGXMIPSFW_TLB_VALID) :
+                                      BITMASK_HAS(ui64RawPTE, RGX_MMUCTRL_PT_DATA_VALID_EN);
+               if (!bValidPage)
+               {
+                       /* don't report invalid pages */
+                       eError = PVRSRV_ERROR_DEVICEMEM_NO_MAPPING;
+               }
+               else
+               {
+                       sDevPA.uiAddr = ui32PageOffset + ((RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS)) ?
+                                       RGXMIPSFW_TLB_GET_PA(ui64RawPTE) :
+                                       (ui64RawPTE & ~RGX_MMUCTRL_PT_DATA_PAGE_CLRMSK));
+
+                       /* Only the Host's Firmware heap is present in the Host's CPU IPA space */
+                       if (ui32OSID == RGXFW_HOST_OS)
+                       {
+                               PhysHeapDevPAddrToCpuPAddr(psPhysHeap, 1, &sCpuPA, &sDevPA);
+                       }
+                       else
+                       {
+                               sCpuPA.uiAddr = 0U;
+                       }
+               }
+       }
+
+       if (psCpuPA != NULL)
+       {
+               *psCpuPA = sCpuPA;
+       }
+
+       if (psDevPA != NULL)
+       {
+               *psDevPA = sDevPA;
+       }
+
+       if (pui64RawPTE != NULL)
+       {
+               *pui64RawPTE = ui64RawPTE;
+       }
+
+ErrorExit:
+       return eError;
+}
 
 /******************************************************************************
  End of file (rgxfwutils.c)
index de339a2..d69f92f 100644 (file)
@@ -63,7 +63,7 @@ static INLINE PVRSRV_ERROR _SelectDevMemHeap(PVRSRV_RGXDEV_INFO *psDevInfo,
                                                                                         PVRSRV_MEMALLOCFLAGS_T *puiFlags,
                                                                                         DEVMEM_HEAP **ppsFwHeap)
 {
-       PVRSRV_PHYS_HEAP ePhysHeap = PVRSRV_GET_PHYS_HEAP_HINT(*puiFlags);
+       PVRSRV_PHYS_HEAP ePhysHeap = (PVRSRV_PHYS_HEAP)PVRSRV_GET_PHYS_HEAP_HINT(*puiFlags);
        PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (ePhysHeap)
@@ -141,9 +141,15 @@ static INLINE PVRSRV_ERROR DevmemFwAllocate(PVRSRV_RGXDEV_INFO *psDevInfo,
                PVR_DPF_RETURN_RC(eError);
        }
 
+#define MIPS_CACHE_LINE_SIZE_IN_BYTES  16
        uiAlign = (psFwHeap == psDevInfo->psFirmwareConfigHeap) ?
                                (RGX_FIRMWARE_CONFIG_HEAP_ALLOC_GRANULARITY) :
-                               (GET_ROGUE_CACHE_LINE_SIZE(RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS)));
+/*
+ * Aligning fw based allocations for MIPS based rogue cores at cache line boundary(16 bytes) instead of SLC(64 bytes)
+ * to have more compact memory with less wastage and hopefully save some tlb misses.
+ */
+                               (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) ? MIPS_CACHE_LINE_SIZE_IN_BYTES
+                               : GET_ROGUE_CACHE_LINE_SIZE(RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS)));
 
        eError = DevmemAllocateAndMap(psFwHeap,
                                uiSize,
@@ -329,17 +335,16 @@ static INLINE IMG_UINT64 RGXReadHWTimerReg(PVRSRV_RGXDEV_INFO *psDevInfo)
                                       PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
                                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
 
-#define RGX_FWSHAREDMEM_ALLOCFLAGS   (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
-                                      PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
-                                      PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
-                                      PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
-                                      PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
-                                      PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
-                                      PVRSRV_MEMALLOCFLAG_UNCACHED | \
-                                      PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
-
-#define RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS  (RGX_FWSHAREDMEM_ALLOCFLAGS | \
-                                                                                  PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
+#define RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                         PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                         PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                         PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
 
 #define RGX_FWSHAREDMEM_CONFIG_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
                                            PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
@@ -351,12 +356,6 @@ static INLINE IMG_UINT64 RGXReadHWTimerReg(PVRSRV_RGXDEV_INFO *psDevInfo)
                                            PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
                                            PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
                                            PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CONFIG))
-/*
- * This FW Init Data is initialised on the CPU and then passed to the FW. We need
- * to make the CPU mapping write-combined to avoid CPU-specific alignment issues
- * for device memory.
- */
-#define RGX_FWINITDATA_WC_ALLOCFLAGS ((RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS & (~PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK)) | PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC)
 
 #define RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
                                            PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
@@ -368,6 +367,13 @@ static INLINE IMG_UINT64 RGXReadHWTimerReg(PVRSRV_RGXDEV_INFO *psDevInfo)
                                            PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
                                            PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
 
+/* Firmware memory that is not accessible by the CPU. */
+#define RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                             PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+
 /* Firmware shared memory that is supposed to be read-only to the CPU.
  * In reality it isn't due to ZERO_ON_ALLOC which enforces CPU_WRITEABLE
  * flag on the allocations. */
@@ -414,7 +420,8 @@ PVRSRV_ERROR RGXSetupFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
                               IMG_UINT32               ui32HWPerfCountersDataSize,
                               IMG_UINT32               *pui32TPUTrilinearFracMask,
                               RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
-                              FW_PERF_CONF             eFirmwarePerf);
+                              FW_PERF_CONF             eFirmwarePerf,
+                              IMG_UINT32               ui32KCCBSizeLog2);
 
 
 
@@ -558,7 +565,7 @@ PVRSRV_ERROR RGXGetFWCommonContextAddrFromServerMMUCtx(PVRSRV_RGXDEV_INFO *psDev
                                                                                                           PRGXFWIF_FWCOMMONCONTEXT *psFWCommonContextFWAddr);
 
 PVRSRV_ERROR FWCommonContextSetFlags(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
-                                                                        IMG_UINT32 ui32ContextFlags);
+                                     IMG_UINT32 ui32ContextFlags);
 /*!
 *******************************************************************************
 @Function       RGXScheduleProcessQueuesKM
@@ -668,7 +675,6 @@ PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
 @Input          psDevInfo          Device Info
 @Input          eDM                To which DM the cmd is sent.
 @Input          psKCCBCmd          The cmd to send.
-@Input          ui32CacheOpFence   Pending cache op. fence value.
 @Input          ui32PDumpFlags     PDump flags
 @Output         pui32CmdKCCBSlot   When non-NULL:
                                    - Pointer on return contains the kCCB slot
@@ -680,11 +686,10 @@ PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
 PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
                                                                                          RGXFWIF_DM         eKCCBType,
                                                                                          RGXFWIF_KCCB_CMD   *psKCCBCmd,
-                                                                                         IMG_UINT32         ui32CacheOpFence,
                                                                                          IMG_UINT32         ui32PDumpFlags,
                                                                                          IMG_UINT32         *pui32CmdKCCBSlot);
-#define RGXScheduleCommand(psDevInfo, eKCCBType, psKCCBCmd, ui32CacheOpFence, ui32PDumpFlags) \
-  RGXScheduleCommandAndGetKCCBSlot(psDevInfo, eKCCBType, psKCCBCmd, ui32CacheOpFence, ui32PDumpFlags, NULL)
+#define RGXScheduleCommand(psDevInfo, eKCCBType, psKCCBCmd, ui32PDumpFlags) \
+  RGXScheduleCommandAndGetKCCBSlot(psDevInfo, eKCCBType, psKCCBCmd, ui32PDumpFlags, NULL)
 
 /*************************************************************************/ /*!
 @Function       RGXWaitForKCCBSlotUpdate
@@ -710,13 +715,15 @@ PVRSRV_ERROR RGXFirmwareUnittests(PVRSRV_RGXDEV_INFO *psDevInfo);
 
 @Description    Copy framework command into FW addressable buffer
 
+@param          psDeviceNode
 @param          psFWFrameworkMemDesc
 @param          pbyGPUFRegisterList
 @param          ui32FrameworkRegisterSize
 
 @Return         PVRSRV_ERROR
 */ /**************************************************************************/
-PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(DEVMEM_MEMDESC      *psFWFrameworkMemDesc,
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                  DEVMEM_MEMDESC       *psFWFrameworkMemDesc,
                                                                                   IMG_PBYTE            pbyGPUFRegisterList,
                                                                                   IMG_UINT32           ui32FrameworkRegisterSize);
 
@@ -955,42 +962,6 @@ PVRSRV_ERROR RGXFWConfigPHR(PVRSRV_RGXDEV_INFO *psDevInfo,
 ******************************************************************************/
 PVRSRV_ERROR RGXFWConfigWdg(PVRSRV_RGXDEV_INFO *psDevInfo,
                             IMG_UINT32 ui32WdgPeriod);
-/*!
-*******************************************************************************
-@Function      RGXReadMETAAddr
-
-@Description    Reads a value at given address in META memory space
-                (it can be either a memory location or a META register)
-
-@Input          psDevInfo       pointer to device info
-@Input          ui32METAAddr    address in META memory space
-
-@Output         pui32Value      value
-
-@Return         PVRSRV_ERROR
-******************************************************************************/
-
-PVRSRV_ERROR RGXReadMETAAddr(PVRSRV_RGXDEV_INFO        *psDevInfo,
-                             IMG_UINT32 ui32METAAddr,
-                             IMG_UINT32 *pui32Value);
-
-/*!
-*******************************************************************************
-@Function      RGXWriteMETAAddr
-
-@Description    Write a value to the given address in META memory space
-                (it can be either a memory location or a META register)
-
-@Input          psDevInfo       pointer to device info
-@Input          ui32METAAddr    address in META memory space
-@Input          ui32Value       Value to write to address in META memory space
-
-@Return         PVRSRV_ERROR
-******************************************************************************/
-
-PVRSRV_ERROR RGXWriteMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo,
-                              IMG_UINT32 ui32METAAddr,
-                              IMG_UINT32 ui32Value);
 
 /*!
 *******************************************************************************
@@ -1180,6 +1151,18 @@ PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo);
 
 /*!
 *******************************************************************************
+@Function       RGXRiscvIsHalted
+
+@Description    Check if the RISC-V FW is halted
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         IMG_BOOL
+******************************************************************************/
+IMG_BOOL RGXRiscvIsHalted(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
 @Function       RGXRiscvResume
 
 @Description    Resume the RISC-V FW core
@@ -1241,42 +1224,61 @@ PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 /*!
 *******************************************************************************
-@Function       RGXRiscvReadMem
+@Function       RGXRiscvPollMem
 
-@Description    Read a value at the given address in RISC-V memory space
+@Description    Poll for a value at the given address in RISC-V memory space
 
 @Input          psDevInfo       Pointer to device info
 @Input          ui32Addr        Address in RISC-V memory space
-
-@Output         pui32Value      Read value
+@Input          ui32Value       Expected value
 
 @Return         PVRSRV_ERROR
 ******************************************************************************/
-PVRSRV_ERROR RGXRiscvReadMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
                              IMG_UINT32 ui32Addr,
-                             IMG_UINT32 *pui32Value);
+                             IMG_UINT32 ui32Value);
 
 /*!
 *******************************************************************************
-@Function       RGXRiscvPollMem
+@Function       RGXRiscvDmiOp
 
-@Description    Poll for a value at the given address in RISC-V memory space
+@Description    Acquire the powerlock and perform an operation on the RISC-V
+                Debug Module Interface, but only if the GPU is powered on.
 
 @Input          psDevInfo       Pointer to device info
-@Input          ui32Addr        Address in RISC-V memory space
-@Input          ui32Value       Expected value
+@InOut          pui64DMI        Encoding of a request for the RISC-V Debug
+                                Module with same format as the 'dmi' register
+                                from the RISC-V debug specification (v0.13+).
+                                On return, this is updated with the result of
+                                the request, encoded the same way.
 
 @Return         PVRSRV_ERROR
 ******************************************************************************/
-PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
-                             IMG_UINT32 ui32Addr,
-                             IMG_UINT32 ui32Value);
+PVRSRV_ERROR RGXRiscvDmiOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                           IMG_UINT64 *pui64DMI);
 
 /*!
 *******************************************************************************
-@Function       RGXRiscvWriteMem
+@Function       RGXReadFWModuleAddr
 
-@Description    Write a value to the given address in RISC-V memory space
+@Description    Read a value at the given address in META or RISCV memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in META or RISCV memory space
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXReadFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                 IMG_UINT32 ui32Addr,
+                                 IMG_UINT32 *pui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXWriteFWModuleAddr
+
+@Description    Write a value to the given address in META or RISC memory space
 
 @Input          psDevInfo       Pointer to device info
 @Input          ui32Addr        Address in RISC-V memory space
@@ -1284,9 +1286,31 @@ PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
 
 @Return         PVRSRV_ERROR
 ******************************************************************************/
-PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
-                              IMG_UINT32 ui32MemAddr,
-                              IMG_UINT32 ui32Value);
+PVRSRV_ERROR RGXWriteFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                  IMG_UINT32 ui32MemAddr,
+                                  IMG_UINT32 ui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXGetFwMapping
+
+@Description    Retrieve any of the CPU Physical Address, Device Physical
+                Address or the raw value of the page table entry associated
+                with the firmware virtual address given.
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32FwVA        The Fw VA that needs decoding
+@Output         psCpuPA         Pointer to the resulting CPU PA
+@Output         psDevPA         Pointer to the resulting Dev PA
+@Output         pui64RawPTE     Pointer to  the raw Page Table Entry value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXGetFwMapping(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                    IMG_UINT32 ui32FwVA,
+                                    IMG_CPU_PHYADDR *psCpuPA,
+                                    IMG_DEV_PHYADDR *psDevPA,
+                                    IMG_UINT64 *pui64RawPTE);
 
 #if defined(SUPPORT_AUTOVZ_HW_REGS) && !defined(SUPPORT_AUTOVZ)
 #error "VZ build configuration error: use of OS scratch registers supported only in AutoVz drivers."
@@ -1314,7 +1338,7 @@ PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
 /* native, static-vz and AutoVz using shared memory */
 #define KM_GET_FW_CONNECTION(psDevInfo)                        (psDevInfo->psRGXFWIfConnectionCtl->eConnectionFwState)
 #define KM_GET_OS_CONNECTION(psDevInfo)                        (psDevInfo->psRGXFWIfConnectionCtl->eConnectionOsState)
-#define KM_SET_OS_CONNECTION(val, psDevInfo)   OSWriteDeviceMem32WithWMB(&psDevInfo->psRGXFWIfConnectionCtl->eConnectionOsState, RGXFW_CONNECTION_OS_##val)
+#define KM_SET_OS_CONNECTION(val, psDevInfo)   OSWriteDeviceMem32WithWMB((void*)&psDevInfo->psRGXFWIfConnectionCtl->eConnectionOsState, RGXFW_CONNECTION_OS_##val)
 #else
 /* dynamic-vz & nohw */
 #define KM_GET_FW_CONNECTION(psDevInfo)                        (RGXFW_CONNECTION_FW_ACTIVE)
index 47138e7..a6e2dd4 100644 (file)
@@ -71,9 +71,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxinit.h"
 
 #include "info_page_defs.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 /* This is defined by default to enable producer callbacks.
  * Clients of the TL interface can disable the use of the callback
@@ -124,52 +121,6 @@ RGXSuspendHWPerfL2DataCopy(PVRSRV_RGXDEV_INFO* psDeviceInfo,
        }
 }
 
-/*************************************************************************/ /*!
-@Function       RGXHWPerfIsInitRequired
-
-@Description    Returns true if the HWperf firmware buffer (L1 buffer) and host
-                driver TL buffer (L2 buffer) are not already allocated. Caller
-                must possess hHWPerfLock lock before calling this
-                function so the state tested is not inconsistent.
-
-@Input          psRgxDevInfo RGX Device Info, on which init requirement is
-                checked.
-
-@Return         IMG_BOOL       Whether initialization (allocation) is required
- */ /**************************************************************************/
-static INLINE IMG_BOOL RGXHWPerfIsInitRequired(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
-{
-       PVR_ASSERT(OSLockIsLocked(psRgxDevInfo->hHWPerfLock));
-
-#if !defined(NO_HARDWARE)
-       /* Both L1 and L2 buffers are required (for HWPerf functioning) on driver
-        * built for actual hardware (TC, EMU, etc.)
-        */
-       if (psRgxDevInfo->hHWPerfStream == (IMG_HANDLE) NULL)
-       {
-               /* The allocation API (RGXHWPerfInitOnDemandResources) allocates
-                * device memory for both L1 and L2 without any checks. Hence,
-                * either both should be allocated or both be NULL.
-                *
-                * In-case this changes in future (for e.g. a situation where one
-                * of the 2 buffers is already allocated and other is required),
-                * add required checks before allocation calls to avoid memory leaks.
-                */
-               PVR_ASSERT(psRgxDevInfo->psRGXFWIfHWPerfBufMemDesc == NULL);
-               return IMG_TRUE;
-       }
-       PVR_ASSERT(psRgxDevInfo->psRGXFWIfHWPerfBufMemDesc != NULL);
-#else
-       /* On a NO-HW driver L2 is not allocated. So, no point in checking its
-        * allocation */
-       if (psRgxDevInfo->psRGXFWIfHWPerfBufMemDesc == NULL)
-       {
-               return IMG_TRUE;
-       }
-#endif
-       return IMG_FALSE;
-}
-
 /******************************************************************************
  * RGX HW Performance Profiling Server API(s)
  *****************************************************************************/
@@ -191,7 +142,14 @@ static IMG_BOOL RGXServerFeatureFlagsToHWPerfFlagsAddBlock(
                number of blocks and counters) but PVRScopeServices expects the latter (plus the number of blocks and counters). The conversion
                could always be moved to PVRScopeServices, but it's less code this way. */
                psBlock->ui16BlockID            = (ui16BlockID & RGX_CNTBLK_ID_GROUP_MASK) ? (ui16BlockID | RGX_CNTBLK_ID_UNIT_ALL_MASK) : ui16BlockID;
-               psBlock->ui16NumCounters        = ui16NumCounters;
+               if ((ui16BlockID & RGX_CNTBLK_ID_DA_MASK) == RGX_CNTBLK_ID_DA_MASK)
+               {
+                       psBlock->ui16NumCounters        = RGX_CNTBLK_COUNTERS_MAX;
+               }
+               else
+               {
+                       psBlock->ui16NumCounters        = ui16NumCounters;
+               }
                psBlock->ui16NumBlocks          = ui16NumBlocks;
 
                *pui16Count = ui16Count + 1;
@@ -222,26 +180,34 @@ PVRSRV_ERROR RGXServerFeatureFlagsToHWPerfFlags(PVRSRV_RGXDEV_INFO *psDevInfo, R
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_PERFBUS_FLAG;
        }
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_S7_TOP_INFRASTRUCTURE_FLAG;
        }
+#endif
+#if defined(RGX_FEATURE_XT_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, XT_TOP_INFRASTRUCTURE))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_XT_TOP_INFRASTRUCTURE_FLAG;
        }
+#endif
+#if defined(RGX_FEATURE_PERF_COUNTER_BATCH_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, PERF_COUNTER_BATCH))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_PERF_COUNTER_BATCH_FLAG;
        }
+#endif
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ROGUEXE))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_ROGUEXE_FLAG;
        }
+#if defined(RGX_FEATURE_DUST_POWER_ISLAND_S7_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, DUST_POWER_ISLAND_S7))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_DUST_POWER_ISLAND_S7_FLAG;
        }
+#endif
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, PBE2_IN_XE))
        {
                psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_PBE2_IN_XE_FLAG;
@@ -293,21 +259,18 @@ PVRSRV_ERROR RGXServerFeatureFlagsToHWPerfFlags(PVRSRV_RGXDEV_INFO *psDevInfo, R
 }
 
 /*
-       PVRSRVRGXEnableHWPerfCountersKM
+       PVRSRVRGXConfigMuxHWPerfCountersKM
  */
-PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
-               CONNECTION_DATA          psConnection,
-               PVRSRV_DEVICE_NODE       psDeviceNode,
-               IMG_UINT32                 ui32ArrayLen,
-               RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs)
+PVRSRV_ERROR PVRSRVRGXConfigMuxHWPerfCountersKM(
+               CONNECTION_DATA               *psConnection,
+               PVRSRV_DEVICE_NODE            *psDeviceNode,
+               IMG_UINT32                     ui32ArrayLen,
+               RGX_HWPERF_CONFIG_MUX_CNTBLK  *psBlockConfigs)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_ERROR            eError = PVRSRV_OK;
        RGXFWIF_KCCB_CMD        sKccbCmd;
        DEVMEM_MEMDESC*         psFwBlkConfigsMemDesc;
-       RGX_HWPERF_CONFIG_CNTBLK* psFwArray;
+       RGX_HWPERF_CONFIG_MUX_CNTBLK* psFwArray;
        IMG_UINT32                      ui32kCCBCommandSlot;
        PVRSRV_RGXDEV_INFO      *psDevice;
 
@@ -317,7 +280,7 @@ PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
 
        PVR_LOG_RETURN_IF_FALSE(ui32ArrayLen > 0, "ui32ArrayLen is 0",
                          PVRSRV_ERROR_INVALID_PARAMS);
@@ -331,15 +294,16 @@ PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
        sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS;
        sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.ui32NumBlocks = ui32ArrayLen;
 
+       /* used for passing counters config to the Firmware, write-only for the CPU */
        eError = DevmemFwAllocate(psDevice,
-                                 sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+                                 sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK)*ui32ArrayLen,
                                  PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
                                  PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                                  PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                                 PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                 PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
                                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-                                 PVRSRV_MEMALLOCFLAG_UNCACHED |
-                                 PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                                  PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
                                  "FwHWPerfCountersConfigBlock",
                                  &psFwBlkConfigsMemDesc);
@@ -352,25 +316,24 @@ PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
        eError = DevmemAcquireCpuVirtAddr(psFwBlkConfigsMemDesc, (void **)&psFwArray);
        PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail2);
 
-       OSDeviceMemCopy(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
+       OSCachedMemCopyWMB(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK)*ui32ArrayLen);
        DevmemPDumpLoadMem(psFwBlkConfigsMemDesc,
                           0,
-                          sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+                          sizeof(RGX_HWPERF_CONFIG_MUX_CNTBLK)*ui32ArrayLen,
                           PDUMP_FLAGS_CONTINUOUS);
 
-       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM parameters set, calling FW"));*/
+       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigMuxHWPerfCountersKM parameters set, calling FW"));*/
 
        /* Ask the FW to carry out the HWPerf configuration command
         */
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
                                                  RGXFWIF_DM_GP,
                                                                                          &sKccbCmd,
-                                                                                         0,
                                                                                          PDUMP_FLAGS_CONTINUOUS,
                                                                                          &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", fail2);
 
-       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM command scheduled for FW"));*/
+       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigMuxHWPerfCountersKM command scheduled for FW"));*/
 
        /* Wait for FW to complete */
        eError = RGXWaitForKCCBSlotUpdate(psDevice, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
@@ -379,34 +342,16 @@ PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
        /* Release temporary memory used for block configuration
         */
        RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFwBlkConfigsMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFwArray - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
        DevmemFwUnmapAndFree(psDevice, psFwBlkConfigsMemDesc);
 
-       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigEnableHWPerfCountersKM firmware completed"));*/
+       /*PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVRGXConfigMuxHWPerfCountersKM firmware completed"));*/
 
        PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks configured and ENABLED", ui32ArrayLen));
 
        PVR_DPF_RETURN_OK;
 
 fail3:
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFwBlkConfigsMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFwArray - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
 fail2:
        RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
@@ -427,9 +372,6 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
                IMG_UINT16                    ui16NumCustomCounters,
                IMG_UINT32                  * pui32CustomCounterIDs)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        PVRSRV_ERROR            eError = PVRSRV_OK;
        RGXFWIF_KCCB_CMD        sKccbCmd;
        DEVMEM_MEMDESC*         psFwSelectCntrsMemDesc = NULL;
@@ -439,7 +381,7 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
 
        PVR_DPF_ENTERED;
 
@@ -456,15 +398,16 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
        {
                PVR_ASSERT(pui32CustomCounterIDs);
 
+               /* used for passing counters config to the Firmware, write-only for the CPU */
                eError = DevmemFwAllocate(psDevice,
                                          sizeof(IMG_UINT32) * ui16NumCustomCounters,
                                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
                                          PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                                          PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                                         PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                         PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                         PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                         PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
                                          PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-                                         PVRSRV_MEMALLOCFLAG_UNCACHED |
-                                         PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                                          PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
                                          "FwHWPerfConfigCustomCounters",
                                          &psFwSelectCntrsMemDesc);
@@ -477,7 +420,7 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
                eError = DevmemAcquireCpuVirtAddr(psFwSelectCntrsMemDesc, (void **)&psFwArray);
                PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail2);
 
-               OSDeviceMemCopy(psFwArray, pui32CustomCounterIDs, sizeof(IMG_UINT32) * ui16NumCustomCounters);
+               OSCachedMemCopyWMB(psFwArray, pui32CustomCounterIDs, sizeof(IMG_UINT32) * ui16NumCustomCounters);
                DevmemPDumpLoadMem(psFwSelectCntrsMemDesc,
                                   0,
                                   sizeof(IMG_UINT32) * ui16NumCustomCounters,
@@ -488,7 +431,6 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
        eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
                                                  RGXFWIF_DM_GP,
                                                                                          &sKccbCmd,
-                                                                                         0,
                                                                                          PDUMP_FLAGS_CONTINUOUS,
                                                                                          &ui32kCCBCommandSlot);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", fail3);
@@ -505,15 +447,6 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
        {
                /* Release temporary memory used for block configuration */
                RGXUnsetFirmwareAddress(psFwSelectCntrsMemDesc);
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFwSelectCntrsMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFwArray - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psFwSelectCntrsMemDesc);
                DevmemFwUnmapAndFree(psDevice, psFwSelectCntrsMemDesc);
        }
@@ -525,15 +458,6 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
 fail3:
        if (psFwSelectCntrsMemDesc)
        {
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFwSelectCntrsMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFwArray - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psFwSelectCntrsMemDesc);
        }
 fail2:
@@ -550,6 +474,105 @@ fail1:
        PVR_DPF_RETURN_RC(eError);
 }
 
+/*
+       PVRSRVRGXConfigureHWPerfBlocksKM
+ */
+PVRSRV_ERROR PVRSRVRGXConfigureHWPerfBlocksKM(
+               CONNECTION_DATA          * psConnection,
+               PVRSRV_DEVICE_NODE       * psDeviceNode,
+               IMG_UINT32                 ui32CtrlWord,
+               IMG_UINT32                 ui32ArrayLen,
+               RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs)
+{
+       PVRSRV_ERROR             eError = PVRSRV_OK;
+       RGXFWIF_KCCB_CMD         sKccbCmd;
+       DEVMEM_MEMDESC           *psFwBlkConfigsMemDesc;
+       RGX_HWPERF_CONFIG_CNTBLK *psFwArray;
+       IMG_UINT32               ui32kCCBCommandSlot;
+       PVRSRV_RGXDEV_INFO       *psDevice;
+
+       PVR_LOG_RETURN_IF_FALSE(psDeviceNode != NULL, "psDeviceNode is NULL",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+
+       psDevice = psDeviceNode->pvDevice;
+
+       PVR_UNREFERENCED_PARAMETER(ui32CtrlWord);
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       PVR_LOG_RETURN_IF_FALSE(ui32ArrayLen > 0, "ui32ArrayLen is 0",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+       PVR_LOG_RETURN_IF_FALSE(psBlockConfigs != NULL, "psBlockConfigs is NULL",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+
+       PVR_DPF_ENTERED;
+
+       /* Fill in the command structure with the parameters needed */
+       sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_BLKS;
+       sKccbCmd.uCmdData.sHWPerfCfgDABlks.ui32NumBlocks = ui32ArrayLen;
+
+       /* used for passing counters config to the Firmware, write-only for the CPU */
+       eError = DevmemFwAllocate(psDevice,
+                                 sizeof(RGX_HWPERF_CONFIG_CNTBLK) * ui32ArrayLen,
+                                 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                 PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                 PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                 "FwHWPerfCountersDAConfigBlock",
+                                 &psFwBlkConfigsMemDesc);
+       PVR_LOG_RETURN_IF_ERROR(eError, "DevmemFwAllocate");
+
+       eError = RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfCfgDABlks.sBlockConfigs,
+                                 psFwBlkConfigsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", fail1);
+
+       eError = DevmemAcquireCpuVirtAddr(psFwBlkConfigsMemDesc, (void **)&psFwArray);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevMemAcquireCpuVirtAddr", fail2);
+
+       OSCachedMemCopyWMB(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
+       DevmemPDumpLoadMem(psFwBlkConfigsMemDesc,
+                          0,
+                          sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+                          PDUMP_FLAGS_CONTINUOUS);
+
+       /* Ask the FW to carry out the HWPerf configuration command. */
+       eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
+                                                 RGXFWIF_DM_GP,
+                                                 &sKccbCmd,
+                                                 PDUMP_FLAGS_CONTINUOUS,
+                                                 &ui32kCCBCommandSlot);
+
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", fail2);
+
+       /* Wait for FW to complete */
+       eError = RGXWaitForKCCBSlotUpdate(psDevice, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate", fail3);
+
+       /* Release temporary memory used for block configuration. */
+       RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+       DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+       DevmemFwUnmapAndFree(psDevice, psFwBlkConfigsMemDesc);
+
+       PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks configured and ENABLED",
+                ui32ArrayLen));
+
+       PVR_DPF_RETURN_OK;
+
+fail3:
+       DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+
+fail2:
+       RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+
+fail1:
+       DevmemFwUnmapAndFree(psDevice, psFwBlkConfigsMemDesc);
+
+       PVR_DPF_RETURN_RC (eError);
+}
+
 /******************************************************************************
  * Currently only implemented on Linux. Feature can be enabled to provide
  * an interface to 3rd-party kernel modules that wish to access the
@@ -580,10 +603,10 @@ typedef struct
 
 } RGX_KM_HWPERF_DEVDATA;
 
-PVRSRV_ERROR RGXHWPerfConfigureAndEnableCounters(
-               RGX_HWPERF_CONNECTION *psHWPerfConnection,
-               IMG_UINT32                                      ui32NumBlocks,
-               RGX_HWPERF_CONFIG_CNTBLK*       asBlockConfigs)
+PVRSRV_ERROR RGXHWPerfConfigMuxCounters(
+               RGX_HWPERF_CONNECTION           *psHWPerfConnection,
+               IMG_UINT32                                           ui32NumBlocks,
+               RGX_HWPERF_CONFIG_MUX_CNTBLK    *asBlockConfigs)
 {
        PVRSRV_ERROR           eError = PVRSRV_OK;
        RGX_KM_HWPERF_DEVDATA* psDevData;
@@ -609,8 +632,10 @@ PVRSRV_ERROR RGXHWPerfConfigureAndEnableCounters(
                psDevData = (RGX_KM_HWPERF_DEVDATA *) psHWPerfDev->hDevData;
 
                /* Call the internal server API */
-               eError = PVRSRVRGXConfigEnableHWPerfCountersKM(NULL,
-                                                              psDevData->psRgxDevNode, ui32NumBlocks, asBlockConfigs);
+               eError = PVRSRVRGXConfigMuxHWPerfCountersKM(NULL,
+                                                           psDevData->psRgxDevNode,
+                                                           ui32NumBlocks,
+                                                           asBlockConfigs);
                PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM");
 
                psHWPerfDev = psHWPerfDev->psNext;
index 7f4df72..8819fe4 100644 (file)
@@ -50,11 +50,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * RGX HW Performance Profiling API(s) Rogue specific
  *****************************************************************************/
 
-PVRSRV_ERROR PVRSRVRGXConfigEnableHWPerfCountersKM(
-       CONNECTION_DATA    psConnection,
-       PVRSRV_DEVICE_NODE psDeviceNode,
-       IMG_UINT32         ui32ArrayLen,
-       RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs);
+PVRSRV_ERROR PVRSRVRGXConfigMuxHWPerfCountersKM(
+       CONNECTION_DATA               *psConnection,
+       PVRSRV_DEVICE_NODE            *psDeviceNode,
+       IMG_UINT32                     ui32ArrayLen,
+       RGX_HWPERF_CONFIG_MUX_CNTBLK  *psBlockConfigs);
 
 
 PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
@@ -64,5 +64,11 @@ PVRSRV_ERROR PVRSRVRGXConfigCustomCountersKM(
        IMG_UINT16           ui16NumCustomCounters,
        IMG_UINT32         * pui32CustomCounterIDs);
 
+PVRSRV_ERROR PVRSRVRGXConfigureHWPerfBlocksKM(
+       CONNECTION_DATA       * psConnection,
+       PVRSRV_DEVICE_NODE    * psDeviceNode,
+       IMG_UINT32            ui32CtrlWord,
+       IMG_UINT32            ui32ArrayLen,
+       RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs);
 
 #endif /* RGXHWPERF_H_ */
index 13bcd18..ca92eff 100644 (file)
@@ -51,6 +51,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvr_notifier.h"
 #include "pvrsrv.h"
 #include "pvrsrv_bridge_init.h"
+#include "rgx_bridge_init.h"
 #include "syscommon.h"
 #include "rgx_heaps.h"
 #include "rgxheapconfig.h"
@@ -102,10 +103,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxtimecorr.h"
 #include "rgxshader.h"
 
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
-
 #include "rgx_bvnc_defs_km.h"
 #if defined(PDUMP)
 #include "rgxstartstop.h"
@@ -122,6 +119,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "rgxpdvfs.h"
 #endif
 
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+#include "rgxsoctimer.h"
+#endif
+
 #if defined(PDUMP) && defined(SUPPORT_SECURITY_VALIDATION)
 #include "pdump_physmem.h"
 #endif
@@ -131,24 +132,13 @@ static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_CH
 static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_PUINT32 pui32RGXClockSpeed);
 static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64ResetValue1, IMG_UINT64 ui64ResetValue2);
 static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode);
+static void DevPart2DeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 #if (RGX_NUM_OS_SUPPORTED > 1)
 static PVRSRV_ERROR RGXInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap, IMG_UINT32 ui32OSid);
 static void RGXDeInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap);
 #endif
 
-#if defined(SUPPORT_AUTOVZ)
-#define RGX_FW_MMU_RESERVED_MEM_SETUP(devnode) (MMU_PX_SETUP) {                                                        \
-                                                                                                       LMA_PhyContigPagesAlloc,                                \
-                                                                                                       LMA_PhyContigPagesFree,                                 \
-                                                                                                       LMA_PhyContigPagesMap,                                  \
-                                                                                                       LMA_PhyContigPagesUnmap,                                \
-                                                                                                       LMA_PhyContigPagesClean,                                \
-                                                                                                       OSGetPageShift(),                                               \
-                                                                                                       (devnode)->psFwMMUReservedMemArena              \
-                                                                                               }
-#endif
-
 /* Services internal heap identification used in this file only */
 #define RGX_FIRMWARE_MAIN_HEAP_IDENT   "FwMain"   /*!< RGX Main Firmware Heap identifier */
 #define RGX_FIRMWARE_CONFIG_HEAP_IDENT "FwConfig" /*!< RGX Config firmware Heap identifier */
@@ -167,47 +157,6 @@ static void RGXDeInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap);
 static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
 
 #if !defined(NO_HARDWARE)
-#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
-#define RGX_LISR_INIT                                                  (0U)
-#define RGX_LISR_DEVICE_NOT_POWERED                            (1U)
-#define RGX_LISR_NOT_TRIGGERED_BY_HW                   (2U)
-#define RGX_LISR_FW_IRQ_COUNTER_NOT_UPDATED            (3U)
-#define RGX_LISR_PROCESSED                                             (4U)
-
-typedef IMG_UINT32 LISR_STATUS;
-
-typedef struct _LISR_EXECUTION_INFO_
-{
-       /* status of last LISR invocation */
-       LISR_STATUS ui32Status;
-
-       /* snapshot from the last LISR invocation */
-#if defined(RGX_FW_IRQ_OS_COUNTERS)
-       IMG_UINT32 aui32InterruptCountSnapshot[RGX_NUM_OS_SUPPORTED];
-#else
-       IMG_UINT32 aui32InterruptCountSnapshot[RGXFW_THREAD_NUM];
-#endif
-
-       /* time of the last LISR invocation */
-       IMG_UINT64 ui64Clockns;
-} LISR_EXECUTION_INFO;
-
-/* information about the last execution of the LISR */
-static LISR_EXECUTION_INFO g_sLISRExecutionInfo;
-
-#define UPDATE_LISR_DBG_STATUS(status)         g_sLISRExecutionInfo.ui32Status = (status)
-#define UPDATE_LISR_DBG_SNAPSHOT(idx, val)     g_sLISRExecutionInfo.aui32InterruptCountSnapshot[idx] = (val)
-#define UPDATE_LISR_DBG_TIMESTAMP()                    g_sLISRExecutionInfo.ui64Clockns = OSClockns64()
-#define UPDATE_LISR_DBG_COUNTER()                      psDeviceNode->ui64nLISR++
-#define UPDATE_MISR_DBG_COUNTER()                      psDeviceNode->ui64nMISR++
-#else
-#define UPDATE_LISR_DBG_STATUS(status)
-#define UPDATE_LISR_DBG_SNAPSHOT(idx, val)
-#define UPDATE_LISR_DBG_TIMESTAMP()
-#define UPDATE_LISR_DBG_COUNTER()
-#define UPDATE_MISR_DBG_COUNTER()
-#endif /* defined(PVRSRV_DEBUG_LISR_EXECUTION) */
-
 /*************************************************************************/ /*!
 @Function       SampleIRQCount
 @Description    Utility function taking snapshots of RGX FW interrupt count.
@@ -272,7 +221,6 @@ static INLINE IMG_UINT32 RGXHostSafetyEvents(PVRSRV_RGXDEV_INFO *psDevInfo)
        else
        {
                IMG_UINT32 ui32SafetyEventStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_SAFETY_EVENT_STATUS__ROGUEXE);
-
                return (ui32SafetyEventStatus & psDevInfo->ui32HostSafetyEventMask);
        }
 }
@@ -396,21 +344,24 @@ static void RGXSafetyEventHandler(PVRSRV_RGXDEV_INFO *psDevInfo)
 static IMG_BOOL _WaitForInterruptsTimeoutCheck(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
        IMG_UINT32 ui32idx;
 #endif
 
        RGXDEBUG_PRINT_IRQ_COUNT(psDevInfo);
 
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
-       PVR_DPF((PVR_DBG_ERROR, "Last RGX_LISRHandler State: 0x%08X Clock: %llu",
-                       g_sLISRExecutionInfo.ui32Status,
-                       g_sLISRExecutionInfo.ui64Clockns));
+       PVR_DPF((PVR_DBG_ERROR,
+               "Last RGX_LISRHandler State (DevID %u): 0x%08X Clock: %llu",
+                        psDeviceNode->sDevId.ui32InternalID,
+                        psDeviceNode->sLISRExecutionInfo.ui32Status,
+                        psDeviceNode->sLISRExecutionInfo.ui64Clockns));
 
        for_each_irq_cnt(ui32idx)
        {
                PVR_DPF((PVR_DBG_ERROR,
                                MSG_IRQ_CNT_TYPE " %u: InterruptCountSnapshot: 0x%X",
-                               ui32idx, g_sLISRExecutionInfo.aui32InterruptCountSnapshot[ui32idx]));
+                               ui32idx, psDeviceNode->sLISRExecutionInfo.aui32InterruptCountSnapshot[ui32idx]));
        }
 #else
        PVR_DPF((PVR_DBG_ERROR, "No further information available. Please enable PVRSRV_DEBUG_LISR_EXECUTION"));
@@ -464,6 +415,7 @@ static inline IMG_BOOL RGXAckHwIrq(PVRSRV_RGXDEV_INFO *psDevInfo,
        }
 }
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static IMG_BOOL RGXAckIrqMETA(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
        return RGXAckHwIrq(psDevInfo,
@@ -472,6 +424,7 @@ static IMG_BOOL RGXAckIrqMETA(PVRSRV_RGXDEV_INFO *psDevInfo)
                                           RGX_CR_META_SP_MSLVIRQSTATUS,
                                           RGX_CR_META_SP_MSLVIRQSTATUS_TRIGVECT2_CLRMSK);
 }
+#endif
 
 static IMG_BOOL RGXAckIrqMIPS(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
@@ -584,9 +537,9 @@ static void RGX_MISR_ProcessKCCBDeferredList(PVRSRV_DEVICE_NODE     *psDeviceNode)
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Failed to acquire PowerLock (device: %p, error: %s)",
-                               __func__, psDeviceNode, PVRSRVGetErrorString(eError)));
-               goto _RGX_MISR_ProcessKCCBDeferredList_PowerLock_failed;
+                                "%s: Failed to acquire PowerLock (device: %p, error: %s)",
+                                __func__, psDeviceNode, PVRSRVGetErrorString(eError)));
+               return;
        }
 
        /* Try to send deferred KCCB commands Do not Poll from here*/
@@ -600,17 +553,13 @@ static void RGX_MISR_ProcessKCCBDeferredList(PVRSRV_DEVICE_NODE   *psDeviceNode)
                                 "%s could not flush Deferred KCCB list, KCCB is full.",
                                 __func__));
        }
-
-_RGX_MISR_ProcessKCCBDeferredList_PowerLock_failed:
-
-       return;
 }
 
 static void RGX_MISRHandler_CheckFWActivePowerState(void *psDevice)
 {
-       PVRSRV_DEVICE_NODE      *psDeviceNode = psDevice;
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevice;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
        PVRSRV_ERROR eError = PVRSRV_OK;
 
        if (psFwSysData->ePowState == RGXFWIF_POW_ON || psFwSysData->ePowState == RGXFWIF_POW_IDLE)
@@ -649,8 +598,8 @@ static void RGX_MISRHandler_CheckFWActivePowerState(void *psDevice)
 #define MAX_ITERATIONS 64
 
 static PVRSRV_ERROR RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode,
-               IMG_HANDLE hGpuUtilUser,
-               RGXFWIF_GPU_UTIL_STATS *psReturnStats)
+                                       IMG_HANDLE hGpuUtilUser,
+                                       RGXFWIF_GPU_UTIL_STATS *psReturnStats)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        volatile RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
@@ -709,7 +658,7 @@ static PVRSRV_ERROR RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode,
                if (i == MAX_ITERATIONS)
                {
                        PVR_DPF((PVR_DBG_WARNING,
-                                       "RGXGetGpuUtilStats could not get reliable data after trying %u times", i));
+                                "RGXGetGpuUtilStats could not get reliable data after trying %u times", i));
                        return PVRSRV_ERROR_TIMEOUT;
                }
 
@@ -717,8 +666,8 @@ static PVRSRV_ERROR RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode,
                /***** (3) Compute return stats *****/
 
                /* Update temp counters to account for the time since the last update to the shared ones */
-               OSMemoryBarrier(); /* Ensure the current time is read after the loop above */
-               ui64TimeNow    = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64());
+               OSMemoryBarrier(NULL); /* Ensure the current time is read after the loop above */
+               ui64TimeNow    = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64(psDeviceNode));
                ui64LastTime   = RGXFWIF_GPU_UTIL_GET_TIME(ui64LastWord);
                ui64LastPeriod = RGXFWIF_GPU_UTIL_GET_PERIOD(ui64TimeNow, ui64LastTime);
                aui64TmpCounters[ui64LastState] += ui64LastPeriod;
@@ -748,11 +697,11 @@ static PVRSRV_ERROR RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode,
                        if (psReturnStats->ui64GpuStatCumulative < ui64MinReturnedStats)
                        {
                                PVR_DPF((PVR_DBG_MESSAGE,
-                                               "%s: Return stats (%" IMG_UINT64_FMTSPEC ") too low "
-                                               "(call period %" IMG_UINT64_FMTSPEC ")",
-                                               __func__, psReturnStats->ui64GpuStatCumulative, ui64TimeSinceLastCall));
+                                        "%s: Return stats (%" IMG_UINT64_FMTSPEC ") too low "
+                                        "(call period %" IMG_UINT64_FMTSPEC ")",
+                                        __func__, psReturnStats->ui64GpuStatCumulative, ui64TimeSinceLastCall));
                                PVR_DPF((PVR_DBG_MESSAGE, "%s: Attempt #%u has failed, trying again",
-                                               __func__, ui32Attempts));
+                                        __func__, ui32Attempts));
                                continue;
                        }
                }
@@ -887,10 +836,6 @@ static void RGX_MISRHandler_Main (void *pvData)
 static PVRSRV_ERROR RGXPDumpBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
                PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-
        PMR *psFWDataPMR;
        RGXMIPSFW_BOOT_DATA *psBootData;
        IMG_DEV_PHYADDR sTmpAddr;
@@ -906,7 +851,7 @@ static PVRSRV_ERROR RGXPDumpBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
         * than the ones we have put in the MIPS bootloader configuration data.
         * We have to tell the pdump player to replace the original values with the real ones.
         */
-       PDUMPCOMMENT("Pass new boot parameters to the FW");
+       PDUMPCOMMENT(psDeviceNode, "Pass new boot parameters to the FW");
 
        /* Rogue Registers physical address */
        ui32ParamOffset = ui32BootConfOffset + offsetof(RGXMIPSFW_BOOT_DATA, ui64RegBase);
@@ -941,16 +886,6 @@ static PVRSRV_ERROR RGXPDumpBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
                return eError;
        }
 
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWDataMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-               printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-               BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psBootData - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
-
        psBootData = IMG_OFFSET_ADDR(psBootData, ui32BootConfOffset);
 
        for (i = 0; i < psBootData->ui32PTNumPages; i++)
@@ -995,7 +930,7 @@ static PVRSRV_ERROR RGXPDumpBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
 #endif /* PDUMP */
 
 static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
-               PVRSRV_DEVICE_CONFIG *psDevConfig)
+                                      PVRSRV_DEVICE_CONFIG *psDevConfig)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
 
@@ -1009,6 +944,7 @@ static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
 #if defined(PDUMP)
        psDevInfo->sLayerParams.ui32PdumpFlags = PDUMP_FLAGS_CONTINUOUS;
 #endif
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX) || defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
            RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
@@ -1049,6 +985,7 @@ static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
                psDevInfo->sLayerParams.sPCAddr = sKernelMMUCtxPCAddr;
        }
        else
+#endif
        {
                PMR *psFWCodePMR = (PMR *)(psDevInfo->psRGXFWCodeMemDesc->psImport->hPMR);
                PMR *psFWDataPMR = (PMR *)(psDevInfo->psRGXFWDataMemDesc->psImport->hPMR);
@@ -1133,12 +1070,19 @@ static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
        {
                PVRSRV_TD_POWER_PARAMS sTDPowerParams;
 
-               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
-                   RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
                {
                        sTDPowerParams.sPCAddr = psDevInfo->sLayerParams.sPCAddr;
                }
-               else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+               {
+                       sTDPowerParams.sPCAddr = psDevInfo->sLayerParams.sPCAddr;
+               }
+#endif
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
                {
                        sTDPowerParams.sGPURegAddr    = psDevInfo->sLayerParams.sGPURegAddr;
                        sTDPowerParams.sBootRemapAddr = psDevInfo->sLayerParams.sBootRemapAddr;
@@ -1147,7 +1091,7 @@ static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
                }
 
                eError = psDevConfig->pfnTDSetPowerParams(psDevConfig->hSysData,
-                               &sTDPowerParams);
+                                                                                                 &sTDPowerParams);
        }
        else
        {
@@ -1164,11 +1108,13 @@ static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
 */
 static IMG_BOOL RGXSystemHasFBCDCVersion31(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 #if defined(SUPPORT_VALIDATION)
        IMG_UINT32 ui32FBCDCVersionOverride = 0;
 #endif
 
+#if defined(FIX_HW_ERN_66622_BIT_MASK)
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
        if (RGX_IS_ERN_SUPPORTED(psDevInfo, 66622))
        {
 #if defined(SUPPORT_VALIDATION)
@@ -1178,7 +1124,7 @@ static IMG_BOOL RGXSystemHasFBCDCVersion31(PVRSRV_DEVICE_NODE *psDeviceNode)
 
                OSCreateKMAppHintState(&pvAppHintState);
                ui32AppHintDefault = PVRSRV_APPHINT_FBCDCVERSIONOVERRIDE;
-               OSGetKMAppHintUINT32(pvAppHintState, FBCDCVersionOverride,
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, FBCDCVersionOverride,
                                     &ui32AppHintDefault, &ui32FBCDCVersionOverride);
                OSFreeKMAppHintState(pvAppHintState);
 
@@ -1199,6 +1145,7 @@ static IMG_BOOL RGXSystemHasFBCDCVersion31(PVRSRV_DEVICE_NODE *psDeviceNode)
                }
        }
        else
+#endif
        {
 
 #if defined(SUPPORT_VALIDATION)
@@ -1242,6 +1189,7 @@ static MMU_DEVICEATTRIBS *RGXDevMMUAttributes(PVRSRV_DEVICE_NODE *psDeviceNode,
        {
                psMMUDevAttrs = psDeviceNode->psMMUDevAttrs;
        }
+
        return psMMUDevAttrs;
 }
 
@@ -1250,7 +1198,6 @@ static MMU_DEVICEATTRIBS *RGXDevMMUAttributes(PVRSRV_DEVICE_NODE *psDeviceNode,
  */
 PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE        *psDeviceNode,
                IMG_UINT32                      ui32DeviceFlags,
-               IMG_UINT32                      ui32HWPerfHostBufSizeKB,
                IMG_UINT32                      ui32HWPerfHostFilter,
                RGX_ACTIVEPM_CONF               eActivePMConf)
 {
@@ -1262,6 +1209,8 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
        /* Assume system layer has turned power on by this point, required before powering device */
        psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_ON;
 
+       PDUMPCOMMENT(psDeviceNode, "RGX Initialisation Part 2");
+
 #if defined(PDUMP)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
@@ -1272,8 +1221,6 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
        OSUserModeAccessToPerfCountersEn();
 #endif
 
-       PDUMPCOMMENT("RGX Initialisation Part 2");
-
        /* Initialise Device Flags */
        psDevInfo->ui32DeviceFlags = 0;
        RGXSetDeviceFlags(psDevInfo, ui32DeviceFlags, IMG_TRUE);
@@ -1283,28 +1230,20 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
        psDevInfo->psGpuDVFSTable = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSTable)));
        PVR_LOG_GOTO_IF_NOMEM(psDevInfo->psGpuDVFSTable, eError, ErrorExit);
 
-       /* Initialise HWPerfHost buffer. */
-       if (RGXHWPerfHostInit(psDevInfo, ui32HWPerfHostBufSizeKB) == PVRSRV_OK)
+       if (psDevInfo->ui32HWPerfHostFilter == 0)
        {
-               if (psDevInfo->ui32HWPerfHostFilter == 0)
-               {
-                       RGXHWPerfHostSetEventFilter(psDevInfo, ui32HWPerfHostFilter);
-               }
+               RGXHWPerfHostSetEventFilter(psDevInfo, ui32HWPerfHostFilter);
+       }
 
-               /* If HWPerf enabled allocate all resources for the host side buffer. */
-               if (psDevInfo->ui32HWPerfHostFilter != 0)
+       /* If HWPerf enabled allocate all resources for the host side buffer. */
+       if (psDevInfo->ui32HWPerfHostFilter != 0)
+       {
+               if (RGXHWPerfHostInitOnDemandResources(psDevInfo) != PVRSRV_OK)
                {
-                       if (RGXHWPerfHostInitOnDemandResources(psDevInfo) != PVRSRV_OK)
-                       {
-                               PVR_DPF((PVR_DBG_WARNING, "HWPerfHost buffer on demand"
-                                               " initialisation failed."));
-                       }
+                       PVR_DPF((PVR_DBG_WARNING, "HWPerfHost buffer on demand"
+                               " initialisation failed."));
                }
        }
-       else
-       {
-               PVR_DPF((PVR_DBG_WARNING, "HWPerfHost buffer initialisation failed."));
-       }
 
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
        /* Initialise work estimation lock */
@@ -1355,12 +1294,12 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
                RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
                IMG_BOOL bSysEnableAPM = psRGXData->psRGXTimingInfo->bEnableActivePM;
                IMG_BOOL bEnableAPM = ((eActivePMConf == RGX_ACTIVEPM_DEFAULT) && bSysEnableAPM) ||
-                               (eActivePMConf == RGX_ACTIVEPM_FORCE_ON);
+                                                          (eActivePMConf == RGX_ACTIVEPM_FORCE_ON);
 
                if (bEnableAPM && (!PVRSRV_VZ_MODE_IS(NATIVE)))
                {
                        PVR_DPF((PVR_DBG_WARNING, "%s: Active Power Management disabled in virtualization mode", __func__));
-                       bEnableAPM = (IMG_BOOL)false;
+                       bEnableAPM = IMG_FALSE;
                }
 
 #if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1) && defined(SUPPORT_AUTOVZ)
@@ -1383,10 +1322,10 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
 #endif
 
        PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableAPM,
-                       RGXQueryAPMState,
-                       RGXSetAPMState,
-                       psDeviceNode,
-                       NULL);
+                                           RGXQueryAPMState,
+                                           RGXSetAPMState,
+                                           psDeviceNode,
+                                           NULL);
 
        RGXTimeCorrInitAppHintCallbacks(psDeviceNode);
 
@@ -1414,7 +1353,7 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
 
                OSCreateKMAppHintState(&pvAppHintState);
                ui32AppHintDefault = PVRSRV_APPHINT_TESTSLRINTERVAL;
-               OSGetKMAppHintUINT32(pvAppHintState, TestSLRInterval,
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, TestSLRInterval,
                                     &ui32AppHintDefault, &psDevInfo->ui32TestSLRInterval);
                PVR_LOG(("OSGetKMAppHintUINT32(TestSLRInterval) ui32AppHintDefault=%d, psDevInfo->ui32TestSLRInterval=%d",
                        ui32AppHintDefault, psDevInfo->ui32TestSLRInterval));
@@ -1423,7 +1362,7 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
                psDevInfo->ui32SLRSkipFWAddr = 0;
 
                ui32AppHintDefault = 0;
-               OSGetKMAppHintUINT32(pvAppHintState, ECCRAMErrInj, &ui32AppHintDefault, &psDevInfo->ui32ECCRAMErrInjModule);
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, ECCRAMErrInj, &ui32AppHintDefault, &psDevInfo->ui32ECCRAMErrInjModule);
                psDevInfo->ui32ECCRAMErrInjInterval = RGXKM_ECC_ERR_INJ_INTERVAL;
 
 #if defined(PDUMP) && defined(SUPPORT_VALIDATION)
@@ -1431,8 +1370,8 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
                if (psDevInfo->ui32ECCRAMErrInjModule != RGXKM_ECC_ERR_INJ_DISABLE &&
                        psDevInfo->ui32ECCRAMErrInjModule != RGXKM_ECC_ERR_INJ_MARS)
                {
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "Verify ECC fault event");
-                       eError = PDUMPREGPOL(RGX_PDUMPREG_NAME,
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_DEINIT, "Verify ECC fault event");
+                       eError = PDUMPREGPOL(psDeviceNode, RGX_PDUMPREG_NAME,
                                                                 RGX_CR_SCRATCH11,
                                                                 1U,
                                                                 0xFFFFFFFF,
@@ -1445,10 +1384,10 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
 
 #if defined(PDUMP)
 #if defined(NO_HARDWARE)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "Wait for the FW to signal idle");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_DEINIT, "Wait for the FW to signal idle");
 
        /* Kick the FW once, in case it still needs to detect and set the idle state */
-       PDUMPREG32(RGX_PDUMPREG_NAME,
+       PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME,
                           RGX_CR_MTS_SCHEDULE,
                           RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK,
                           PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_DEINIT);
@@ -1463,7 +1402,8 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
 #endif
 
        /* Run RGXStop with the correct PDump flags to feed the last-frame deinit buffer */
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_DEINIT, "RGX deinitialisation commands");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_DEINIT,
+                             "RGX deinitialisation commands");
 
        psDevInfo->sLayerParams.ui32PdumpFlags |= PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW;
 
@@ -1480,6 +1420,9 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE   *psDeviceNode,
        eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXInstallProcessQueuesMISR", ErrorExit);
 
+       /* Register RGX to receive notifies when other devices complete some work */
+       PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
+
        /* Register the interrupt handlers */
        eError = OSInstallMISR(&psDevInfo->pvMISRData,
                        RGX_MISRHandler_Main,
@@ -1499,18 +1442,22 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
        else
        {
                /* native and host drivers must clear the unique GPU physical interrupt */
-               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
                {
-                       psDevInfo->pfnRGXAckIrq = RGXAckIrqMETA;
+                       psDevInfo->pfnRGXAckIrq = RGXAckIrqMIPS;
                }
-               else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+               else if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
                {
-                       psDevInfo->pfnRGXAckIrq = RGXAckIrqMIPS;
+                       psDevInfo->pfnRGXAckIrq = RGXAckIrqMETA;
                }
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
                else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
                {
                        psDevInfo->pfnRGXAckIrq = RGXAckIrqDedicated;
                }
+#endif
                else
                {
                        PVR_DPF((PVR_DBG_ERROR, "%s: GPU IRQ clearing mechanism not implemented "
@@ -1554,23 +1501,28 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
                if (!PVRSRVSystemSnoopingOfCPUCache(psDevConfig) &&
                                !PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
                {
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has NO cache snooping");
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "System has NO cache snooping");
                }
                else
                {
                        if (PVRSRVSystemSnoopingOfCPUCache(psDevConfig))
                        {
-                               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has CPU cache snooping");
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                     "System has CPU cache snooping");
                        }
                        if (PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
                        {
-                               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "System has DEVICE cache snooping");
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                     "System has DEVICE cache snooping");
                        }
                }
        }
 #endif
 
+#if defined(RGX_FEATURE_COMPUTE_ONLY_BIT_MASK)
        if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE_ONLY))
+#endif
        {
                eError = PVRSRVTQLoadShaders(psDeviceNode);
                PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVTQLoadShaders", ErrorExit);
@@ -1581,31 +1533,15 @@ PVRSRV_ERROR RGXInitDevPart2(PVRSRV_DEVICE_NODE *psDeviceNode,
        return PVRSRV_OK;
 
 ErrorExit:
-#if !defined(NO_HARDWARE)
-       if (psDevInfo->pvLISRData != NULL)
-       {
-               (void) SysUninstallDeviceLISR(psDevInfo->pvLISRData);
-       }
-       if (psDevInfo->pvMISRData != NULL)
-       {
-               (void) OSUninstallMISR(psDevInfo->pvMISRData);
-       }
-       if (psDevInfo->hProcessQueuesMISR != NULL)
-       {
-               (void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
-       }
-       if (psDevInfo->pvAPMISRData != NULL)
-       {
-               (void) OSUninstallMISR(psDevInfo->pvAPMISRData);
-       }
-#endif /* !defined(NO_HARDWARE) */
+       DevPart2DeInitRGX(psDeviceNode);
 
        return eError;
 }
 
 #define VZ_RGX_FW_FILENAME_SUFFIX ".vz"
+#define RGX_64K_FW_FILENAME_SUFFIX ".64k"
 #define RGX_FW_FILENAME_MAX_SIZE   ((sizeof(RGX_FW_FILENAME)+ \
-                       RGX_BVNC_STR_SIZE_MAX+sizeof(VZ_RGX_FW_FILENAME_SUFFIX)))
+                       RGX_BVNC_STR_SIZE_MAX+sizeof(VZ_RGX_FW_FILENAME_SUFFIX) + sizeof(RGX_64K_FW_FILENAME_SUFFIX)))
 
 static void _GetFWFileName(PVRSRV_DEVICE_NODE *psDeviceNode,
                IMG_CHAR *pszFWFilenameStr,
@@ -1615,19 +1551,24 @@ static void _GetFWFileName(PVRSRV_DEVICE_NODE *psDeviceNode,
        const IMG_CHAR * const pszFWFilenameSuffix =
                        PVRSRV_VZ_MODE_IS(NATIVE) ? "" : VZ_RGX_FW_FILENAME_SUFFIX;
 
+       const IMG_CHAR * const pszFWFilenameSuffix2 =
+                       ((OSGetPageSize() == RGX_MMU_PAGE_SIZE_64KB) &&
+                        RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+                       ? RGX_64K_FW_FILENAME_SUFFIX : "";
+
        OSSNPrintf(pszFWFilenameStr, RGX_FW_FILENAME_MAX_SIZE,
-                       "%s." RGX_BVNC_STR_FMTSPEC "%s",
+                       "%s." RGX_BVNC_STR_FMTSPEC "%s%s",
                        RGX_FW_FILENAME,
                        psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
                        psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C,
-                       pszFWFilenameSuffix);
+                       pszFWFilenameSuffix, pszFWFilenameSuffix2);
 
        OSSNPrintf(pszFWpFilenameStr, RGX_FW_FILENAME_MAX_SIZE,
-                       "%s." RGX_BVNC_STRP_FMTSPEC "%s",
+                       "%s." RGX_BVNC_STRP_FMTSPEC "%s%s",
                        RGX_FW_FILENAME,
                        psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
                        psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C,
-                       pszFWFilenameSuffix);
+                       pszFWFilenameSuffix, pszFWFilenameSuffix2);
 }
 
 PVRSRV_ERROR RGXLoadAndGetFWData(PVRSRV_DEVICE_NODE *psDeviceNode,
@@ -1672,6 +1613,7 @@ PVRSRV_ERROR RGXLoadAndGetFWData(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        return eErr;
+
 }
 
 #if defined(PDUMP)
@@ -1688,16 +1630,16 @@ PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode
        PVRSRV_ERROR       eError;
 
 #if defined(SUPPORT_AUTOVZ)
-       MMU_PX_SETUP sDefaultPxSetup = psDeviceNode->sDevMMUPxSetup;
+       PHYS_HEAP *psDefaultPhysHeap = psDeviceNode->psMMUPhysHeap;
 
        if (PVRSRV_VZ_MODE_IS(HOST) && (!psDeviceNode->bAutoVzFwIsUp))
        {
-               /* Temporarily swap the MMU Px methods and default LMA region of GPU physheap to
-                * allow the page tables of all memory mapped by the FwKernel context to be placed
+               /* Temporarily swap the MMU and default GPU physheap to allow the page
+                * tables of all memory mapped by the FwKernel context to be placed
                 * in a dedicated memory carveout. This should allow the firmware mappings to
                 * persist after a Host kernel crash or driver reset. */
 
-               psDeviceNode->sDevMMUPxSetup = RGX_FW_MMU_RESERVED_MEM_SETUP(psDeviceNode);
+               psDeviceNode->psMMUPhysHeap = psDeviceNode->psFwMMUReservedPhysHeap;
        }
 #endif
 
@@ -1718,7 +1660,7 @@ PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode
        }
 
        eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx, RGX_FIRMWARE_MAIN_HEAP_IDENT,
-                       &psDevInfo->psFirmwareMainHeap);
+                                     &psDevInfo->psFirmwareMainHeap);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1729,7 +1671,7 @@ PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode
        }
 
        eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx, RGX_FIRMWARE_CONFIG_HEAP_IDENT,
-                       &psDevInfo->psFirmwareConfigHeap);
+                                     &psDevInfo->psFirmwareConfigHeap);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1784,7 +1726,7 @@ PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode
 
 #if defined(SUPPORT_AUTOVZ)
                /* restore default Px setup */
-               psDeviceNode->sDevMMUPxSetup = sDefaultPxSetup;
+               psDeviceNode->psMMUPhysHeap = psDefaultPhysHeap;
 #endif
        }
 #else
@@ -1825,9 +1767,9 @@ void RGXDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (PVRSRV_VZ_MODE_IS(HOST))
        {
 #if defined(SUPPORT_AUTOVZ)
-               MMU_PX_SETUP sDefaultPxSetup = psDeviceNode->sDevMMUPxSetup;
+               PHYS_HEAP *psDefaultPhysHeap = psDeviceNode->psMMUPhysHeap;
 
-               psDeviceNode->sDevMMUPxSetup = RGX_FW_MMU_RESERVED_MEM_SETUP(psDeviceNode);
+               psDeviceNode->psMMUPhysHeap = psDeviceNode->psFwMMUReservedPhysHeap;
 
                if (!psDeviceNode->bAutoVzFwIsUp)
 #endif
@@ -1840,7 +1782,7 @@ void RGXDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode)
                        }
                }
 #if defined(SUPPORT_AUTOVZ)
-               psDeviceNode->sDevMMUPxSetup = sDefaultPxSetup;
+               psDeviceNode->psMMUPhysHeap = psDefaultPhysHeap;
 #endif
        }
 #else
@@ -1874,8 +1816,8 @@ void RGXDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode)
 }
 
 static PVRSRV_ERROR RGXAlignmentCheck(PVRSRV_DEVICE_NODE *psDevNode,
-               IMG_UINT32 ui32AlignChecksSizeUM,
-               IMG_UINT32 aui32AlignChecksUM[])
+                                      IMG_UINT32 ui32AlignChecksSizeUM,
+                                      IMG_UINT32 aui32AlignChecksUM[])
 {
        static const IMG_UINT32 aui32AlignChecksKM[] = {RGXFW_ALIGN_CHECKS_INIT_KM};
        IMG_UINT32 ui32UMChecksOffset = ARRAY_SIZE(aui32AlignChecksKM) + 1;
@@ -1889,13 +1831,14 @@ static PVRSRV_ERROR RGXAlignmentCheck(PVRSRV_DEVICE_NODE *psDevNode,
 
        if (psDevInfo->psRGXFWAlignChecksMemDesc == NULL)
        {
-               PVR_DPF((PVR_DBG_ERROR, "%s: FW Alignment Check"
-                               " Mem Descriptor is NULL", __func__));
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: FW Alignment Check Mem Descriptor is NULL",
+                        __func__));
                return PVRSRV_ERROR_ALIGNMENT_ARRAY_NOT_AVAILABLE;
        }
 
        eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc,
-                       (void **) &paui32FWAlignChecks);
+                                         (void **) &paui32FWAlignChecks);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -1944,10 +1887,10 @@ return_:
 
 static
 PVRSRV_ERROR RGXAllocateFWMemoryRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
-               IMG_DEVMEM_SIZE_T ui32Size,
-               PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags,
-               const IMG_PCHAR pszText,
-               DEVMEM_MEMDESC **ppsMemDescPtr)
+                                       IMG_DEVMEM_SIZE_T ui32Size,
+                                       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags,
+                                       const IMG_PCHAR pszText,
+                                       DEVMEM_MEMDESC **ppsMemDescPtr)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_DEVMEM_LOG2ALIGN_T uiLog2Align = OSGetPageShift();
@@ -1965,13 +1908,13 @@ PVRSRV_ERROR RGXAllocateFWMemoryRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
        uiMemAllocFlags = (uiMemAllocFlags |
                                           PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
                                           PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &
-               RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+                          RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
 
 #if defined(SUPPORT_TRUSTED_DEVICE) && !defined(SUPPORT_SECURITY_VALIDATION)
        uiMemAllocFlags &= PVRSRV_MEMALLOCFLAGS_TDFWMASK;
 #endif
 
-       PDUMPCOMMENT("Allocate FW %s memory", pszText);
+       PDUMPCOMMENT(psDeviceNode, "Allocate FW %s memory", pszText);
 
        eError = DevmemFwAllocateExportable(psDeviceNode,
                                                                                ui32Size,
@@ -2075,7 +2018,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(PVRSRV_RGXD
 #endif
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Compatibility check: KM driver and FW DDK version");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW DDK version");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, ui32DDKVersion),
@@ -2141,7 +2085,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(PVRSRV_RGXDEV
 #endif
 
 #if defined(PDUMP) && defined(PVRSRV_STRICT_COMPAT_CHECK)
-       PDUMPCOMMENT("Compatibility check: KM driver and FW DDK build");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW DDK build");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, ui32DDKBuild),
@@ -2211,7 +2156,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INF
 #endif
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (struct version)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (struct version)");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
@@ -2225,7 +2171,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INF
                PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
        }
 
-       PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BVNC part - Lower 32 bits)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (BVNC part - Lower 32 bits)");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
@@ -2239,7 +2186,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INF
                PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
        }
 
-       PDUMPCOMMENT("Compatibility check: KM driver and FW BVNC (BVNC part - Higher 32 bits)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (BVNC part - Higher 32 bits)");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
@@ -2316,13 +2264,14 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
 {
 #if defined(PDUMP) || !defined(NO_HARDWARE)
        IMG_UINT64 ui64MaskBVNC = RGX_BVNC_PACK_MASK_B |
-                       RGX_BVNC_PACK_MASK_V |
-                       RGX_BVNC_PACK_MASK_N |
-                       RGX_BVNC_PACK_MASK_C;
+                                 RGX_BVNC_PACK_MASK_V |
+                                 RGX_BVNC_PACK_MASK_N |
+                                 RGX_BVNC_PACK_MASK_C;
 
        PVRSRV_ERROR                            eError;
        RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sSWBVNC);
 #endif
+
 #if defined(PDUMP)
        PDUMP_FLAGS_T ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
 #endif
@@ -2354,11 +2303,12 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
                                                                        psDevInfo->sDevFeatureCfg.ui32N,
                                                                        psDevInfo->sDevFeatureCfg.ui32C);
 
+#if defined(FIX_HW_BRN_38344_BIT_MASK)
        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 38344) && (psDevInfo->sDevFeatureCfg.ui32C >= 10))
        {
                ui64MaskBVNC &= ~RGX_BVNC_PACK_MASK_C;
        }
-
+#endif
        if (ui64MaskBVNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_V | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C))
        {
                PVR_LOG(("Compatibility checks: Ignoring fields: '%s%s%s%s' of HW BVNC.",
@@ -2370,7 +2320,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
 #endif
 
 #if defined(PDUMP)
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Compatibility check: Layout version of compchecks struct");
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Compatibility check: Layout version of compchecks struct");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
@@ -2385,12 +2336,13 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
                return eError;
        }
 
-       PDUMPCOM(ui32PDumpFlags, "BVNC compatibility check started");
+       PDUMPCOM(psDevInfo->psDeviceNode, ui32PDumpFlags, "BVNC compatibility check started");
        if (ui64MaskBVNC & (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C))
        {
-               PDUMPIF("DISABLE_HWBNC_CHECK", ui32PDumpFlags);
-               PDUMPELSE("DISABLE_HWBNC_CHECK", ui32PDumpFlags);
-               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Compatibility check: HW BNC and FW BNC (Lower 32 bits)");
+               PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+               PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW BNC and FW BNC (Lower 32 bits)");
                eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                                offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                                offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
@@ -2405,7 +2357,8 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
                        return eError;
                }
 
-               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Compatibility check: HW BNC and FW BNC (Higher 32 bits)");
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW BNC and FW BNC (Higher 32 bits)");
                eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                                offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                                offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
@@ -2421,14 +2374,15 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
                        return eError;
                }
 
-               PDUMPFI("DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+               PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
        }
        if (ui64MaskBVNC & RGX_BVNC_PACK_MASK_V)
        {
-               PDUMPIF("DISABLE_HWV_CHECK", ui32PDumpFlags);
-               PDUMPELSE("DISABLE_HWV_CHECK", ui32PDumpFlags);
+               PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
+               PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
 
-               PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Compatibility check: HW V and FW V");
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW V and FW V");
                eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                                        offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
@@ -2443,9 +2397,9 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INF
                        PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
                        return eError;
                }
-               PDUMPFI("DISABLE_HWV_CHECK", ui32PDumpFlags);
+               PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
        }
-       PDUMPCOM(ui32PDumpFlags, "BVNC compatibility check finished");
+       PDUMPCOM(psDevInfo->psDeviceNode, ui32PDumpFlags, "BVNC compatibility check finished");
 #endif
 
 #if !defined(NO_HARDWARE)
@@ -2537,7 +2491,9 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSR
                ui32FWCoreIDValue = RGXMIPSFW_CORE_ID_VALUE;
                pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
        }
-       else if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       else
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
                switch (RGX_GET_FEATURE_VALUE(psDevInfo, META))
                {
@@ -2551,21 +2507,26 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSR
                }
                pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
        }
-       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       else
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
                ui32FWCoreIDValue = RGXRISCVFW_CORE_ID_VALUE;
                pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_RISCV;
        }
        else
+#endif
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Undefined FW_CORE_ID_VALUE", __func__));
                PVR_ASSERT(0);
        }
 
 #if defined(PDUMP)
-       PDUMPIF("DISABLE_HWMETA_CHECK", ui32PDumpFlags);
-       PDUMPELSE("DISABLE_HWMETA_CHECK", ui32PDumpFlags);
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Compatibility check: KM driver and HW FW Processor version");
+       PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+       PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Compatibility check: KM driver and HW FW Processor version");
        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
                        offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
                        offsetof(RGXFWIF_COMPCHECKS, ui32FWProcessorVersion),
@@ -2578,7 +2539,7 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSR
                PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
                return eError;
        }
-       PDUMPFI("DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+       PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
 #endif
 
 #if !defined(NO_HARDWARE)
@@ -2588,10 +2549,10 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSR
        if (psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion != ui32FWCoreIDValue)
        {
                PVR_LOG(("RGXDevInitCompatCheck: Incompatible driver %s version (%d) / HW %s version (%d).",
-                               pcRGXFW_PROCESSOR,
-                               ui32FWCoreIDValue,
-                               pcRGXFW_PROCESSOR,
-                               psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
+                                pcRGXFW_PROCESSOR,
+                                ui32FWCoreIDValue,
+                                pcRGXFW_PROCESSOR,
+                                psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
                eError = PVRSRV_ERROR_FWPROCESSOR_MISMATCH;
                PVR_DBG_BREAK;
                return eError;
@@ -2599,10 +2560,10 @@ static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSR
        else
        {
                PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Compatible driver %s version (%d) / HW %s version (%d) [OK].",
-                               pcRGXFW_PROCESSOR,
-                               ui32FWCoreIDValue,
-                               pcRGXFW_PROCESSOR,
-                               psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
+                                pcRGXFW_PROCESSOR,
+                                ui32FWCoreIDValue,
+                                pcRGXFW_PROCESSOR,
+                                psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
        }
 #endif
        return PVRSRV_OK;
@@ -2644,10 +2605,11 @@ static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
 
        ui32RegValue = 0;
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if ((!PVRSRV_VZ_MODE_IS(GUEST)) &&
-                       RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
-               eError = RGXReadMETAAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
 
                if (eError != PVRSRV_OK)
                {
@@ -2665,6 +2627,7 @@ static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
                        goto chk_exit;
                }
        }
+#endif
 
        if (!*((volatile IMG_BOOL *)&psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated))
        {
@@ -2720,6 +2683,7 @@ static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
                        goto chk_exit;
                }
        }
+
        eError = RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
        if (eError != PVRSRV_OK)
        {
@@ -2758,19 +2722,23 @@ static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        /* the device info */
        psDevInfo = psDeviceNode->pvDevice;
+#if defined(RGX_CR_SOFT_RESET__PBE2_XE__MASKFULL)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, PBE2_IN_XE))
        {
                ui64SoftResetMask = RGX_CR_SOFT_RESET__PBE2_XE__MASKFULL;
        }else
+#endif
        {
                ui64SoftResetMask = RGX_CR_SOFT_RESET_MASKFULL;
        }
 
+#if defined(RGX_CR_SOFT_RESET2_MASKFULL)
        if ((RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE)) &&
                        ((ui64ResetValue2 & RGX_CR_SOFT_RESET2_MASKFULL) != ui64ResetValue2))
        {
                bSoftReset = IMG_TRUE;
        }
+#endif
 
        if (((ui64ResetValue1 & ui64SoftResetMask) != ui64ResetValue1) || bSoftReset)
        {
@@ -2780,32 +2748,39 @@ static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
        /* Set in soft-reset */
        OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue1);
 
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, ui64ResetValue2);
        }
-
+#endif
 
        /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
        (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
        }
+#endif
 
        /* Take the modules out of reset... */
        OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, 0);
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2, 0);
        }
+#endif
 
        /* ...and fence again */
        (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET2);
        }
+#endif
 
        return PVRSRV_OK;
 }
@@ -2839,7 +2814,7 @@ static PVRSRV_ERROR RGXAllocTrampoline(PVRSRV_DEVICE_NODE *psDeviceNode)
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        RGX_MIPS_ADDRESS_TRAMPOLINE *pasTrampoline[TRAMPOLINE_ALLOC_MAX_RETRIES];
 
-       PDUMPCOMMENT("Allocate pages for trampoline");
+       PDUMPCOMMENT(psDeviceNode, "Allocate pages for trampoline");
 
        /* Retry the allocation of the trampoline block (16KB), retaining any
         * previous allocations overlapping  with the target range until we get an
@@ -2922,10 +2897,10 @@ fail:
 
 
 PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
-               IMG_DEVMEM_SIZE_T    uiFWCodeLen,
-               IMG_DEVMEM_SIZE_T    uiFWDataLen,
-               IMG_DEVMEM_SIZE_T    uiFWCorememCodeLen,
-               IMG_DEVMEM_SIZE_T    uiFWCorememDataLen)
+                                  IMG_DEVMEM_SIZE_T    uiFWCodeLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWDataLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememCodeLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememDataLen)
 {
        PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags;
        PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
@@ -2950,14 +2925,14 @@ PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
         * Set up Allocation for FW code section
         */
        uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-                       PVRSRV_MEMALLOCFLAG_GPU_READABLE |
-                       PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                       PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-                       PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
-                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
-                       PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CODE);
+                         PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                         PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                         PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                         PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                         PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                         PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                         PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                         PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CODE);
 
        eError = RGXAllocateFWMemoryRegion(psDeviceNode,
                        uiFWCodeLen,
@@ -2968,18 +2943,18 @@ PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
-                            "Failed to allocate fw code mem (%u)",
-                            eError));
+                        "Failed to allocate fw code mem (%u)",
+                        eError));
                goto failFWCodeMemDescAlloc;
        }
 
        eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
-                       &psDevInfo->sFWCodeDevVAddrBase);
+                                         &psDevInfo->sFWCodeDevVAddrBase);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
-                            "Failed to acquire devVAddr for fw code mem (%u)",
-                            eError));
+                        "Failed to acquire devVAddr for fw code mem (%u)",
+                        eError));
                goto failFWCodeMemDescAqDevVirt;
        }
 
@@ -3049,7 +3024,7 @@ PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
        }
 
        eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
-                       &psDevInfo->sFWDataDevVAddrBase);
+                                         &psDevInfo->sFWDataDevVAddrBase);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -3087,7 +3062,7 @@ PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
                }
 
                eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc,
-                               &psDevInfo->sFWCorememCodeDevVAddrBase);
+                                                 &psDevInfo->sFWCorememCodeDevVAddrBase);
                if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR,
@@ -3097,8 +3072,8 @@ PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
                }
 
                eError = RGXSetFirmwareAddress(&psDevInfo->sFWCorememCodeFWAddr,
-                               psDevInfo->psRGXFWCorememCodeMemDesc,
-                               0, RFW_FWADDR_NOREF_FLAG);
+                                     psDevInfo->psRGXFWCorememCodeMemDesc,
+                                     0, RFW_FWADDR_NOREF_FLAG);
                PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", failFWCorememCodeMemDescFwAddr);
        }
        else
@@ -3212,8 +3187,8 @@ failTrampolineMemDescAlloc:
  */
 static
 PVRSRV_ERROR RGXFWTraceQueryFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_UINT32 *pui32Value)
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
 {
        PVRSRV_ERROR eResult;
 
@@ -3224,8 +3199,8 @@ PVRSRV_ERROR RGXFWTraceQueryFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
 
 static
 PVRSRV_ERROR RGXFWTraceQueryLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_UINT32 *pui32Value)
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
 {
        PVRSRV_ERROR eResult;
 
@@ -3246,8 +3221,8 @@ PVRSRV_ERROR RGXFWTraceQueryLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
 
 static
 PVRSRV_ERROR RGXFWTraceSetFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_UINT32 ui32Value)
+                                 const void *psPrivate,
+                                 IMG_UINT32 ui32Value)
 {
        PVRSRV_ERROR eResult;
        IMG_UINT32 ui32RGXFWLogType;
@@ -3266,8 +3241,8 @@ PVRSRV_ERROR RGXFWTraceSetFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
 
 static
 PVRSRV_ERROR RGXFWTraceSetLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_UINT32 ui32Value)
+                                  const void *psPrivate,
+                                  IMG_UINT32 ui32Value)
 {
        PVRSRV_ERROR eResult;
        IMG_UINT32 ui32RGXFWLogType = ui32Value;
@@ -3301,10 +3276,11 @@ PVRSRV_ERROR RGXFWTraceSetLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
        return eResult;
 }
 
+#if defined(DEBUG)
 static
 PVRSRV_ERROR RGXQueryFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_BOOL *pbValue)
+                                                                       const void *psPrivate,
+                                                                       IMG_BOOL *pbValue)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
 
@@ -3316,8 +3292,8 @@ PVRSRV_ERROR RGXQueryFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
 
 static
 PVRSRV_ERROR RGXSetFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
-               const void *psPrivate,
-               IMG_BOOL bValue)
+                                                                       const void *psPrivate,
+                                                                       IMG_BOOL bValue)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
        psDevInfo->uiFWPoisonOnFreeFlag = bValue
@@ -3326,7 +3302,7 @@ PVRSRV_ERROR RGXSetFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
 
        return PVRSRV_OK;
 }
-
+#endif
 
 /*
  * RGXInitFirmware
@@ -3346,14 +3322,17 @@ RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
                IMG_UINT32               *pui32TPUTrilinearFracMask,
                RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
                FW_PERF_CONF             eFirmwarePerf,
+               IMG_UINT32               ui32KCCBSizeLog2,
                IMG_UINT32               ui32ConfigFlagsExt,
                IMG_UINT32               ui32FwOsCfgFlags)
 {
        PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+#if defined(DEBUG)
        void *pvAppHintState = NULL;
        IMG_UINT32 ui32AppHintDefault;
-       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
        IMG_BOOL bEnableFWPoisonOnFree = IMG_FALSE;
+#endif
 
        eError = RGXSetupFirmware(psDeviceNode,
                        bEnableSignatureChecks,
@@ -3370,7 +3349,8 @@ RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
                        ui32HWPerfCountersDataSize,
                        pui32TPUTrilinearFracMask,
                        eRGXRDPowerIslandingConf,
-                       eFirmwarePerf);
+                       eFirmwarePerf,
+                       ui32KCCBSizeLog2);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -3382,21 +3362,23 @@ RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
        if (!PVRSRV_VZ_MODE_IS(GUEST))
        {
                PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableLogGroup,
-                               RGXFWTraceQueryFilter,
-                               RGXFWTraceSetFilter,
-                               psDeviceNode,
-                               NULL);
+                                                   RGXFWTraceQueryFilter,
+                                                   RGXFWTraceSetFilter,
+                                                   psDeviceNode,
+                                                   NULL);
                PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_FirmwareLogType,
-                               RGXFWTraceQueryLogType,
-                               RGXFWTraceSetLogType,
-                               psDeviceNode,
-                               NULL);
+                                                   RGXFWTraceQueryLogType,
+                                                   RGXFWTraceSetLogType,
+                                                   psDeviceNode,
+                                                   NULL);
        }
 
+#if defined(DEBUG)
        OSCreateKMAppHintState(&pvAppHintState);
 
        ui32AppHintDefault = PVRSRV_APPHINT_ENABLEFWPOISONONFREE;
-       OSGetKMAppHintBOOL(pvAppHintState,
+       OSGetKMAppHintBOOL(psDeviceNode,
+                       pvAppHintState,
                        EnableFWPoisonOnFree,
                        &ui32AppHintDefault,
                        &bEnableFWPoisonOnFree);
@@ -3404,14 +3386,20 @@ RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
        OSFreeKMAppHintState(pvAppHintState);
 
        PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_EnableFWPoisonOnFree,
-                       RGXQueryFWPoisonOnFree,
-                       RGXSetFWPoisonOnFree,
-                       psDeviceNode,
-                       NULL);
+                                          RGXQueryFWPoisonOnFree,
+                                          RGXSetFWPoisonOnFree,
+                                          psDeviceNode,
+                                          NULL);
 
        psDevInfo->uiFWPoisonOnFreeFlag = bEnableFWPoisonOnFree
                        ? PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
                        : 0ULL;
+#else
+       psDevInfo->uiFWPoisonOnFreeFlag = 0ULL;
+#endif
+
+       psDevInfo->ui32ClockSource = PVRSRV_APPHINT_TIMECORRCLOCK;
+       psDevInfo->ui32LastClockSource = PVRSRV_APPHINT_TIMECORRCLOCK;
 
        return PVRSRV_OK;
 
@@ -3422,9 +3410,9 @@ failed_init_firmware:
 
 /* See device.h for function declaration */
 static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
-               DEVMEM_MEMDESC **psMemDesc,
-               IMG_UINT32 *puiSyncPrimVAddr,
-               IMG_UINT32 *puiSyncPrimBlockSize)
+                                                                        DEVMEM_MEMDESC **psMemDesc,
+                                                                        IMG_UINT32 *puiSyncPrimVAddr,
+                                                                        IMG_UINT32 *puiSyncPrimBlockSize)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo;
        PVRSRV_ERROR eError;
@@ -3455,19 +3443,19 @@ static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
        }
 
        eError = DevmemFwAllocateExportable(psDeviceNode,
-                       uiUFOBlockSize,
-                       ui32UFOBlockAlign,
-                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) |
-                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
-                       PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
-                       PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
-                       PVRSRV_MEMALLOCFLAG_GPU_READABLE |
-                       PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                       PVRSRV_MEMALLOCFLAG_CPU_READABLE |
-                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-                       ui32CoherencyFlag,
-                       "FwExUFOBlock",
-                       psMemDesc);
+                                                                               uiUFOBlockSize,
+                                                                               ui32UFOBlockAlign,
+                                                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) |
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                                               ui32CoherencyFlag,
+                                                                               "FwExUFOBlock",
+                                                                               psMemDesc);
        if (eError != PVRSRV_OK)
        {
                goto e0;
@@ -3480,6 +3468,7 @@ static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
        *puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
 
        return PVRSRV_OK;
+
 e1:
        DevmemFwUnmapAndFree(psDevInfo, *psMemDesc);
 e0:
@@ -3488,7 +3477,7 @@ e0:
 
 /* See device.h for function declaration */
 static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
-               DEVMEM_MEMDESC *psMemDesc)
+                                                       DEVMEM_MEMDESC *psMemDesc)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
 
@@ -3502,7 +3491,7 @@ static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
                already.
         */
        if (PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig) &&
-                       psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
+               psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
        {
                RGXFWIF_KCCB_CMD sFlushInvalCmd;
                PVRSRV_ERROR eError;
@@ -3510,7 +3499,8 @@ static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
 
                /* Schedule the SLC flush command ... */
 #if defined(PDUMP)
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Submit SLC flush and invalidate");
 #endif
                sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
                sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
@@ -3551,6 +3541,101 @@ static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
        DevmemFwUnmapAndFree(psDevInfo, psMemDesc);
 }
 
+static void DevPart2DeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+
+       psDevInfo->bDevInit2Done = IMG_FALSE;
+
+#if defined(RGX_FEATURE_COMPUTE_ONLY_BIT_MASK)
+       if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE_ONLY))
+#endif
+       {
+               if ((psDevInfo->hTQUSCSharedMem != NULL) &&
+                   (psDevInfo->hTQCLISharedMem != NULL))
+               {
+                       PVRSRVTQUnloadShaders(psDeviceNode);
+               }
+       }
+
+#if !defined(NO_HARDWARE)
+       if (psDevInfo->pvLISRData != NULL)
+       {
+               (void) SysUninstallDeviceLISR(psDevInfo->pvLISRData);
+       }
+       if (psDevInfo->pvMISRData != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->pvMISRData);
+       }
+       if (psDevInfo->hProcessQueuesMISR != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+       }
+       if (psDevInfo->pvAPMISRData != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->pvAPMISRData);
+       }
+       if (psDeviceNode->hCmdCompNotify != NULL)
+       {
+               /* Cancel notifications to this device */
+               PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
+               psDeviceNode->hCmdCompNotify = NULL;
+       }
+#endif /* !NO_HARDWARE */
+
+       /* Remove the device from the power manager */
+       PVRSRVRemovePowerDevice(psDeviceNode);
+
+       psDevInfo->pfnGetGpuUtilStats = NULL;
+       if (psDevInfo->hGPUUtilLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hGPUUtilLock);
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) &&
+               (psDevInfo->hNMILock != NULL))
+       {
+               OSLockDestroy(psDevInfo->hNMILock);
+       }
+
+       if ((GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED) &&
+               (psDevInfo->hMMUCtxUnregLock != NULL))
+       {
+               OSLockDestroy(psDevInfo->hMMUCtxUnregLock);
+       }
+
+       if (psDevInfo->hDebugFaultInfoLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hDebugFaultInfoLock);
+       }
+
+       /* De-init Freelists/ZBuffers... */
+       if (psDevInfo->hLockFreeList != NULL)
+       {
+               OSLockDestroy(psDevInfo->hLockFreeList);
+       }
+
+       if (psDevInfo->hLockZSBuffer != NULL)
+       {
+               OSLockDestroy(psDevInfo->hLockZSBuffer);
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* De-init work estimation lock */
+       if (psDevInfo->hWorkEstLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hWorkEstLock);
+       }
+#endif
+
+       /* Free DVFS Table */
+       if (psDevInfo->psGpuDVFSTable != NULL)
+       {
+               OSFreeMem(psDevInfo->psGpuDVFSTable);
+               psDevInfo->psGpuDVFSTable = NULL;
+       }
+}
+
 /*
        DevDeInitRGX
  */
@@ -3573,14 +3658,12 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
                KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
        }
 
-       eError = DeviceDepBridgeDeInit(psDevInfo->sDevFeatureCfg.ui64Features);
-       PVR_LOG_IF_ERROR(eError, "DeviceDepBridgeDeInit");
+       DeviceDepBridgeDeInit(psDevInfo);
 
 #if defined(PDUMP)
        DevmemIntFreeDefBackingPage(psDeviceNode,
                                                                &psDeviceNode->sDummyPage,
                                                                DUMMY_PAGE);
-
        DevmemIntFreeDefBackingPage(psDeviceNode,
                                                                &psDeviceNode->sDevZeroPage,
                                                                DEV_ZERO_PAGE);
@@ -3621,12 +3704,12 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
 #if defined(PDUMP)
        if (NULL != psDeviceNode->sDummyPage.hPdumpPg)
        {
-               PDUMPCOMMENT("Error dummy page handle is still active");
+               PDUMPCOMMENT(psDeviceNode, "Error dummy page handle is still active");
        }
 
        if (NULL != psDeviceNode->sDevZeroPage.hPdumpPg)
        {
-               PDUMPCOMMENT("Error Zero page handle is still active");
+               PDUMPCOMMENT(psDeviceNode, "Error Zero page handle is still active");
        }
 #endif
 
@@ -3646,85 +3729,30 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
 
        RGXDebugDeinit(psDevInfo);
 
-
-       /* Cancel notifications to this device */
-       PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
-       psDeviceNode->hCmdCompNotify = NULL;
-
-       /*
-        * De-initialise in reverse order, so stage 2 init is undone first.
-        */
+       /* De-initialise in reverse order, so stage 2 init is undone first. */
        if (psDevInfo->bDevInit2Done)
        {
-               psDevInfo->bDevInit2Done = IMG_FALSE;
-
-               if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE_ONLY))
-               {
-                       eError = PVRSRVTQUnloadShaders(psDeviceNode);
-                       if (eError != PVRSRV_OK)
-                       {
-                               return eError;
-                       }
-               }
-
-#if !defined(NO_HARDWARE)
-               (void) SysUninstallDeviceLISR(psDevInfo->pvLISRData);
-               (void) OSUninstallMISR(psDevInfo->pvMISRData);
-               (void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
-               if (psDevInfo->pvAPMISRData != NULL)
-               {
-                       (void) OSUninstallMISR(psDevInfo->pvAPMISRData);
-               }
-#endif /* !NO_HARDWARE */
-
-               /* Remove the device from the power manager */
-               eError = PVRSRVRemovePowerDevice(psDeviceNode);
-               if (eError != PVRSRV_OK)
-               {
-                       return eError;
-               }
-
-               psDevInfo->pfnGetGpuUtilStats = NULL;
-               OSLockDestroy(psDevInfo->hGPUUtilLock);
-
-               /* Free DVFS Table */
-               if (psDevInfo->psGpuDVFSTable != NULL)
-               {
-                       OSFreeMem(psDevInfo->psGpuDVFSTable);
-                       psDevInfo->psGpuDVFSTable = NULL;
-               }
-
-               /* De-init Freelists/ZBuffers... */
-               OSLockDestroy(psDevInfo->hLockFreeList);
-               OSLockDestroy(psDevInfo->hLockZSBuffer);
+               DevPart2DeInitRGX(psDeviceNode);
+       }
 
-#if defined(SUPPORT_WORKLOAD_ESTIMATION)
-               /* De-init work estimation lock */
-               OSLockDestroy(psDevInfo->hWorkEstLock);
-#endif
+       /* Unregister MMU related stuff */
+       eError = RGXMMUInit_Unregister(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)",
+                        eError));
+       }
 
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       {
                /* Unregister MMU related stuff */
-               eError = RGXMMUInit_Unregister(psDeviceNode);
+               eError = RGXMipsMMUInit_Unregister(psDeviceNode);
                if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR,
-                                "DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)",
+                                "DevDeInitRGX: Failed RGXMipsMMUInit_Unregister (0x%x)",
                                 eError));
-                       return eError;
-               }
-
-
-               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
-               {
-                       /* Unregister MMU related stuff */
-                       eError = RGXMipsMMUInit_Unregister(psDeviceNode);
-                       if (eError != PVRSRV_OK)
-                       {
-                               PVR_DPF((PVR_DBG_ERROR,
-                                        "DevDeInitRGX: Failed RGXMipsMMUInit_Unregister (0x%x)",
-                                        eError));
-                               return eError;
-                       }
                }
        }
 
@@ -3733,7 +3761,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        {
 #if !defined(NO_HARDWARE)
                OSUnMapPhysToLin((void __force *) psDevInfo->pvRegsBaseKM,
-                               psDevInfo->ui32RegSize);
+                                                psDevInfo->ui32RegSize);
 #endif /* !NO_HARDWARE */
                psDevInfo->pvRegsBaseKM = NULL;
        }
@@ -3744,7 +3772,8 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
                eError = OSRemoveTimer(psDevInfo->hTimer);
                if (eError != PVRSRV_OK)
                {
-                       PVR_DPF((PVR_DBG_ERROR, "DevDeInitRGX: Failed to remove timer"));
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "DevDeInitRGX: Failed to remove timer"));
                        return eError;
                }
                psDevInfo->hTimer = NULL;
@@ -3758,7 +3787,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (psDevInfo->psRGXFWCodeMemDesc)
        {
                /* Free fw code */
-               PDUMPCOMMENT("Freeing FW code memory");
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW code memory");
                DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
                DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCodeMemDesc);
                psDevInfo->psRGXFWCodeMemDesc = NULL;
@@ -3774,7 +3803,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
                if (psDevInfo->psTrampoline->sPages.u.pvHandle)
                {
                        /* Free trampoline region */
-                       PDUMPCOMMENT("Freeing trampoline memory");
+                       PDUMPCOMMENT(psDeviceNode, "Freeing trampoline memory");
                        RGXFreeTrampoline(psDeviceNode);
                }
        }
@@ -3782,7 +3811,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (psDevInfo->psRGXFWDataMemDesc)
        {
                /* Free fw data */
-               PDUMPCOMMENT("Freeing FW data memory");
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW data memory");
                DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
                DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWDataMemDesc);
                psDevInfo->psRGXFWDataMemDesc = NULL;
@@ -3795,7 +3824,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (psDevInfo->psRGXFWCorememCodeMemDesc)
        {
                /* Free fw core mem code */
-               PDUMPCOMMENT("Freeing FW coremem code memory");
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW coremem code memory");
                DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
                DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCorememCodeMemDesc);
                psDevInfo->psRGXFWCorememCodeMemDesc = NULL;
@@ -3804,7 +3833,7 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
        {
                /* Free fw core mem data */
-               PDUMPCOMMENT("Freeing FW coremem data store memory");
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW coremem data store memory");
                DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
                DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
                psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
@@ -3814,13 +3843,15 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
           Free the firmware allocations.
         */
        RGXFreeFirmware(psDevInfo);
-       RGXDeInitDestroyFWKernelMemoryContext(psDeviceNode);
 
        /* De-initialise non-device specific (TL) users of RGX device memory */
+       RGXHWPerfDeinit(psDevInfo);
        RGXHWPerfHostDeInit(psDevInfo);
        eError = HTBDeInit();
        PVR_LOG_IF_ERROR(eError, "HTBDeInit");
 
+       RGXDeInitDestroyFWKernelMemoryContext(psDeviceNode);
+
        /* destroy the stalled CCB locks */
        OSLockDestroy(psDevInfo->hCCBRecoveryLock);
        OSLockDestroy(psDevInfo->hCCBStallCheckLock);
@@ -3838,25 +3869,6 @@ PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
        OSSpinLockDestroy(psDevInfo->hLockKCCBDeferredCommandsList);
        OSWRLockDestroy(psDevInfo->hCommonCtxtListLock);
 
-
-       if ((psDevInfo->hNMILock != NULL) && (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS)))
-       {
-               OSLockDestroy(psDevInfo->hNMILock);
-       }
-
-       if (psDevInfo->hDebugFaultInfoLock != NULL)
-       {
-               OSLockDestroy(psDevInfo->hDebugFaultInfoLock);
-       }
-
-       if (GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED)
-       {
-               if (psDevInfo->hMMUCtxUnregLock != NULL)
-               {
-                       OSLockDestroy(psDevInfo->hMMUCtxUnregLock);
-               }
-       }
-
        /* Free device BVNC string */
        if (NULL != psDevInfo->sDevFeatureCfg.pszBVNCString)
        {
@@ -3946,7 +3958,7 @@ static INLINE IMG_UINT32 RGXHeapDerivePageSize(IMG_UINT32 uiLog2PageSize)
 typedef struct RGX_HEAP_INFO_TAG RGX_HEAP_INFO; // Forward declaration
 typedef IMG_BOOL (*PFN_IS_PRESENT)(PVRSRV_RGXDEV_INFO*, const RGX_HEAP_INFO*);
 
-typedef struct RGX_HEAP_INFO_TAG
+struct RGX_HEAP_INFO_TAG
 {
        IMG_CHAR           *pszName;
        IMG_UINT64         ui64HeapBase;
@@ -3955,12 +3967,13 @@ typedef struct RGX_HEAP_INFO_TAG
        IMG_UINT32         ui32Log2ImportAlignment;
        PFN_IS_PRESENT     pfnIsHeapPresent;
        IMG_UINT32         ui32HeapInstanceFlags;
-} RGX_HEAP_INFO;
+};
 
 /* Feature Present function prototypes */
 
 static IMG_BOOL BRN65273IsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
 {
+#if defined(FIX_HW_BRN_65273_BIT_MASK)
        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 65273))
        {
                return (((pksHeapInfo->ui32HeapInstanceFlags & HEAP_INST_VALUE_MASK) == HEAP_INST_BRN_ALT_VALUE) ||
@@ -3968,6 +3981,9 @@ static IMG_BOOL BRN65273IsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_
                        IMG_TRUE : IMG_FALSE;
        }
        else
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+#endif
        {
                return ((pksHeapInfo->ui32HeapInstanceFlags & HEAP_INST_VALUE_MASK) == HEAP_INST_DEFAULT_VALUE) ? IMG_TRUE : IMG_FALSE;
        }
@@ -3977,6 +3993,7 @@ static IMG_BOOL BRN63142IsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_
 {
        PVR_UNREFERENCED_PARAMETER(pksHeapInfo);
 
+#if defined(FIX_HW_BRN_63142_BIT_MASK)
        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 63142))
        {
                PVR_ASSERT((pksHeapInfo->ui64HeapBase & IMG_UINT64_C(0x3FFFFFFFF)) +
@@ -3984,71 +4001,96 @@ static IMG_BOOL BRN63142IsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_
 
                return IMG_TRUE;
        }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+#endif
+
+       return IMG_FALSE;
+}
+
+static IMG_BOOL FBCDescriptorIsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
+{
+       PVR_UNREFERENCED_PARAMETER(pksHeapInfo);
+
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, FBC_MAX_DEFAULT_DESCRIPTORS))
+       {
+               return IMG_TRUE;
+       }
 
        return IMG_FALSE;
 }
 
+static IMG_BOOL FBCLargeDescriptorIsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
+{
+       PVR_UNREFERENCED_PARAMETER(pksHeapInfo);
+
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, FBC_MAX_LARGE_DESCRIPTORS))
+       {
+               return IMG_TRUE;
+       }
+
+       return IMG_FALSE;
+}
+
+static IMG_BOOL TextureStateIsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
+{
+       PVR_UNREFERENCED_PARAMETER(pksHeapInfo);
+#if defined(RGX_FEATURE_BINDLESS_IMAGE_AND_TEXTURE_STATE_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, BINDLESS_IMAGE_AND_TEXTURE_STATE))
+       {
+               return IMG_TRUE;
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+#endif
+       return IMG_FALSE;
+}
+
 static IMG_BOOL SignalSnoopingIsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
 {
        PVR_UNREFERENCED_PARAMETER(pksHeapInfo);
 
+#if defined(RGX_FEATURE_SIGNAL_SNOOPING_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, SIGNAL_SNOOPING))
        {
                return IMG_TRUE;
        }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+#endif
 
        return IMG_FALSE;
 }
 
-/* FW Feature Present function prototypes */
-
 static IMG_BOOL FWBRN65101IsPresent(PVRSRV_RGXDEV_INFO *psDevInfo, const RGX_HEAP_INFO *pksHeapInfo)
 {
        /* Used to determine the correct table row to instantiate as a heap by checking
         * the Heap size and base at run time VS the current table instance
         */
-       IMG_UINT64 ui64FWCPUTypeAndBRN;
-       IMG_UINT64 ui64VZTypeBase;
+       IMG_UINT64 ui64MainSubHeapSize;
 
-       /* Check if the FW CPU is of MIPS type, if not then assume META for now */
-       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       /* MIPS Firmware must reserve some space in its Host/Native heap for GPU memory mappings */
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) && (!PVRSRV_VZ_MODE_IS(GUEST)))
        {
+#if defined(FIX_HW_BRN_65101_BIT_MASK)
                if (RGX_IS_BRN_SUPPORTED(psDevInfo, 65101))
                {
-                       ui64FWCPUTypeAndBRN = RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101;
+                       ui64MainSubHeapSize = RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_BRN65101;
                }
                else
+#endif
                {
-                       ui64FWCPUTypeAndBRN = RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL;
+                       ui64MainSubHeapSize = RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_NORMAL;
                }
        }
        else
        {
-               ui64FWCPUTypeAndBRN = RGX_FIRMWARE_META_MAIN_HEAP_SIZE;
-       }
-
-       /* Check if the FW CPU is RISC-V, if not then we have determined by elimination
-        * that the FW type is META
-        */
-       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
-       {
-               /* We currently use the META config in this case */
-               ui64FWCPUTypeAndBRN = RGX_FIRMWARE_META_MAIN_HEAP_SIZE;
-       }
-
-       /* Check VZ Type */
-       if (PVRSRV_VZ_MODE_IS(GUEST))
-       {
-               ui64VZTypeBase = RGX_FIRMWARE_GUEST_MAIN_HEAP_BASE;
-       }
-       else
-       {
-               ui64VZTypeBase = RGX_FIRMWARE_HOST_MAIN_HEAP_BASE;
+               ui64MainSubHeapSize = RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE;
        }
 
        /* Determine if we should include this entry based upon previous checks */
-       return (pksHeapInfo->uiHeapLength == ui64FWCPUTypeAndBRN &&
-               pksHeapInfo->ui64HeapBase == ui64VZTypeBase) ?
+       return (pksHeapInfo->uiHeapLength == ui64MainSubHeapSize &&
+               pksHeapInfo->ui64HeapBase == RGX_FIRMWARE_MAIN_HEAP_BASE) ?
                IMG_TRUE : IMG_FALSE;
 }
 
@@ -4057,60 +4099,48 @@ static IMG_BOOL FWVZConfigPresent(PVRSRV_RGXDEV_INFO* psDevInfo, const RGX_HEAP_
        /* Used to determine the correct table row to instantiate as a heap by checking
         * the Heap base at run time VS the current table instance
         */
-       IMG_UINT64 ui64VZTypeBase;
-
-       /* Check VZ Type */
-       if (PVRSRV_VZ_MODE_IS(GUEST))
-       {
-               ui64VZTypeBase = RGX_FIRMWARE_GUEST_CONFIG_HEAP_BASE;
-       }
-       else
-       {
-               ui64VZTypeBase = RGX_FIRMWARE_HOST_CONFIG_HEAP_BASE;
-       }
 
        /* Determine if we should include this entry based upon previous checks */
-       return (pksHeapInfo->ui64HeapBase == ui64VZTypeBase) ? IMG_TRUE : IMG_FALSE;
+       return (pksHeapInfo->ui64HeapBase == RGX_FIRMWARE_CONFIG_HEAP_BASE) ? IMG_TRUE : IMG_FALSE;
 }
 
 /* Blueprint array. note: not all heaps are available to clients*/
 
 static const RGX_HEAP_INFO gasRGXHeapLayoutApp[] =
 {
-       /* Name                             HeapBase                                 HeapLength                               HeapReservedRegionLength                     Log2ImportAlignment pfnPresent               HeapInstanceFlags   */
-       {RGX_GENERAL_SVM_HEAP_IDENT,        RGX_GENERAL_SVM_HEAP_BASE,               RGX_GENERAL_SVM_HEAP_SIZE,               0,                                           0,                  NULL,                    HEAP_INST_DEFAULT_VALUE },
-       {RGX_GENERAL_HEAP_IDENT,            RGX_GENERAL_HEAP_BASE,                   RGX_GENERAL_HEAP_SIZE,                   (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE },
-       {RGX_GENERAL_HEAP_IDENT,            RGX_GENERAL_BRN_65273_HEAP_BASE,         RGX_GENERAL_BRN_65273_HEAP_SIZE,         (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE },
-       {RGX_GENERAL_NON4K_HEAP_IDENT,      RGX_GENERAL_NON4K_HEAP_BASE,             RGX_GENERAL_NON4K_HEAP_SIZE,             0,                                           0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE | HEAP_INST_NON4K_FLAG },
-       {RGX_GENERAL_NON4K_HEAP_IDENT,      RGX_GENERAL_NON4K_BRN_65273_HEAP_BASE,   RGX_GENERAL_NON4K_BRN_65273_HEAP_SIZE,   0,                                           0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE | HEAP_INST_NON4K_FLAG },
-       {RGX_PDSCODEDATA_HEAP_IDENT,        RGX_PDSCODEDATA_HEAP_BASE,               RGX_PDSCODEDATA_HEAP_SIZE,               (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE },
-       {RGX_PDSCODEDATA_HEAP_IDENT,        RGX_PDSCODEDATA_BRN_65273_HEAP_BASE,     RGX_PDSCODEDATA_BRN_65273_HEAP_SIZE,     (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE },
-       {RGX_RGNHDR_BRN_63142_HEAP_IDENT,   RGX_RGNHDR_BRN_63142_HEAP_BASE,          RGX_RGNHDR_BRN_63142_HEAP_SIZE,          0,                                           0,                  BRN63142IsPresent,       HEAP_INST_BRN_DEP_VALUE },
-       {RGX_USCCODE_HEAP_IDENT,            RGX_USCCODE_HEAP_BASE,                   RGX_USCCODE_HEAP_SIZE,                   (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE },
-       {RGX_USCCODE_HEAP_IDENT,            RGX_USCCODE_BRN_65273_HEAP_BASE,         RGX_USCCODE_BRN_65273_HEAP_SIZE,         (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE },
-       {RGX_TQ3DPARAMETERS_HEAP_IDENT,     RGX_TQ3DPARAMETERS_HEAP_BASE,            RGX_TQ3DPARAMETERS_HEAP_SIZE,            0,                                           0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE },
-       {RGX_TQ3DPARAMETERS_HEAP_IDENT,     RGX_TQ3DPARAMETERS_BRN_65273_HEAP_BASE,  RGX_TQ3DPARAMETERS_BRN_65273_HEAP_SIZE,  0,                                           0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE },
-       {RGX_VK_CAPT_REPLAY_HEAP_IDENT,     RGX_VK_CAPT_REPLAY_HEAP_BASE,            RGX_VK_CAPT_REPLAY_HEAP_SIZE,            0,                                           0,                  NULL,                    HEAP_INST_DEFAULT_VALUE },
-       {RGX_SIGNALS_HEAP_IDENT,            RGX_SIGNALS_HEAP_BASE,                   RGX_SIGNALS_HEAP_SIZE,                   0,                                           0,                  SignalSnoopingIsPresent, HEAP_INST_FEAT_DEP_VALUE},
-       {RGX_CMP_MISSION_RMW_HEAP_IDENT,    RGX_CMP_MISSION_RMW_HEAP_BASE,           RGX_CMP_MISSION_RMW_HEAP_SIZE,           0,                                           0,                  NULL,                    HEAP_INST_DEFAULT_VALUE },
-       {RGX_CMP_SAFETY_RMW_HEAP_IDENT,     RGX_CMP_SAFETY_RMW_HEAP_BASE,            RGX_CMP_SAFETY_RMW_HEAP_SIZE,            0,                                           0,                  NULL,                    HEAP_INST_DEFAULT_VALUE },
-       {RGX_VISIBILITY_TEST_HEAP_IDENT,    RGX_VISIBILITY_TEST_HEAP_BASE,           RGX_VISIBILITY_TEST_HEAP_SIZE,           0,                                           0,                  BRN65273IsPresent,       HEAP_INST_DEFAULT_VALUE },
-       {RGX_VISIBILITY_TEST_HEAP_IDENT,    RGX_VISIBILITY_TEST_BRN_65273_HEAP_BASE, RGX_VISIBILITY_TEST_BRN_65273_HEAP_SIZE, 0,                                           0,                  BRN65273IsPresent,       HEAP_INST_BRN_ALT_VALUE },
-       {RGX_MMU_INIA_BRN_65273_HEAP_IDENT, RGX_MMU_INIA_BRN_65273_HEAP_BASE,        RGX_MMU_INIA_BRN_65273_HEAP_SIZE,        0,                                           0,                  BRN65273IsPresent,       HEAP_INST_BRN_DEP_VALUE },
-       {RGX_MMU_INIB_BRN_65273_HEAP_IDENT, RGX_MMU_INIB_BRN_65273_HEAP_BASE,        RGX_MMU_INIB_BRN_65273_HEAP_SIZE,        0,                                           0,                  BRN65273IsPresent,       HEAP_INST_BRN_DEP_VALUE }
+       /* Name                             HeapBase                                 HeapLength                               HeapReservedRegionLength                     Log2ImportAlignment pfnPresent                   HeapInstanceFlags   */
+       {RGX_GENERAL_SVM_HEAP_IDENT,        RGX_GENERAL_SVM_HEAP_BASE,               RGX_GENERAL_SVM_HEAP_SIZE,               0,                                           0,                  NULL,                        HEAP_INST_DEFAULT_VALUE },
+       {RGX_GENERAL_HEAP_IDENT,            RGX_GENERAL_HEAP_BASE,                   RGX_GENERAL_HEAP_SIZE,                   (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE },
+       {RGX_GENERAL_HEAP_IDENT,            RGX_GENERAL_BRN_65273_HEAP_BASE,         RGX_GENERAL_BRN_65273_HEAP_SIZE,         (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE },
+       {RGX_GENERAL_NON4K_HEAP_IDENT,      RGX_GENERAL_NON4K_HEAP_BASE,             RGX_GENERAL_NON4K_HEAP_SIZE,             0,                                           0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE | HEAP_INST_NON4K_FLAG },
+       {RGX_GENERAL_NON4K_HEAP_IDENT,      RGX_GENERAL_NON4K_BRN_65273_HEAP_BASE,   RGX_GENERAL_NON4K_BRN_65273_HEAP_SIZE,   0,                                           0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE | HEAP_INST_NON4K_FLAG },
+       {RGX_PDSCODEDATA_HEAP_IDENT,        RGX_PDSCODEDATA_HEAP_BASE,               RGX_PDSCODEDATA_HEAP_SIZE,               (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE },
+       {RGX_PDSCODEDATA_HEAP_IDENT,        RGX_PDSCODEDATA_BRN_65273_HEAP_BASE,     RGX_PDSCODEDATA_BRN_65273_HEAP_SIZE,     (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE },
+       {RGX_RGNHDR_BRN_63142_HEAP_IDENT,   RGX_RGNHDR_BRN_63142_HEAP_BASE,          RGX_RGNHDR_BRN_63142_HEAP_SIZE,          0,                                           0,                  BRN63142IsPresent,           HEAP_INST_BRN_DEP_VALUE },
+       {RGX_USCCODE_HEAP_IDENT,            RGX_USCCODE_HEAP_BASE,                   RGX_USCCODE_HEAP_SIZE,                   (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE },
+       {RGX_USCCODE_HEAP_IDENT,            RGX_USCCODE_BRN_65273_HEAP_BASE,         RGX_USCCODE_BRN_65273_HEAP_SIZE,         (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE },
+       {RGX_TQ3DPARAMETERS_HEAP_IDENT,     RGX_TQ3DPARAMETERS_HEAP_BASE,            RGX_TQ3DPARAMETERS_HEAP_SIZE,            0,                                           0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE },
+       {RGX_TQ3DPARAMETERS_HEAP_IDENT,     RGX_TQ3DPARAMETERS_BRN_65273_HEAP_BASE,  RGX_TQ3DPARAMETERS_BRN_65273_HEAP_SIZE,  0,                                           0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE },
+       {RGX_VK_CAPT_REPLAY_HEAP_IDENT,     RGX_VK_CAPT_REPLAY_HEAP_BASE,            RGX_VK_CAPT_REPLAY_HEAP_SIZE,            0,                                           0,                  NULL,                        HEAP_INST_DEFAULT_VALUE },
+       {RGX_SIGNALS_HEAP_IDENT,            RGX_SIGNALS_HEAP_BASE,                   RGX_SIGNALS_HEAP_SIZE,                   0,                                           0,                  SignalSnoopingIsPresent,     HEAP_INST_FEAT_DEP_VALUE},
+       {RGX_FBCDC_HEAP_IDENT,              RGX_FBCDC_HEAP_BASE,                     RGX_FBCDC_HEAP_SIZE,                     0,                                           0,                  FBCDescriptorIsPresent,      HEAP_INST_FEAT_DEP_VALUE},
+       {RGX_FBCDC_LARGE_HEAP_IDENT,        RGX_FBCDC_LARGE_HEAP_BASE,               RGX_FBCDC_LARGE_HEAP_SIZE,               0,                                           0,                  FBCLargeDescriptorIsPresent, HEAP_INST_FEAT_DEP_VALUE},
+       {RGX_CMP_MISSION_RMW_HEAP_IDENT,    RGX_CMP_MISSION_RMW_HEAP_BASE,           RGX_CMP_MISSION_RMW_HEAP_SIZE,           0,                                           0,                  NULL,                        HEAP_INST_DEFAULT_VALUE },
+       {RGX_CMP_SAFETY_RMW_HEAP_IDENT,     RGX_CMP_SAFETY_RMW_HEAP_BASE,            RGX_CMP_SAFETY_RMW_HEAP_SIZE,            0,                                           0,                  NULL,                        HEAP_INST_DEFAULT_VALUE },
+       {RGX_TEXTURE_STATE_HEAP_IDENT,      RGX_TEXTURE_STATE_HEAP_BASE,             RGX_TEXTURE_STATE_HEAP_SIZE,             0,                                           0,                  TextureStateIsPresent,       HEAP_INST_FEAT_DEP_VALUE},
+       {RGX_VISIBILITY_TEST_HEAP_IDENT,    RGX_VISIBILITY_TEST_HEAP_BASE,           RGX_VISIBILITY_TEST_HEAP_SIZE,           0,                                           0,                  BRN65273IsPresent,           HEAP_INST_DEFAULT_VALUE },
+       {RGX_VISIBILITY_TEST_HEAP_IDENT,    RGX_VISIBILITY_TEST_BRN_65273_HEAP_BASE, RGX_VISIBILITY_TEST_BRN_65273_HEAP_SIZE, 0,                                           0,                  BRN65273IsPresent,           HEAP_INST_BRN_ALT_VALUE },
+       {RGX_MMU_INIA_BRN_65273_HEAP_IDENT, RGX_MMU_INIA_BRN_65273_HEAP_BASE,        RGX_MMU_INIA_BRN_65273_HEAP_SIZE,        0,                                           0,                  BRN65273IsPresent,           HEAP_INST_BRN_DEP_VALUE },
+       {RGX_MMU_INIB_BRN_65273_HEAP_IDENT, RGX_MMU_INIB_BRN_65273_HEAP_BASE,        RGX_MMU_INIB_BRN_65273_HEAP_SIZE,        0,                                           0,                  BRN65273IsPresent,           HEAP_INST_BRN_DEP_VALUE }
 };
 
 static const RGX_HEAP_INFO gasRGXHeapLayoutFW[] =
 {
        /* Name                          HeapBase                             HeapLength                                 HeapReservedRegionLength Log2ImportAlignment pfnIsHeapPresent     HeapInstanceFlags*/
-       {RGX_FIRMWARE_CONFIG_HEAP_IDENT, RGX_FIRMWARE_GUEST_CONFIG_HEAP_BASE, RGX_FIRMWARE_CONFIG_HEAP_SIZE,             0,                       0,                  FWVZConfigPresent,   HEAP_INST_DEFAULT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_GUEST_MAIN_HEAP_BASE,   RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL,   0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_GUEST_MAIN_HEAP_BASE,   RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101, 0,                       0,                  FWBRN65101IsPresent, HEAP_INST_BRN_ALT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_GUEST_MAIN_HEAP_BASE,   RGX_FIRMWARE_META_MAIN_HEAP_SIZE,          0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_HOST_MAIN_HEAP_BASE,    RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL,   0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_HOST_MAIN_HEAP_BASE,    RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101, 0,                       0,                  FWBRN65101IsPresent, HEAP_INST_BRN_ALT_VALUE},
-       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_HOST_MAIN_HEAP_BASE,    RGX_FIRMWARE_META_MAIN_HEAP_SIZE,          0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
-       {RGX_FIRMWARE_CONFIG_HEAP_IDENT, RGX_FIRMWARE_HOST_CONFIG_HEAP_BASE,  RGX_FIRMWARE_CONFIG_HEAP_SIZE,             0,                       0,                  FWVZConfigPresent,   HEAP_INST_DEFAULT_VALUE}
+       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_MAIN_HEAP_BASE,    RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE,            0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
+       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_MAIN_HEAP_BASE,    RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_NORMAL,   0,                       0,                  FWBRN65101IsPresent, HEAP_INST_DEFAULT_VALUE},
+       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_MAIN_HEAP_BASE,    RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_BRN65101, 0,                       0,                  FWBRN65101IsPresent, HEAP_INST_BRN_ALT_VALUE},
+       {RGX_FIRMWARE_CONFIG_HEAP_IDENT, RGX_FIRMWARE_CONFIG_HEAP_BASE,  RGX_FIRMWARE_CONFIG_HEAP_SIZE,                  0,                       0,                  FWVZConfigPresent,   HEAP_INST_DEFAULT_VALUE},
 };
 
 /* Generic counting method. */
@@ -4321,9 +4351,6 @@ static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
 static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
-       IMG_UINT64 uPhysheapSize;
-       IMG_CPU_PHYADDR sCpuPAddr;
-       IMG_DEV_PHYADDR sDevPAddr;
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
        PHYS_HEAP_CONFIG *psFwMainConfig = FindPhysHeapConfig(psDeviceNode->psDevConfig,
                                                                                                                   PHYS_HEAP_USAGE_FW_MAIN);
@@ -4357,53 +4384,34 @@ static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode)
        }
        else /* PHYS_HEAP_TYPE_LMA or PHYS_HEAP_TYPE_DMA */
        {
-               IMG_UINT64 uRawHeapBase;
-               RA_BASE_T uFwCfgSubHeapBase, uFwMainSubHeapBase;
-               const IMG_UINT64 ui64ExpectedHeapSize = RGX_FIRMWARE_RAW_HEAP_SIZE;
-               const RA_LENGTH_T uFwCfgSubHeapSize  = RGX_FIRMWARE_CONFIG_HEAP_SIZE;
-               RA_LENGTH_T uFwMainSubHeapSize;
+               IMG_UINT64 uFwMainSubHeapSize;
                PHYS_HEAP_CONFIG sFwHeapConfig;
 
-               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+               /* MIPS Firmware must reserve some space in its Host/Native heap for GPU memory mappings */
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) && (!PVRSRV_VZ_MODE_IS(GUEST)))
                {
+#if defined(FIX_HW_BRN_65101_BIT_MASK)
                        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 65101))
                        {
-                               uFwMainSubHeapSize = RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_BRN65101;
+                               uFwMainSubHeapSize = RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_BRN65101;
                        }
                        else
+#endif
                        {
-                               uFwMainSubHeapSize = RGX_FIRMWARE_MIPS_MAIN_HEAP_SIZE_NORMAL;
+                               uFwMainSubHeapSize = RGX_FIRMWARE_HOST_MIPS_MAIN_HEAP_SIZE_NORMAL;
                        }
                }
                else
                {
-                       uFwMainSubHeapSize = RGX_FIRMWARE_META_MAIN_HEAP_SIZE;
+                       uFwMainSubHeapSize = RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE;
                }
 
                PVR_DPF((PVR_DBG_MESSAGE, "%s: Firmware physical heap uses local memory managed by the driver (LMA)", __func__));
 
-               sCpuPAddr = psFwMainConfig->sStartAddr;
-               sDevPAddr = psFwMainConfig->sCardBase;
-               uPhysheapSize = psFwMainConfig->uiSize;
-
-               PVR_LOG_GOTO_IF_FALSE(uPhysheapSize >= ui64ExpectedHeapSize,
+               PVR_LOG_GOTO_IF_FALSE(psFwMainConfig->uiSize >= RGX_FIRMWARE_RAW_HEAP_SIZE,
                                                          "Invalid firmware physical heap size.", ErrorDeinit);
 
                /* Now we construct RAs to manage the FW heaps */
-               uRawHeapBase = sDevPAddr.uiAddr;
-
-               if (PVRSRV_VZ_MODE_IS(GUEST))
-               {
-                       /* Guest subheap layout: Config + Main */
-                       uFwCfgSubHeapBase = uRawHeapBase;
-                       uFwMainSubHeapBase = uFwCfgSubHeapBase + uFwCfgSubHeapSize;
-               }
-               else
-               {
-                       /* Native/Host subheap layout: Main + (optional MIPS reserved range) + Config */
-                       uFwMainSubHeapBase = uRawHeapBase;
-                       uFwCfgSubHeapBase = uRawHeapBase + RGX_FIRMWARE_RAW_HEAP_SIZE - uFwCfgSubHeapSize;
-               }
 
 #if defined(SUPPORT_AUTOVZ)
                if (PVRSRV_VZ_MODE_IS(HOST))
@@ -4411,28 +4419,31 @@ static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode)
                        /* 1 Mb can hold the maximum amount of page tables for the memory shared between the firmware and all KM drivers:
                         *  MAX(RAW_HEAP_SIZE) = 32 Mb; MAX(NUMBER_OS) = 8; Total shared memory = 256 Mb;
                         *  MMU objects required: 65536 PTEs; 16 PDEs; 1 PCE; */
-                       RA_LENGTH_T uMaxFwMmuPageTableSize = 1 * 1024 * 1024;
+                       IMG_UINT64 uMaxFwMmuPageTableSize = 1 * 1024 * 1024;
+
+                       sFwHeapConfig = *psFwMainConfig;
 
                        /* By default the firmware MMU's page tables are allocated from the same carveout memory as the firmware heap.
                         * If a different base address is specified for this reserved range, use the overriding define instead. */
 #if defined(PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR)
-                       RA_BASE_T uFwMmuReservedMemStart = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
+                       sFwHeapConfig.sStartAddr.uiAddr = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
+                       sFwHeapConfig.sCardBase.uiAddr = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
 #else
-                       RA_BASE_T uFwMmuReservedMemStart = uRawHeapBase + (RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED);
+                       sFwHeapConfig.sStartAddr.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED;
+                       sFwHeapConfig.sCardBase.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED;
 #endif
 
-                       psDeviceNode->psFwMMUReservedMemArena = RA_Create_With_Span("Fw MMU Mem 0",
-                                                                                   OSGetPageShift(),
-                                                                                   0,
-                                                                                   uFwMmuReservedMemStart,
-                                                                                   uMaxFwMmuPageTableSize);
-                       PVR_LOG_GOTO_IF_NOMEM(psDeviceNode->psFwMMUReservedMemArena, eError, ErrorDeinit);
+                       sFwHeapConfig.uiSize = uMaxFwMmuPageTableSize;
+                       sFwHeapConfig.ui32UsageFlags = 0;
+
+                       eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, "Fw MMU subheap",
+                                                     &psDeviceNode->psFwMMUReservedPhysHeap);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemCreateHeapLMA:MMU", ErrorDeinit);
                }
 #endif
 
+               /* Subheap layout: Main + (optional MIPS reserved range) + Config */
                sFwHeapConfig = *psFwMainConfig;
-               sFwHeapConfig.sStartAddr.uiAddr = sCpuPAddr.uiAddr + (uFwMainSubHeapBase - uRawHeapBase);
-               sFwHeapConfig.sCardBase.uiAddr = uFwMainSubHeapBase;
                sFwHeapConfig.uiSize = uFwMainSubHeapSize;
                sFwHeapConfig.ui32UsageFlags = PHYS_HEAP_USAGE_FW_MAIN;
 
@@ -4440,9 +4451,9 @@ static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode)
                PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemCreateHeapLMA:MAIN", ErrorDeinit);
 
                sFwHeapConfig = *psFwMainConfig;
-               sFwHeapConfig.sStartAddr.uiAddr = sCpuPAddr.uiAddr + (uFwCfgSubHeapBase - uRawHeapBase);
-               sFwHeapConfig.sCardBase.uiAddr = uFwCfgSubHeapBase;
-               sFwHeapConfig.uiSize = uFwCfgSubHeapSize;
+               sFwHeapConfig.sStartAddr.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE;
+               sFwHeapConfig.sCardBase.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE;
+               sFwHeapConfig.uiSize = RGX_FIRMWARE_CONFIG_HEAP_SIZE;
                sFwHeapConfig.ui32UsageFlags = PHYS_HEAP_USAGE_FW_CONFIG;
 
                eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, "Fw Cfg subheap", &psDeviceNode->psFWCfgPhysHeap);
@@ -4483,29 +4494,32 @@ static void _ReadNon4KHeapPageSize(IMG_UINT32 *pui32Log2Non4KPgSize)
 
        /* Get the page size for the dummy page from the NON4K heap apphint */
        OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintUINT32(pvAppHintState, GeneralNon4KHeapPageSize,
-                       &ui32AppHintDefault, &ui32GeneralNon4KHeapPageSize);
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState,
+                                GeneralNon4KHeapPageSize, &ui32AppHintDefault,
+                         &ui32GeneralNon4KHeapPageSize);
        *pui32Log2Non4KPgSize = ExactLog2(ui32GeneralNon4KHeapPageSize);
        OSFreeKMAppHintState(pvAppHintState);
 }
 
-/*
-       RGXRegisterDevice
+/* RGXRegisterDevice
+ *
+ * NOTE: No PDUMP statements are allowed in until Part 2 of the device initialisation
+ * is reached.
  */
 PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        PVRSRV_ERROR eError;
        DEVICE_MEMORY_INFO *psDevMemoryInfo;
        PVRSRV_RGXDEV_INFO      *psDevInfo;
+       void *pvAppHintState = NULL;
+       IMG_UINT32 ui32AppHintDefault = HWPERF_HOST_TL_STREAM_SIZE_DEFAULT, ui32HWPerfHostBufSizeKB;
 
-       PDUMPCOMMENT("Device Name: %s", psDeviceNode->psDevConfig->pszName);
-
-       if (psDeviceNode->psDevConfig->pszVersion)
-       {
-               PDUMPCOMMENT("Device Version: %s", psDeviceNode->psDevConfig->pszVersion);
-       }
-
-       PDUMPCOMMENT("RGX Initialisation (Part 1)");
+       ui32AppHintDefault = PVRSRV_APPHINT_DRIVERMODE;
+       OSCreateKMAppHintState(&pvAppHintState);
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, HWPerfHostBufSizeInKB,
+                            &ui32AppHintDefault, &ui32HWPerfHostBufSizeKB);
+       OSFreeKMAppHintState(pvAppHintState);
+       pvAppHintState = NULL;
 
        /*********************
         * Device node setup *
@@ -4532,9 +4546,6 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
 
        psDeviceNode->pfnMMUCacheInvalidateKick = RGXMMUCacheInvalidateKick;
 
-       /* Register RGX to receive notifies when other devices complete some work */
-       PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
-
        psDeviceNode->pfnInitDeviceCompatCheck  = &RGXDevInitCompatCheck;
 
        /* Register callbacks for creation of device memory contexts */
@@ -4799,13 +4810,6 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
                goto e14;
        }
 
-       /* pdump info about the core */
-       PDUMPCOMMENT("RGX Version Information (KM): %d.%d.%d.%d",
-                       psDevInfo->sDevFeatureCfg.ui32B,
-                       psDevInfo->sDevFeatureCfg.ui32V,
-                       psDevInfo->sDevFeatureCfg.ui32N,
-                       psDevInfo->sDevFeatureCfg.ui32C);
-
        _ReadNon4KHeapPageSize(&psDevInfo->ui32Log2Non4KPgSize);
 
        /*Set the zero & dummy page sizes as needed for the heap with largest page size */
@@ -4818,20 +4822,40 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
                goto e14;
        }
 
-
        eError = RGXHWPerfInit(psDevInfo);
        PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfInit", e14);
 
+       eError = RGXHWPerfHostInit(psDeviceNode->pvDevice, ui32HWPerfHostBufSizeKB);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfHostInit", ErrorDeInitHWPerfFw);
+
 #if defined(SUPPORT_VALIDATION)
        /* This completion will be signaled by the ISR when processing
         * the answer CCB command carrying an RGX Register read value */
        init_completion(&psDevInfo->sFwRegs.sRegComp);
        psDevInfo->sFwRegs.ui64RegVal = 0;
+
+#if defined(SUPPORT_SOC_TIMER)
+       {
+               IMG_BOOL ui32AppHintDefault = IMG_FALSE;
+               IMG_BOOL bInitSocTimer;
+               void *pvAppHintState = NULL;
+
+               OSCreateKMAppHintState(&pvAppHintState);
+               OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, ValidateSOCUSCTimer, &ui32AppHintDefault, &bInitSocTimer);
+               OSFreeKMAppHintState(pvAppHintState);
+
+               if (bInitSocTimer)
+               {
+                       eError = RGXInitSOCUSCTimer(psDeviceNode);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXInitSOCUSCTimer", ErrorDeInitHWPerfHost);
+               }
+       }
+#endif
 #endif
 
        /* Register callback for dumping debug info */
        eError = RGXDebugInit(psDevInfo);
-       PVR_LOG_GOTO_IF_ERROR(eError, "RGXDebugInit", e15);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXDebugInit", ErrorDeInitHWPerfHost);
 
        /* Register callback for fw mmu init */
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
@@ -4839,17 +4863,16 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
                psDeviceNode->pfnFwMMUInit = RGXMipsMMUInit_Register;
        }
 
-       /* switch to power on state to avoid hang while accessing register */
        PVRSRVSetSystemPowerState(psDeviceNode->psDevConfig, PVRSRV_SYS_POWER_STATE_ON);
-       RGXInitMultiCoreInfo(psDeviceNode);
-
        /* The device shared-virtual-memory heap address-space size is stored here for faster
           look-up without having to walk the device heap configuration structures during
           client device connection  (i.e. this size is relative to a zero-based offset) */
+#if defined(FIX_HW_BRN_65273_BIT_MASK)
        if (RGX_IS_BRN_SUPPORTED(psDevInfo, 65273))
        {
                psDeviceNode->ui64GeneralSVMHeapTopVA = 0;
        }else
+#endif
        {
                psDeviceNode->ui64GeneralSVMHeapTopVA = RGX_GENERAL_SVM_HEAP_BASE + RGX_GENERAL_SVM_HEAP_SIZE;
        }
@@ -4863,7 +4886,7 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
        psDeviceNode->bHasSystemDMA = psDeviceNode->psDevConfig->bHasDma;
 
        /* Initialise the device dependent bridges */
-       eError = DeviceDepBridgeInit(psDevInfo->sDevFeatureCfg.ui64Features);
+       eError = DeviceDepBridgeInit(psDevInfo);
        PVR_LOG_IF_ERROR(eError, "DeviceDepBridgeInit");
 
 #if defined(SUPPORT_POWER_SAMPLING_VIA_DEBUGFS)
@@ -4871,31 +4894,7 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock for counter sampling.", __func__));
-               goto e15;
-       }
-#endif
-
-#if defined(PDUMP)
-       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
-                                                                                 &psDeviceNode->sDummyPage,
-                                                                                 PVR_DUMMY_PAGE_INIT_VALUE,
-                                                                                 DUMMY_PAGE,
-                                             IMG_TRUE);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate dummy page.", __func__));
-               goto e16;
-       }
-
-       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
-                                                                                 &psDeviceNode->sDevZeroPage,
-                                                                                 PVR_ZERO_PAGE_INIT_VALUE,
-                                                                                 DEV_ZERO_PAGE,
-                                             IMG_TRUE);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate Zero page.", __func__));
-               goto e17;
+               goto ErrorDeInitDeviceDepBridge;
        }
 #endif
 
@@ -4904,19 +4903,17 @@ PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
 
        return PVRSRV_OK;
 
-#if defined(PDUMP)
-e17:
-       DevmemIntFreeDefBackingPage(psDeviceNode,
-                                                               &psDeviceNode->sDummyPage,
-                                                               DUMMY_PAGE);
-e16:
 #if defined(SUPPORT_POWER_SAMPLING_VIA_DEBUGFS)
-       OSLockDestroy(psDevInfo->hCounterDumpingLock);
-#endif
+ErrorDeInitDeviceDepBridge:
+       DeviceDepBridgeDeInit(psDevInfo);
 #endif
 
-e15:
+ErrorDeInitHWPerfHost:
+       RGXHWPerfHostDeInit(psDevInfo);
+
+ErrorDeInitHWPerfFw:
        RGXHWPerfDeinit(psDevInfo);
+
 e14:
 #if !defined(NO_HARDWARE)
        OSUnMapPhysToLin((void __force *) psDevInfo->pvRegsBaseKM,
@@ -5092,6 +5089,7 @@ static PVRSRV_ERROR RGXInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap, IMG_UI
        /* Append the OSID number to the RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT string */
        OSSNPrintf((IMG_CHAR *)psDevMemHeap->pszName, uiStringLength, RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT, ui32OSid);
 
+       /* Use the common blueprint template support function to initialise the heap */
        HeapCfgBlueprintInit(psDevMemHeap->pszName,
                                 RGX_FIRMWARE_RAW_HEAP_BASE + (ui32OSid * RGX_FIRMWARE_RAW_HEAP_SIZE),
                                 RGX_FIRMWARE_RAW_HEAP_SIZE,
index 1acc108..6cc8c8b 100644 (file)
@@ -74,7 +74,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ******************************************************************************/
 PVRSRV_ERROR RGXInitDevPart2 (PVRSRV_DEVICE_NODE       *psDeviceNode,
                                                          IMG_UINT32                    ui32DeviceFlags,
-                                                         IMG_UINT32                    ui32HWPerfHostBufSizeKB,
                                                          IMG_UINT32                    ui32HWPerfHostFilter,
                                                          RGX_ACTIVEPM_CONF             eActivePMConf);
 
@@ -114,6 +113,7 @@ RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
                 IMG_UINT32               *pui32TPUTrilinearFracMask,
                 RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
                 FW_PERF_CONF             eFirmwarePerf,
+                IMG_UINT32               ui32KCCBSizeLog2,
                 IMG_UINT32               ui32ConfigFlagsExt,
                 IMG_UINT32               ui32FwOsCfgFlags);
 
index 4a65b19..431a7b6 100644 (file)
@@ -64,6 +64,7 @@ extern "C" {
 #include "img_types.h"
 #include "img_elf.h"
 #include "pvrsrv_error.h" /* includes pvrsrv_errors.h */
+#include "pvrsrv_firmware_boot.h"
 #include "rgx_bvnc_defs_km.h"
 #include "rgx_fw_info.h"
 #include "rgx_fwif_shared.h" /* includes rgx_common.h and mem_types.h */
index 1702364..c82b04c 100644 (file)
@@ -49,9 +49,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "devicemem.h"
 #include "cache_km.h"
 #include "pmr.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #if defined(PDUMP)
 #include <stdarg.h>
@@ -80,11 +77,17 @@ void RGXCommentLog(const void *hPrivate,
                ...)
 {
 #if defined(PDUMP)
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
        va_list argList;
        va_start(argList, pszString);
-       PDumpCommentWithFlagsVA(PDUMP_FLAGS_CONTINUOUS, pszString, argList);
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       PDumpCommentWithFlagsVA(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, pszString, argList);
        va_end(argList);
-       PVR_UNREFERENCED_PARAMETER(hPrivate);
 #else
        PVR_UNREFERENCED_PARAMETER(hPrivate);
        PVR_UNREFERENCED_PARAMETER(pszString);
@@ -115,6 +118,7 @@ IMG_UINT32 RGXGetOSPageSize(const void *hPrivate)
 
 IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate)
 {
+#if defined(RGX_FEATURE_META_COREMEM_SIZE_MAX_VALUE_IDX)
        RGX_LAYER_PARAMS *psParams;
        PVRSRV_RGXDEV_INFO *psDevInfo;
        IMG_UINT32 ui32CorememSize = 0;
@@ -130,6 +134,11 @@ IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate)
        }
 
        return ui32CorememSize;
+#else
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+
+       return 0U;
+#endif
 }
 
 void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
@@ -150,7 +159,8 @@ void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32
                OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
        }
 
-       PDUMPREG32(RGX_PDUMPREG_NAME, ui32RegAddr, ui32RegValue, psParams->ui32PdumpFlags);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                  ui32RegAddr, ui32RegValue, psParams->ui32PdumpFlags);
 }
 
 void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64RegValue)
@@ -171,7 +181,8 @@ void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64
                OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
        }
 
-       PDUMPREG64(RGX_PDUMPREG_NAME, ui32RegAddr, ui64RegValue, psParams->ui32PdumpFlags);
+       PDUMPREG64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                  ui32RegAddr, ui64RegValue, psParams->ui32PdumpFlags);
 }
 
 IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
@@ -197,7 +208,8 @@ IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
                ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
        }
 
-       PDUMPREGREAD32(RGX_PDUMPREG_NAME, ui32RegAddr, psParams->ui32PdumpFlags);
+       PDUMPREGREAD32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                      ui32RegAddr, psParams->ui32PdumpFlags);
 
        return ui32RegValue;
 }
@@ -225,7 +237,8 @@ IMG_UINT64 RGXReadReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr)
                ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
        }
 
-       PDUMPREGREAD64(RGX_PDUMPREG_NAME, ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREGREAD64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                      ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
 
        return ui64RegValue;
 }
@@ -255,16 +268,20 @@ IMG_UINT32 RGXReadModifyWriteReg64(const void *hPrivate,
        PDUMP_BLKSTART(ui32PDumpFlags);
 
        /* Store register offset to temp PDump variable */
-       PDumpRegRead64ToInternalVar(RGX_PDUMPREG_NAME, ":SYSMEM:$1", ui32RegAddr, ui32PDumpFlags);
+       PDumpRegRead64ToInternalVar(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                                   ":SYSMEM:$1", ui32RegAddr, ui32PDumpFlags);
 
        /* Keep the bits set in the mask */
-       PDumpWriteVarANDValueOp(":SYSMEM:$1", uiRegKeepMask, ui32PDumpFlags);
+       PDumpWriteVarANDValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                               uiRegKeepMask, ui32PDumpFlags);
 
        /* OR the new values */
-       PDumpWriteVarORValueOp(":SYSMEM:$1", uiRegValueNew, ui32PDumpFlags);
+       PDumpWriteVarORValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                              uiRegValueNew, ui32PDumpFlags);
 
        /* Do the actual register write */
-       PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
+       PDumpInternalVarToReg64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                               ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
 
        PDUMP_BLKEND(ui32PDumpFlags);
 
@@ -309,7 +326,8 @@ PVRSRV_ERROR RGXPollReg32(const void *hPrivate,
                }
        }
 
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                       RGX_PDUMPREG_NAME,
                        ui32RegAddr,
                        ui32RegValue,
                        ui32RegMask,
@@ -364,7 +382,8 @@ PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
                }
        }
 
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                       RGX_PDUMPREG_NAME,
                        ui32RegAddr + 4,
                        ui32UpperValue,
                        ui32UpperMask,
@@ -372,7 +391,8 @@ PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
                        PDUMP_POLL_OPERATOR_EQUAL);
 
 
-       PDUMPREGPOL(RGX_PDUMPREG_NAME,
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                       RGX_PDUMPREG_NAME,
                        ui32RegAddr,
                        ui32LowerValue,
                        ui32LowerMask,
@@ -384,14 +404,12 @@ PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
 
 void RGXWaitCycles(const void *hPrivate, IMG_UINT32 ui32Cycles, IMG_UINT32 ui32TimeUs)
 {
-       PVR_UNREFERENCED_PARAMETER(hPrivate);
-#ifdef __FPGA_VERIFICATION__
-#warning "RGXWaitCycles() will be modified on FPGA platform"
-       OSWaitus(ui32TimeUs * 60);
-#else
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
        OSWaitus(ui32TimeUs);
-#endif
-       PDUMPIDLWITHFLAGS(ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPIDLWITHFLAGS(psDevInfo->psDeviceNode, ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
 }
 
 void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr)
@@ -476,16 +494,20 @@ void RGXMIPSWrapperConfig(const void *hPrivate,
        PDUMP_BLKSTART(ui32PDumpFlags);
 
        /* Store register offset to temp PDump variable */
-       PDumpRegLabelToInternalVar(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
+       PDumpRegLabelToInternalVar(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                                  ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
 
        /* Align register transactions identifier */
-       PDumpWriteVarSHRValueOp(":SYSMEM:$1", ui32GPURegsAlign, ui32PDumpFlags);
+       PDumpWriteVarSHRValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                               ui32GPURegsAlign, ui32PDumpFlags);
 
        /* Enable micromips instruction encoding */
-       PDumpWriteVarORValueOp(":SYSMEM:$1", ui32BootMode, ui32PDumpFlags);
+       PDumpWriteVarORValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                              ui32BootMode, ui32PDumpFlags);
 
        /* Do the actual register write */
-       PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
+       PDumpInternalVarToReg64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                               ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
 
        PDUMP_BLKEND(ui32PDumpFlags);
 }
@@ -526,22 +548,28 @@ void RGXWriteRemapConfig2Reg(void __iomem *pvRegs,
                IMG_UINT64 ui64Settings)
 {
        PDUMP_FLAGS_T ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+       PVRSRV_DEVICE_NODE *psDevNode;
+
+       PVR_ASSERT(psPMR != NULL);
+       psDevNode = PMR_DeviceNode(psPMR);
 
        OSWriteHWReg64(pvRegs, ui32RegAddr, (ui64PhyAddr & ui64PhyMask) | ui64Settings);
 
        PDUMP_BLKSTART(ui32PDumpFlags);
 
        /* Store memory offset to temp PDump variable */
-       PDumpMemLabelToInternalVar64(":SYSMEM:$1", psPMR, uiLogicalOffset, ui32PDumpFlags);
+       PDumpMemLabelToInternalVar64(":SYSMEM:$1", psPMR,
+                                    uiLogicalOffset, ui32PDumpFlags);
 
        /* Keep only the relevant bits of the output physical address */
-       PDumpWriteVarANDValueOp(":SYSMEM:$1", ui64PhyMask, ui32PDumpFlags);
+       PDumpWriteVarANDValueOp(psDevNode, ":SYSMEM:$1", ui64PhyMask, ui32PDumpFlags);
 
        /* Extra settings for this remapped region */
-       PDumpWriteVarORValueOp(":SYSMEM:$1", ui64Settings, ui32PDumpFlags);
+       PDumpWriteVarORValueOp(psDevNode, ":SYSMEM:$1", ui64Settings, ui32PDumpFlags);
 
        /* Do the actual register write */
-       PDumpInternalVarToReg64(RGX_PDUMPREG_NAME, ui32RegAddr, ":SYSMEM:$1", ui32PDumpFlags);
+       PDumpInternalVarToReg64(psDevNode, RGX_PDUMPREG_NAME, ui32RegAddr,
+                               ":SYSMEM:$1", ui32PDumpFlags);
 
        PDUMP_BLKEND(ui32PDumpFlags);
 }
@@ -655,22 +683,23 @@ void RGXTrampolineRemapConfig(const void *hPrivate,
        PDUMP_BLKSTART(ui32PDumpFlags);
 
        /* Store the memory address in a PDump variable */
-       PDumpPhysHandleToInternalVar64(":SYSMEM:$1",
+       PDumpPhysHandleToInternalVar64(psDevInfo->psDeviceNode, ":SYSMEM:$1",
                        psDevInfo->psTrampoline->hPdumpPages,
                        ui32PDumpFlags);
 
        /* Keep only the relevant bits of the input physical address */
-       PDumpWriteVarANDValueOp(":SYSMEM:$1",
+       PDumpWriteVarANDValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
                        ~RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_BASE_ADDR_IN_CLRMSK,
                        ui32PDumpFlags);
 
        /* Enable bit */
-       PDumpWriteVarORValueOp(":SYSMEM:$1",
+       PDumpWriteVarORValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
                        RGX_CR_MIPS_ADDR_REMAP4_CONFIG1_MODE_ENABLE_EN,
                        ui32PDumpFlags);
 
        /* Do the PDump register write */
-       PDumpInternalVarToReg64(RGX_PDUMPREG_NAME,
+       PDumpInternalVarToReg64(psDevInfo->psDeviceNode,
+                       RGX_PDUMPREG_NAME,
                        ui32Config1RegAddr,
                        ":SYSMEM:$1",
                        ui32PDumpFlags);
@@ -703,6 +732,7 @@ IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate)
        return PVRSRVSystemSnoopingOfCPUCache(psDevConfig);
 }
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
@@ -720,8 +750,9 @@ static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui
 
        return eError;
 }
-extern void do_invalid_range(unsigned long start, unsigned long len);
+#endif
 
+extern void do_invalid_range(unsigned long start, unsigned long len);
 /*
  * The fabric coherency test is performed when platform supports fabric coherency
  * either in the form of ACE-lite or Full-ACE. This test is done quite early
@@ -733,45 +764,43 @@ extern void do_invalid_range(unsigned long start, unsigned long len);
  */
 PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        PVRSRV_RGXDEV_INFO *psDevInfo;
        IMG_UINT32 *pui32FabricCohTestBufferCpuVA;
        DEVMEM_MEMDESC *psFabricCohTestBufferMemDesc;
        RGXFWIF_DEV_VIRTADDR sFabricCohTestBufferDevVA;
        IMG_DEVMEM_SIZE_T uiFabricCohTestBlockSize = sizeof(IMG_UINT64);
        IMG_DEVMEM_ALIGN_T uiFabricCohTestBlockAlign = sizeof(IMG_UINT64);
-       IMG_UINT64 ui64SegOutAddrTopCached = 0;
-       IMG_UINT64 ui64SegOutAddrTopUncached = 0;
        IMG_UINT32 ui32SLCCTRL = 0;
        IMG_UINT32 ui32OddEven;
-       IMG_BOOL   bFeatureS7;
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+       IMG_BOOL   bFeatureS7 = RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE);
+#endif
        IMG_UINT32 ui32TestType;
        IMG_UINT32 ui32OddEvenSeed = 1;
        PVRSRV_ERROR eError = PVRSRV_OK;
        IMG_BOOL bFullTestPassed = IMG_TRUE;
-       IMG_BOOL bSubTestPassed = IMG_FALSE;
        IMG_BOOL bExit = IMG_FALSE;
+#if defined(DEBUG)
+       IMG_BOOL bSubTestPassed = IMG_FALSE;
+#endif
 
        PVR_ASSERT(hPrivate != NULL);
        psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
 
        PVR_LOG(("Starting fabric coherency test ....."));
 
-       bFeatureS7 = RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE);
-
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (bFeatureS7)
        {
-               ui64SegOutAddrTopCached   = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_CACHED(MMU_CONTEXT_MAPPING_FWIF);
-               ui64SegOutAddrTopUncached = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_UNCACHED(MMU_CONTEXT_MAPPING_FWIF);
+               IMG_UINT64 ui64SegOutAddrTopUncached = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_UNCACHED(MMU_CONTEXT_MAPPING_FWIF);
 
                /* Configure META to use SLC force-linefill for the bootloader segment */
                RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
                                (ui64SegOutAddrTopUncached | RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
        }
        else
+#endif
        {
                /* Bypass the SLC when IO coherency is enabled */
                ui32SLCCTRL = RGXReadReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS);
@@ -825,16 +854,6 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
                goto e1;
        }
 
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psFabricCohTestBufferMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           //BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pui32FabricCohTestBufferCpuVA - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif 
-
        /* Create a FW address which is uncached in the Meta DCache and in the SLC
         * using the Meta bootloader segment.
         * This segment is the only one configured correctly out of reset
@@ -941,11 +960,11 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
                                        }
 
                                        /* Write the value using the RGX slave-port interface */
-                                       eError = RGXWriteMETAAddr(psDevInfo, ui32FWAddr, ui32FWValue);
+                                       eError = RGXWriteFWModuleAddr(psDevInfo, ui32FWAddr, ui32FWValue);
                                        if (eError != PVRSRV_OK)
                                        {
                                                PVR_DPF((PVR_DBG_ERROR,
-                                                               "RGXWriteMETAAddr error: %s, exiting",
+                                                               "RGXWriteFWModuleAddr error: %s, exiting",
                                                                PVRSRVGetErrorString(eError)));
                                                bExit = IMG_TRUE;
                                                continue;
@@ -953,11 +972,11 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
 
                                        /* Read back value using RGX slave-port interface, this is used
                                           as a sort of memory barrier for the above write */
-                                       eError = RGXReadMETAAddr(psDevInfo, ui32FWAddr, &ui32FWValue2);
+                                       eError = RGXReadFWModuleAddr(psDevInfo, ui32FWAddr, &ui32FWValue2);
                                        if (eError != PVRSRV_OK)
                                        {
                                                PVR_DPF((PVR_DBG_ERROR,
-                                                               "RGXReadMETAAddr error: %s, exiting",
+                                                               "RGXReadFWModuleAddr error: %s, exiting",
                                                                PVRSRVGetErrorString(eError)));
                                                bExit = IMG_TRUE;
                                                continue;
@@ -1004,7 +1023,7 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
                                        pui32FabricCohTestBufferCpuVA[i] = i + ui32OddEvenSeed;
 
                                        /* Flush possible cpu store-buffer(ing) on LMA */
-                                       OSWriteMemoryBarrier();
+                                       OSWriteMemoryBarrier(&pui32FabricCohTestBufferCpuVA[i]);
 
                                        switch (ui32TestType)
                                        {
@@ -1022,11 +1041,11 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
                                        }
 
                                        /* Read back value using RGX slave-port interface */
-                                       eError = RGXReadMETAAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
+                                       eError = RGXReadFWModuleAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
                                        if (eError != PVRSRV_OK)
                                        {
                                                PVR_DPF((PVR_DBG_ERROR,
-                                                               "RGXReadWithSP error: %s, exiting",
+                                                               "RGXReadFWModuleAddr error: %s, exiting",
                                                                PVRSRVGetErrorString(eError)));
                                                bExit = IMG_TRUE;
                                                continue;
@@ -1057,13 +1076,17 @@ PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
                                /* Compare to see if sub-test passed */
                                if (pui32FabricCohTestBufferCpuVA[i] == ui32FWValue)
                                {
+#if defined(DEBUG)
                                        bSubTestPassed = IMG_TRUE;
+#endif
                                }
                                else
                                {
-                                       bSubTestPassed = IMG_FALSE;
                                        bFullTestPassed = IMG_FALSE;
                                        eError = PVRSRV_ERROR_INIT_FAILURE;
+#if defined(DEBUG)
+                                       bSubTestPassed = IMG_FALSE;
+#endif
                                        if (ui32LastFWValue != ui32FWValue)
                                        {
 #if defined(DEBUG)
@@ -1122,13 +1145,16 @@ e1:
        DevmemFwUnmapAndFree(psDevInfo, psFabricCohTestBufferMemDesc);
 
 e0:
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (bFeatureS7)
        {
                /* Restore bootloader segment settings */
+               IMG_UINT64 ui64SegOutAddrTopCached   = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_CACHED(MMU_CONTEXT_MAPPING_FWIF);
                RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
                                (ui64SegOutAddrTopCached | RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
        }
        else
+#endif
        {
                /* Restore SLC bypass settings */
                RGXWriteReg32(hPrivate, RGX_CR_SLC_CTRL_BYPASS, ui32SLCCTRL);
@@ -1147,6 +1173,11 @@ e0:
        }
 
        return eError;
+#else
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+
+       return PVRSRV_OK;
+#endif
 }
 
 IMG_INT32 RGXDeviceGetFeatureValue(const void *hPrivate, IMG_UINT64 ui64Feature)
index 4af4cdb..0e6c0ab 100644 (file)
@@ -696,7 +696,8 @@ static PVRSRV_ERROR RGXCheckTrampolineAddrs(struct _PVRSRV_DEVICE_NODE_ *psDevNo
                {
                        PVRSRV_RGXDEV_INFO *psDevice = (PVRSRV_RGXDEV_INFO *)psDevNode->pvDevice;
 
-                       if (RGXMIPSFW_SENSITIVE_ADDR(*pui64Addr))
+                       if ((RGX_GET_FEATURE_VALUE(psDevice, PHYS_BUS_WIDTH) == 32) &&
+                                RGXMIPSFW_SENSITIVE_ADDR(*pui64Addr))
                        {
                                *pui64Addr = psDevice->psTrampoline->sPhysAddr.uiAddr + RGXMIPSFW_TRAMPOLINE_OFFSET(*pui64Addr);
                        }
@@ -1005,3 +1006,40 @@ static PVRSRV_ERROR RGXGetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32
        PVR_DPF((PVR_DBG_ERROR, "PDE not supported on MIPS"));
        return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
 }
+
+void RGXMipsCheckFaultAddress(MMU_CONTEXT *psFwMMUCtx,
+                              IMG_UINT32 ui32FwVA,
+                              MMU_FAULT_DATA *psOutFaultData)
+{
+       IMG_UINT32 *pui32PageTable = NULL;
+       PVRSRV_ERROR eError = MMU_AcquireCPUBaseAddr(psFwMMUCtx, (void**) &pui32PageTable);
+       MMU_LEVEL_DATA *psMMULevelData;
+       IMG_UINT32 ui32FwHeapBase = (IMG_UINT32) (RGX_FIRMWARE_RAW_HEAP_BASE & UINT_MAX);
+       IMG_UINT32 ui32PageSize = OSGetPageSize();
+
+       /* MIPS Firmware CPU must use the same page size as the Host */
+       IMG_UINT32 ui32PTEIndex = ((ui32FwVA & ~(ui32PageSize - 1)) - ui32FwHeapBase) / ui32PageSize;
+
+       psOutFaultData->eTopLevel = MMU_LEVEL_1;
+       psOutFaultData->eType = MMU_FAULT_TYPE_NON_PM;
+
+       psMMULevelData = &psOutFaultData->sLevelData[MMU_LEVEL_1];
+       psMMULevelData->uiBytesPerEntry = 1 << RGXMIPSFW_LOG2_PTE_ENTRY_SIZE;
+       psMMULevelData->ui32Index = ui32PTEIndex;
+       psMMULevelData->ui32NumOfEntries = RGX_FIRMWARE_RAW_HEAP_SIZE / ui32PageSize;
+
+       if ((eError == PVRSRV_OK) && (pui32PageTable != NULL))
+       {
+               psMMULevelData->ui64Address = pui32PageTable[ui32PTEIndex];
+       }
+       else
+       {
+               psMMULevelData->ui64Address = 0U;
+       }
+
+       psMMULevelData->psDebugStr = BITMASK_HAS(psMMULevelData->ui64Address,
+                                                RGXMIPSFW_TLB_VALID) ?
+                                    ("valid") : ("not valid");
+}
+
+
index 7129bc4..b2b3940 100644 (file)
@@ -90,5 +90,8 @@ Page Table entry #
 PVRSRV_ERROR RGXMipsMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode);
 PVRSRV_ERROR RGXMipsMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode);
 
+void RGXMipsCheckFaultAddress(MMU_CONTEXT *psFwMMUCtx,
+                              IMG_UINT32 ui32FwVA,
+                              MMU_FAULT_DATA *psOutFaultData);
 
 #endif /* #ifndef SRVKM_RGXMIPSMMUINIT_H */
index 10c26e0..629e7ab 100644 (file)
@@ -892,7 +892,7 @@ static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2Dat
        else if (MMU_PROTFLAGS_WRITEABLE & uiProtFlags)
        {
                /* write only */
-               PVR_DPF((PVR_DBG_MESSAGE, "RGXDerivePTEProt8: write-only is not possible on this device"));
+               PVR_DPF((PVR_DBG_WARNING, "RGXDerivePTEProt8: write-only is not possible on this device"));
        }
        else if ((MMU_PROTFLAGS_INVALID & uiProtFlags) == 0)
        {
index ec268dc..a888e70 100644 (file)
@@ -155,7 +155,7 @@ PVRSRV_ERROR RGXInitMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
                ui32NumCores = RGX_MULTICORE_MAX_NOHW_CORES;
 #endif
                PVR_DPF((PVR_DBG_MESSAGE, "Multicore system has %u cores", ui32NumCores));
-               PDUMPCOMMENT("RGX Multicore has %d cores\n", ui32NumCores);
+               PDUMPCOMMENT(psDeviceNode, "RGX Multicore has %d cores\n", ui32NumCores);
 
                /* allocate storage for capabilities */
                psDeviceNode->pui64MultiCoreCapabilities = OSAllocMem(ui32NumCores * sizeof(psDeviceNode->pui64MultiCoreCapabilities[0]));
@@ -181,7 +181,8 @@ PVRSRV_ERROR RGXInitMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
                                                           | RGX_MULTICORE_CAPABILITY_FRAGMENT_EN;
        #endif
                        PVR_DPF((PVR_DBG_MESSAGE, "Core %d has capabilities value 0x%x", i, (IMG_UINT32)psDeviceNode->pui64MultiCoreCapabilities[i] ));
-                       PDUMPCOMMENT("\tCore %d has caps 0x%08x\n", i, (IMG_UINT32)psDeviceNode->pui64MultiCoreCapabilities[i]);
+                       PDUMPCOMMENT(psDeviceNode, "\tCore %d has caps 0x%08x\n", i,
+                                    (IMG_UINT32)psDeviceNode->pui64MultiCoreCapabilities[i]);
 
                        if (psDeviceNode->pui64MultiCoreCapabilities[i] & RGX_CR_MULTICORE_GPU_CAPABILITY_PRIMARY_EN)
                        {
index b420996..750281d 100644 (file)
@@ -62,12 +62,12 @@ static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
 
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
-       PDUMPIF("DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
-       PDUMPELSE("DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+       PDUMPIF(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+       PDUMPELSE(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
 
 #if defined(SUPPORT_FIRMWARE_GCOV)
        /* Gcov */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Gcov Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Gcov Buffer");
        DevmemPDumpSaveToFileVirtual(psDevInfo->psFirmwareGcovBufferMemDesc,
                                                                         0,
                                                                         psDevInfo->ui32FirmwareGcovSize,
@@ -76,7 +76,7 @@ static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                                         ui32PDumpFlags);
 #endif
        /* TA signatures */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
        DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigTAChecksMemDesc,
                                                                 0,
                                                                 psDevInfo->ui32SigTAChecksSize,
@@ -85,7 +85,7 @@ static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                                 ui32PDumpFlags);
 
        /* 3D signatures */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
        DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSig3DChecksMemDesc,
                                                                 0,
                                                                 psDevInfo->ui32Sig3DChecksSize,
@@ -93,10 +93,11 @@ static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                                 0,
                                                                 ui32PDumpFlags);
 
+#if defined(RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TDM_PDS_CHECKSUM))
        {
                /* TDM signatures */
-               PDumpCommentWithFlags(ui32PDumpFlags, "** Dump TDM signatures and checksums Buffer");
+               PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TDM signatures and checksums Buffer");
                DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigTDM2DChecksMemDesc,
                                                                         0,
                                                                         psDevInfo->ui32SigTDM2DChecksSize,
@@ -104,8 +105,9 @@ static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                                         0,
                                                                         ui32PDumpFlags);
        }
+#endif
 
-       PDUMPFI("DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+       PDUMPFI(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
 
        return PVRSRV_OK;
 }
@@ -120,7 +122,7 @@ static PVRSRV_ERROR _FWDumpTraceBufferKM(CONNECTION_DATA * psConnection,
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
        /* Dump trace buffers */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump trace buffers");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump trace buffers");
        for (ui32ThreadNum = 0, ui32OutFileOffset = 0; ui32ThreadNum < RGXFW_THREAD_NUM; ui32ThreadNum++)
        {
                /*
@@ -181,7 +183,7 @@ static PVRSRV_ERROR _FWDumpTraceBufferKM(CONNECTION_DATA * psConnection,
        PVR_ASSERT(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
 
        /* Dump hwperf buffer */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump HWPerf Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump HWPerf Buffer");
        DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfHWPerfBufMemDesc,
                                                                 0,
                                                                 psDevInfo->ui32RGXFWIfHWPerfBufSize,
@@ -203,7 +205,7 @@ static PVRSRV_ERROR _MipsDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
        /* TA signatures */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
 
        DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigTAChecksMemDesc,
                                                                 0,
@@ -212,23 +214,25 @@ static PVRSRV_ERROR _MipsDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
                                                                 0);
 
        /* 3D signatures */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
        DevmemPDumpSaveToFile(psDevInfo->psRGXFWSig3DChecksMemDesc,
                                                                 0,
                                                                 psDevInfo->ui32Sig3DChecksSize,
                                                                 "out.3dsig",
                                                                 0);
 
+#if defined(RGX_FEATURE_TDM_PDS_CHECKSUM_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TDM_PDS_CHECKSUM))
        {
                /* TDM signatures */
-               PDumpCommentWithFlags(ui32PDumpFlags, "** Dump TDM signatures and checksums Buffer");
+               PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TDM signatures and checksums Buffer");
                DevmemPDumpSaveToFile(psDevInfo->psRGXFWSigTDM2DChecksMemDesc,
                                                                         0,
                                                                         psDevInfo->ui32SigTDM2DChecksSize,
                                                                         "out.tdmsig",
                                                                         0);
        }
+#endif
 
        return PVRSRV_OK;
 }
@@ -243,7 +247,7 @@ static PVRSRV_ERROR _MipsDumpTraceBufferKM(CONNECTION_DATA *psConnection,
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
        /* Dump trace buffers */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump trace buffers");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump trace buffers");
        for (ui32ThreadNum = 0, ui32OutFileOffset = 0; ui32ThreadNum < RGXFW_THREAD_NUM; ui32ThreadNum++)
        {
                /*
@@ -299,7 +303,7 @@ static PVRSRV_ERROR _MipsDumpTraceBufferKM(CONNECTION_DATA *psConnection,
        }
 
        /* Dump hwperf buffer */
-       PDumpCommentWithFlags(ui32PDumpFlags, "** Dump HWPerf Buffer");
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump HWPerf Buffer");
        DevmemPDumpSaveToFile(psDevInfo->psRGXFWIfHWPerfBufMemDesc,
                                                                 0,
                                                                 psDevInfo->ui32RGXFWIfHWPerfBufSize,
@@ -352,8 +356,9 @@ PVRSRV_ERROR PVRSRVPDumpComputeCRCSignatureCheckKM(CONNECTION_DATA * psConnectio
         */
        if (psDevInfo->ui32ValidationFlags & RGX_VAL_KZ_SIG_CHECK_NOERR_EN)
        {
-               PDUMPCOMMENT("Verify KZ Signature: match required");
-               eError = PDUMPREGPOL(RGX_PDUMPREG_NAME,
+               PDUMPCOMMENT(psDeviceNode, "Verify KZ Signature: match required");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
                                     RGX_CR_SCRATCH11,
                                     1U,
                                     0xFFFFFFFF,
@@ -362,8 +367,9 @@ PVRSRV_ERROR PVRSRVPDumpComputeCRCSignatureCheckKM(CONNECTION_DATA * psConnectio
        }
        else if (psDevInfo->ui32ValidationFlags & RGX_VAL_KZ_SIG_CHECK_ERR_EN)
        {
-               PDUMPCOMMENT("Verify KZ Signature: mismatch required");
-               eError = PDUMPREGPOL(RGX_PDUMPREG_NAME,
+               PDUMPCOMMENT(psDeviceNode, "Verify KZ Signature: mismatch required");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
                                     RGX_CR_SCRATCH11,
                                     2U,
                                     0xFFFFFFFF,
@@ -449,6 +455,12 @@ PVRSRV_ERROR RGXPDumpPrepareOutputImageDescriptorHdr(PVRSRV_DEVICE_NODE *psDevic
        IMG_PUINT32 pui32Word;
        IMG_UINT32 ui32HeaderDataSize;
 
+#if defined(RGX_FEATURE_TFBC_LOSSY_37_PERCENT_BIT_MASK) || defined(RGX_FEATURE_TFBC_DELTA_CORRELATION_BIT_MASK) || defined(RGX_FEATURE_TFBC_NATIVE_YUV10_BIT_MASK)
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32 ui32TFBCControl = (psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlagsExt & RGXFWIF_INICFG_EXT_TFBC_CONTROL_MASK) >>
+                                                                                                                                                                         RGXFWIF_INICFG_EXT_TFBC_CONTROL_SHIFT;
+#endif
+
        /* Validate parameters */
        if (((IMAGE_HEADER_SIZE & ~(HEADER_WORD1_SIZE_CLRMSK >> HEADER_WORD1_SIZE_SHIFT)) != 0) ||
                ((IMAGE_HEADER_VERSION & ~(HEADER_WORD1_VERSION_CLRMSK >> HEADER_WORD1_VERSION_SHIFT)) != 0))
@@ -456,6 +468,8 @@ PVRSRV_ERROR RGXPDumpPrepareOutputImageDescriptorHdr(PVRSRV_DEVICE_NODE *psDevic
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
+       memset(pbyPDumpImageHdr, 0, IMAGE_HEADER_SIZE);
+
        pui32Word = IMG_OFFSET_ADDR(pbyPDumpImageHdr, 0);
        pui32Word[0] = (IMAGE_HEADER_TYPE << HEADER_WORD0_TYPE_SHIFT);
        pui32Word[1] = (IMAGE_HEADER_SIZE << HEADER_WORD1_SIZE_SHIFT) |
@@ -528,6 +542,13 @@ PVRSRV_ERROR RGXPDumpPrepareOutputImageDescriptorHdr(PVRSRV_DEVICE_NODE *psDevic
                                pui32Word[9] |= IMAGE_HEADER_WORD9_LOSSY_25;
                        }
 
+                       if (eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY37_8x8  ||
+                               eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY37_16x4 ||
+                               eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY37_32x2)
+                       {
+                               pui32Word[9] |= IMAGE_HEADER_WORD9_LOSSY_37;
+                       }
+
                        if (eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8  ||
                                eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4 ||
                                eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2)
@@ -575,6 +596,69 @@ PVRSRV_ERROR RGXPDumpPrepareOutputImageDescriptorHdr(PVRSRV_DEVICE_NODE *psDevic
        pui32Word[12] = paui32FBCClearColour[2];
        pui32Word[13] = paui32FBCClearColour[3];
 
+#if defined(RGX_FEATURE_TFBC_LOSSY_37_PERCENT_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_LOSSY_37_PERCENT))
+       {
+               /* Should match current value of RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP */
+               IMG_UINT32 ui32TFBCGroup  = (ui32TFBCControl & ~RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_CLRMSK) >>
+                                                                                                               RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_SHIFT;
+               switch (ui32TFBCGroup)
+               {
+                       case RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_GROUP_0:
+                               pui32Word[14] = IMAGE_HEADER_WORD14_TFBC_GROUP_25_50_75;
+                               break;
+                       case RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_GROUP_1:
+                               pui32Word[14] = IMAGE_HEADER_WORD14_TFBC_GROUP_25_37_50;
+                               break;
+               }
+       }
+       else
+#endif
+       {
+               pui32Word[14] = IMAGE_HEADER_WORD14_TFBC_GROUP_25_50_75;
+       }
+
+#if defined(RGX_FEATURE_TFBC_DELTA_CORRELATION_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_DELTA_CORRELATION))
+       {
+               /* Should match current value of RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME */
+               IMG_UINT32 ui32TFBCScheme = (ui32TFBCControl & ~RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_CLRMSK) >>
+                                                                                                               RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_SHIFT;
+               switch (ui32TFBCScheme)
+               {
+                       case RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_DEFAULT:
+                               pui32Word[14] |= IMAGE_HEADER_WORD14_COMP_SCHEME_ALL;
+                               break;
+                       case RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_TFBC_DELTA_STANDARD_AND_CORRELATION:
+                               pui32Word[14] |= IMAGE_HEADER_WORD14_COMP_SCHEME_D_STD_CORR;
+                               break;
+                       case RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_TFBC_DELTA_STANDARD:
+                               pui32Word[14] |= IMAGE_HEADER_WORD14_COMP_SCHEME_D_STD_ONLY;
+                               break;
+                       default:
+                               PVR_DPF((PVR_DBG_ERROR, "Unsupported TFBC compression control scheme - %d", ui32TFBCScheme));
+                               return PVRSRV_ERROR_UNSUPPORTED_FB_COMPRESSION_MODE;
+               }
+       }
+       else
+#endif
+       {
+               /* Should always be set to 2 ("TFBC delta standard only") on cores without this feature */
+               pui32Word[14] |= IMAGE_HEADER_WORD14_COMP_SCHEME_D_STD_ONLY;
+       }
+
+#if defined(RGX_FEATURE_TFBC_NATIVE_YUV10_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_NATIVE_YUV10))
+       {
+               IMG_UINT32 ui32TFBCOverrideYUV10 = (ui32TFBCControl & RGX_CR_TFBC_COMPRESSION_CONTROL_YUV10_OVERRIDE_EN);
+
+               if (ui32TFBCOverrideYUV10)
+               {
+                       pui32Word[14] |= IMAGE_HEADER_WORD14_YUV10_OPTIMAL_FMT_8_EN;
+               }
+       }
+#endif
+
        return PVRSRV_OK;
 }
 
index c66112a..1a2a09e 100644 (file)
@@ -74,9 +74,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) && defined(PDUMP)
 #include "oskm_apphint.h"
 #endif
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 static PVRSRV_ERROR RGXFWNotifyHostTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
@@ -111,7 +108,7 @@ static void _RGXUpdateGPUUtilStats(PVRSRV_RGXDEV_INFO *psDevInfo)
 
        OSLockAcquire(psDevInfo->hGPUUtilLock);
 
-       ui64TimeNow = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64());
+       ui64TimeNow = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64(psDevInfo->psDeviceNode));
 
        /* Update counters to account for the time since the last update */
        ui64LastState  = RGXFWIF_GPU_UTIL_GET_STATE(psUtilFWCb->ui64LastWord);
@@ -156,7 +153,7 @@ static INLINE PVRSRV_ERROR RGXDoStop(PVRSRV_DEVICE_NODE *psDeviceNode)
 PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                               hDevHandle,
                               PVRSRV_DEV_POWER_STATE   eNewPowerState,
                               PVRSRV_DEV_POWER_STATE   eCurrentPowerState,
-                              IMG_BOOL                                 bForced)
+                              PVRSRV_POWER_FLAGS               ePwrFlags)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        PVRSRV_DEVICE_NODE    *psDeviceNode = hDevHandle;
@@ -168,12 +165,12 @@ PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                          hDevHandle,
                RGXFWIF_KCCB_CMD      sPowCmd;
                IMG_UINT32            ui32CmdKCCBSlot;
 
-               RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
 
                /* Send the Power off request to the FW */
                sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
                sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_OFF_REQ;
-               sPowCmd.uCmdData.sPowData.uPowerReqData.bForced = bForced;
+               sPowCmd.uCmdData.sPowData.uPowerReqData.bForced = BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED);
 
                eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
                if (eError != PVRSRV_OK)
@@ -233,8 +230,9 @@ PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                            hDevHandle,
                                        if (eError != PVRSRV_OK)
                                        {
                                                PVR_DPF((PVR_DBG_ERROR,
-                                                               "%s: Wait for pending interrupts failed." MSG_IRQ_CNT_TYPE " %u Host: %u, FW: %u",
+                                                               "%s: Wait for pending interrupts failed (DevID %u)." MSG_IRQ_CNT_TYPE " %u Host: %u, FW: %u",
                                                                __func__,
+                                                               psDeviceNode->sDevId.ui32InternalID,
                                                                ui32idx,
                                                                psDevInfo->aui32SampleIRQCount[ui32idx],
                                                                ui32IrqCnt));
@@ -251,7 +249,7 @@ PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                            hDevHandle,
                                _RGXUpdateGPUUtilStats(psDevInfo);
 
 #if defined(SUPPORT_LINUX_DVFS)
-                               eError = SuspendDVFS();
+                               eError = SuspendDVFS(psDeviceNode);
                                if (eError != PVRSRV_OK)
                                {
                                        PVR_DPF((PVR_DBG_ERROR, "%s: Failed to suspend DVFS", __func__));
@@ -276,7 +274,7 @@ PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                            hDevHandle,
                                /* the sync was updated but the pow state isn't off -> the FW denied the transition */
                                eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
 
-                               if (bForced)
+                               if (BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED))
                                {       /* It is an error for a forced request to be denied */
                                        PVR_DPF((PVR_DBG_ERROR,
                                                         "%s: Failure to power off during a forced power off. FW: %d",
@@ -318,7 +316,7 @@ static PVRSRV_ERROR _RGXWaitForGuestsToDisconnect(PVRSRV_DEVICE_NODE *psDeviceNo
                for (ui32OSid = RGXFW_GUEST_OSID_START;
                         ui32OSid < RGX_NUM_OS_SUPPORTED; ui32OSid++)
                {
-                       RGXFWIF_CONNECTION_FW_STATE eGuestState = (volatile RGXFWIF_CONNECTION_FW_STATE)
+                       RGXFWIF_CONNECTION_FW_STATE eGuestState = (RGXFWIF_CONNECTION_FW_STATE)
                                        psDevInfo->psRGXFWIfFwSysData->asOsRuntimeFlagsMirror[ui32OSid].bfOsState;
 
                        if ((eGuestState == RGXFW_CONNECTION_FW_ACTIVE) ||
@@ -371,7 +369,7 @@ static PVRSRV_ERROR _RGXWaitForGuestsToDisconnect(PVRSRV_DEVICE_NODE *psDeviceNo
 PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                             hDevHandle,
                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
                                 PVRSRV_DEV_POWER_STATE eCurrentPowerState,
-                                IMG_BOOL                               bForced)
+                                PVRSRV_POWER_FLAGS             ePwrFlags)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
@@ -382,8 +380,7 @@ PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                          hDevHandle,
        {
                /* powering down */
 #if defined(SUPPORT_AUTOVZ)
-               PVR_LOG_RETURN_IF_FALSE((!psDeviceNode->bAutoVzFwIsUp), "AutoVz Fw active, power not changed", eError);
-               if (PVRSRV_VZ_MODE_IS(HOST))
+               if (PVRSRV_VZ_MODE_IS(HOST) && (!psDeviceNode->bAutoVzFwIsUp))
                {
                        /* The Host must ensure all Guest drivers have disconnected from the GPU before powering it down.
                         * Guest drivers regularly access hardware registers during runtime. If an attempt is made to
@@ -401,43 +398,16 @@ PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                                hDevHandle,
                                                                        psDeviceNode->psDevConfig->pfnPostPowerState,
                                                                        &RGXForcedIdleRequest, &RGXCancelForcedIdleRequest);
                }
-               else if (PVRSRV_VZ_MODE_IS(GUEST))
+               else
                {
                        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-                       IMG_BOOL bFwOffline = IMG_FALSE;
-                       RGXFWIF_KCCB_CMD sOfflineCmd = { 0 };
-
-                       sOfflineCmd.eCmdType = RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE;
-                       sOfflineCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = RGXFWIF_OS_OFFLINE;
 
-                       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+                       if (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) &&
+                               KM_OS_CONNECTION_IS(ACTIVE, psDevInfo))
                        {
-                               /* Update the watchdog token to prevent the firmware from resetting this driver's
-                                * state to READY. It needs to stay OFFLINE until the driver can confirm it. */
-                               KM_SET_OS_ALIVE_TOKEN(KM_GET_FW_ALIVE_TOKEN(psDevInfo), psDevInfo);
-
-                               eError = RGXSendCommandAndGetKCCBSlot(psDevInfo, &sOfflineCmd, PDUMP_FLAGS_CONTINUOUS, NULL);
-                               if (eError != PVRSRV_ERROR_RETRY) break;
-
-                               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
-                       } END_LOOP_UNTIL_TIMEOUT();
-
-                       if (eError == PVRSRV_OK)
-                       {
-                               LOOP_UNTIL_TIMEOUT(SECONDS_TO_MICROSECONDS)
-                               {
-                                       if (KM_FW_CONNECTION_IS(OFFLINE, psDevInfo))
-                                       {
-                                               bFwOffline = IMG_TRUE;
-                                               break;
-                                       }
-                               } END_LOOP_UNTIL_TIMEOUT();
-                       }
-
-                       if (!bFwOffline)
-                       {
-                               /* The firmware failed to take down the connection, break it from the driver's end as a last resort. */
-                               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+                               PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+                               PVRSRV_ERROR eError = RGXFWSetFwOsState(psDevInfo, 0, RGXFWIF_OS_OFFLINE);
+                               PVR_LOG_RETURN_IF_ERROR(eError, "RGXFWSetFwOsState");
                        }
                }
 #endif
@@ -457,7 +427,7 @@ PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                          hDevHandle,
        if (!(PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp)))
        {
                /* call regular device power function */
-               eError = RGXPrePowerState(hDevHandle, eNewPowerState, eCurrentPowerState, bForced);
+               eError = RGXPrePowerState(hDevHandle, eNewPowerState, eCurrentPowerState, ePwrFlags);
        }
 
        return eError;
@@ -469,7 +439,7 @@ PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                          hDevHandle,
 PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                            hDevHandle,
                                  PVRSRV_DEV_POWER_STATE        eNewPowerState,
                                  PVRSRV_DEV_POWER_STATE        eCurrentPowerState,
-                                 IMG_BOOL                              bForced)
+                                 PVRSRV_POWER_FLAGS            ePwrFlags)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
        PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
@@ -480,7 +450,7 @@ PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                         hDevHandle,
        if (!(PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp)))
        {
                /* call regular device power function */
-               eError = RGXPostPowerState(hDevHandle, eNewPowerState, eCurrentPowerState, bForced);
+               eError = RGXPostPowerState(hDevHandle, eNewPowerState, eCurrentPowerState, ePwrFlags);
        }
 
        if (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)
@@ -608,22 +578,24 @@ PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                               hDevHandle,
 #if defined(TRACK_FW_BOOT)
 static INLINE void RGXCheckFWBootStage(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        FW_BOOT_STAGE eStage;
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
                /* Boot stage temporarily stored to the register below */
                eStage = OSReadHWReg32(psDevInfo->pvRegsBaseKM,
                                       RGX_FW_BOOT_STAGE_REGISTER);
        }
-       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       else
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
        {
                eStage = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_SCRATCH14);
        }
        else
+#endif
        {
                IMG_BYTE *pbBootData;
 
@@ -635,17 +607,6 @@ static INLINE void RGXCheckFWBootStage(PVRSRV_RGXDEV_INFO *psDevInfo)
                }
                else
                {
-#ifdef CACHE_TEST
-                       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWDataMemDesc;
-                       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-                       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-                       {
-                               printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                               BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pbBootData - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-                       }
-#endif
-
-               
                        pbBootData += RGXGetFWImageSectionOffset(NULL, MIPS_BOOT_DATA);
 
                        eStage = *(FW_BOOT_STAGE*)&pbBootData[RGXMIPSFW_BOOT_STAGE_OFFSET];
@@ -703,114 +664,57 @@ static INLINE PVRSRV_ERROR RGXDoStart(PVRSRV_DEVICE_NODE *psDeviceNode)
 #if defined(NO_HARDWARE) && defined(PDUMP)
 
 #if 0
-#include "rgxtbdefs.h"
+#include "emu_cr_defs.h"
 #else
-
-/*
-    Register RGX_TB_SYSTEM_STATUS
-*/
-#define RGX_TB_SYSTEM_STATUS                              (0x00E0U)
-#define RGX_TB_SYSTEM_STATUS_MASKFULL                     (IMG_UINT64_C(0x00000000030100FF))
-/*
-directly indicates the status of power_abort flag from the power management controller (RGX_PRCM)
-*/
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_ABORT_SHIFT (25U)
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_ABORT_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFDFFFFFF))
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_ABORT_EN    (IMG_UINT64_C(0X0000000002000000))
-/*
-directly indicates the status of power_complete flag from the power management controller (RGX_PRCM)
-*/
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_COMPLETE_SHIFT (24U)
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_COMPLETE_CLRMSK (IMG_UINT64_C(0XFFFFFFFFFEFFFFFF))
-#define RGX_TB_SYSTEM_STATUS_HOST_POWER_EVENT_COMPLETE_EN (IMG_UINT64_C(0X0000000001000000))
-/*
-directly indicates the status of GPU's hmmu_irq
-*/
-#define RGX_TB_SYSTEM_STATUS_HMMU_IRQ_SHIFT               (16U)
-#define RGX_TB_SYSTEM_STATUS_HMMU_IRQ_CLRMSK              (IMG_UINT64_C(0XFFFFFFFFFFFEFFFF))
-#define RGX_TB_SYSTEM_STATUS_HMMU_IRQ_EN                  (IMG_UINT64_C(0X0000000000010000))
-/*
-directly indicates the status of GPU's irq per OS_ID
-*/
-#define RGX_TB_SYSTEM_STATUS_IRQ_SHIFT                    (1U)
-#define RGX_TB_SYSTEM_STATUS_IRQ_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFFFE01))
-/*
-old deprecated single irq
-*/
-#define RGX_TB_SYSTEM_STATUS_OLD_IRQ_SHIFT                    (0U)
-#define RGX_TB_SYSTEM_STATUS_OLD_IRQ_CLRMSK                   (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
+#define EMU_CR_SYSTEM_IRQ_STATUS                          (0x00E0U)
+/* IRQ is officially defined [8 .. 0] but here we split out the old deprecated single irq. */
+#define EMU_CR_SYSTEM_IRQ_STATUS_IRQ_CLRMSK               (IMG_UINT64_C(0XFFFFFFFFFFFFFE01))
+#define EMU_CR_SYSTEM_IRQ_STATUS_OLD_IRQ_CLRMSK           (IMG_UINT64_C(0XFFFFFFFFFFFFFFFE))
 #endif
 
 static PVRSRV_ERROR
 _ValidateIrqs(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        IMG_UINT32 ui32OSid;
-       IMG_UINT32 ui32ConfigFlags;
        PDUMP_FLAGS_T ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
 
-       {
-               PVRSRV_ERROR eError;
-               RGXFWIF_SYSDATA *psFwSysData;
-
-               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfFwSysDataMemDesc, (void **)&psFwSysData);
-               if (eError != PVRSRV_OK)
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                       "%s: Failed to acquire OS Config (%u)",
-                                       __func__,
-                                       eError));
-                       return eError;
-               }
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWIfFwSysDataMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFwSysData - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-               }
-#endif
-
-               ui32ConfigFlags = psFwSysData->ui32ConfigFlags;
-
-               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfFwSysDataMemDesc);
-       }
-
        /* Check if the Validation IRQ flag is set */
-       if ((ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_IRQ) == 0)
+       if ((psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_IRQ) == 0)
        {
                return PVRSRV_OK;
        }
 
-       PDUMPIF("IMG_PVR_TESTBENCH", ui32PDumpFlags);
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for TB irq status to be set (irqs signalled)...");
-       PDUMPREGPOL(RGX_TB_PDUMPREG_NAME,
-                   RGX_TB_SYSTEM_STATUS,
-                               ~RGX_TB_SYSTEM_STATUS_IRQ_CLRMSK,
-                               ~RGX_TB_SYSTEM_STATUS_IRQ_CLRMSK,
-                               ui32PDumpFlags,
-                               PDUMP_POLL_OPERATOR_EQUAL);
-
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "... and then clear them");
+       PDUMPIF(psDevInfo->psDeviceNode, "IMG_PVR_TESTBENCH", ui32PDumpFlags);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Poll for TB irq status to be set (irqs signalled)...");
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_TB_PDUMPREG_NAME,
+                   EMU_CR_SYSTEM_IRQ_STATUS,
+                   ~EMU_CR_SYSTEM_IRQ_STATUS_IRQ_CLRMSK,
+                   ~EMU_CR_SYSTEM_IRQ_STATUS_IRQ_CLRMSK,
+                   ui32PDumpFlags,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "... and then clear them");
        for (ui32OSid = 0; ui32OSid < RGXFW_MAX_NUM_OS; ui32OSid++)
        {
-               PDUMPREG32(RGX_PDUMPREG_NAME,
+               PDUMPREG32(psDevInfo->psDeviceNode,
+                          RGX_PDUMPREG_NAME,
                           RGX_CR_IRQ_OS0_EVENT_CLEAR + ui32OSid * 0x10000,
                           RGX_CR_IRQ_OS0_EVENT_CLEAR_MASKFULL,
                           ui32PDumpFlags);
        }
 
-       PDUMPFI("IMG_PVR_TESTBENCH", ui32PDumpFlags);
+       PDUMPFI(psDevInfo->psDeviceNode, "IMG_PVR_TESTBENCH", ui32PDumpFlags);
 
        /* Poll on all the interrupt status registers for all OSes */
-       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Validate Interrupt lines.");
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Validate Interrupt lines.");
 
        for (ui32OSid = 0; ui32OSid < RGXFW_MAX_NUM_OS; ui32OSid++)
        {
-               PDUMPREGPOL(RGX_PDUMPREG_NAME,
+               PDUMPREGPOL(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
                            RGX_CR_IRQ_OS0_EVENT_STATUS + ui32OSid * 0x10000,
                            0x0,
                            0xFFFFFFFF,
@@ -851,12 +755,7 @@ static PVRSRV_ERROR RGXVirtualisationPowerupSidebandTest(PVRSRV_DEVICE_NODE         *ps
 
        PVR_DPF((PVR_DBG_MESSAGE, "Testing per-os kick registers:"));
 
-       /* Need to get the maximum supported OSid value from the per-device info.
-        * This can change according to how much memory is physically present and
-        * what the carve-out mapping looks like (provided by the module load-time
-        * parameters).
-        */
-       ui32OsRegBanksMapped = MIN(ui32OsRegBanksMapped, psDeviceNode->ui32NumOSId);
+       ui32OsRegBanksMapped = MIN(ui32OsRegBanksMapped, GPUVIRT_VALIDATION_NUM_OS);
 
        if (ui32OsRegBanksMapped != RGXFW_MAX_NUM_OS)
        {
@@ -871,9 +770,16 @@ static PVRSRV_ERROR RGXVirtualisationPowerupSidebandTest(PVRSRV_DEVICE_NODE         *ps
        {
                /* set Test field */
                psFwSysInit->ui32OSKickTest = (ui32OSid << RGXFWIF_KICK_TEST_OSID_SHIFT) | RGXFWIF_KICK_TEST_ENABLED_BIT;
+
+#if defined(PDUMP)
+               DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                  offsetof(RGXFWIF_SYSINIT, ui32OSKickTest),
+                                                  sizeof(psFwSysInit->ui32OSKickTest),
+                                                  PDUMP_FLAGS_CONTINUOUS);
+#endif
+
                /* Force a read-back to memory to avoid posted writes on certain buses */
-               (void) psFwSysInit->ui32OSKickTest;
-               OSWriteMemoryBarrier();
+               OSWriteMemoryBarrier(&psFwSysInit->ui32OSKickTest);
 
                /* kick register */
                ui32ScheduleRegister = RGX_CR_MTS_SCHEDULE + (ui32OSid * RGX_VIRTUALISATION_REG_SIZE_PER_OS);
@@ -881,7 +787,21 @@ static PVRSRV_ERROR RGXVirtualisationPowerupSidebandTest(PVRSRV_DEVICE_NODE         *ps
                                 ui32OSid,
                                 ui32ScheduleRegister));
                OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32ScheduleRegister, ui32KickType);
-               OSMemoryBarrier();
+               OSMemoryBarrier((IMG_BYTE*) psDevInfo->pvRegsBaseKM + ui32ScheduleRegister);
+
+#if defined(PDUMP)
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "VZ sideband test, kicking MTS register %u", ui32OSid);
+
+               PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME,
+                               ui32ScheduleRegister, ui32KickType, PDUMP_FLAGS_CONTINUOUS);
+
+               DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                          offsetof(RGXFWIF_SYSINIT, ui32OSKickTest),
+                                                          0,
+                                                          0xFFFFFFFF,
+                                                          PDUMP_POLL_OPERATOR_EQUAL,
+                                                          PDUMP_FLAGS_CONTINUOUS);
+#endif
 
                /* Wait test enable bit to be unset */
                if (PVRSRVPollForValueKM(psDeviceNode,
@@ -919,9 +839,6 @@ static PVRSRV_ERROR RGXVirtualisationPowerupSidebandTest(PVRSRV_DEVICE_NODE  *ps
 
 static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        void *pvAppHintState = NULL;
        IMG_UINT32 ui32AppHintDefault = 0;
        IMG_BOOL bRunRiscvDmiTest;
@@ -930,7 +847,7 @@ static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
        PVRSRV_ERROR eError;
 
        OSCreateKMAppHintState(&pvAppHintState);
-       OSGetKMAppHintBOOL(pvAppHintState, RiscvDmiTest,
+       OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, RiscvDmiTest,
                           &ui32AppHintDefault, &bRunRiscvDmiTest);
        OSFreeKMAppHintState(pvAppHintState);
 
@@ -948,18 +865,9 @@ static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
                         __func__,
                         PVRSRVGetErrorString(eError)));
        }
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWCodeMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pui32FWCode - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
 
-       PDumpIfKM("ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "DMI_TEST BEGIN");
+       PDumpIfKM(psDevInfo->psDeviceNode, "ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "DMI_TEST BEGIN");
 
        RGXRiscvHalt(psDevInfo);
 
@@ -992,13 +900,13 @@ static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
                ui32Tmp = *pui32FWCode;
 
                /* Write FW code at address (bootloader) */
-               RGXRiscvWriteMem(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     SCRATCH_VALUE);
+               RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     SCRATCH_VALUE);
                /* Read FW code at address (bootloader + 4) (compare against value read from Host) */
                RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_BOOTLDR_CODE_BASE + 4, *(pui32FWCode + 1));
                /* Read FW code at address (bootloader) (compare against previously written value) */
                RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_BOOTLDR_CODE_BASE,     SCRATCH_VALUE);
                /* Restore FW code at address (bootloader) */
-               RGXRiscvWriteMem(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     ui32Tmp);
+               RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     ui32Tmp);
 
                DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
        }
@@ -1012,19 +920,21 @@ static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
         */
 
        /* Write SCRATCH0 from the Host */
-       PDUMPREG32(RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0, SCRATCH_VALUE, PDUMP_FLAGS_CONTINUOUS);
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0,
+                  SCRATCH_VALUE, PDUMP_FLAGS_CONTINUOUS);
        /* Read SCRATCH0 */
        RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_SOCIF_BASE | RGX_CR_SCRATCH0, SCRATCH_VALUE);
        /* Write SCRATCH0 */
-       RGXRiscvWriteMem(psDevInfo, RGXRISCVFW_SOCIF_BASE | RGX_CR_SCRATCH0, ~SCRATCH_VALUE);
+       RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_SOCIF_BASE | RGX_CR_SCRATCH0, ~SCRATCH_VALUE);
        /* Read SCRATCH0 from the Host */
-       PDUMPREGPOL(RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0, ~SCRATCH_VALUE, 0xFFFFFFFFU,
+       PDUMPREGPOL(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0,
+                   ~SCRATCH_VALUE, 0xFFFFFFFFU,
                    PDUMP_FLAGS_CONTINUOUS, PDUMP_POLL_OPERATOR_EQUAL);
 
        RGXRiscvResume(psDevInfo);
 
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "DMI_TEST END");
-       PDumpFiKM("ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "DMI_TEST END");
+       PDumpFiKM(psDevInfo->psDeviceNode, "ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
 }
 #endif
 
@@ -1034,14 +944,15 @@ static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
 PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                              hDevHandle,
                                PVRSRV_DEV_POWER_STATE  eNewPowerState,
                                PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
-                               IMG_BOOL                                        bForced)
+                               PVRSRV_POWER_FLAGS              ePwrFlags)
 {
+       PVRSRV_DEVICE_NODE       *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO       *psDevInfo = psDeviceNode->pvDevice;
+
        if ((eNewPowerState != eCurrentPowerState) &&
            (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
        {
                PVRSRV_ERROR             eError;
-               PVRSRV_DEVICE_NODE       *psDeviceNode = hDevHandle;
-               PVRSRV_RGXDEV_INFO       *psDevInfo = psDeviceNode->pvDevice;
 
                if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
                {
@@ -1058,7 +969,7 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                          hDevHandle,
                                return eError;
                        }
 
-                       OSMemoryBarrier();
+                       OSMemoryBarrier(NULL);
 
                        /*
                         * Check whether the FW has started by polling on bFirmwareStarted flag
@@ -1090,7 +1001,7 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                         hDevHandle,
                        }
 
 #if defined(PDUMP)
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Wait for the Firmware to start.");
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "Wait for the Firmware to start.");
                        eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfSysInitMemDesc,
                                                        offsetof(RGXFWIF_SYSINIT, bFirmwareStarted),
                                                        IMG_TRUE,
@@ -1136,7 +1047,7 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                         hDevHandle,
                        psDevInfo->bRGXPowered = IMG_TRUE;
 
 #if defined(SUPPORT_LINUX_DVFS)
-                       eError = ResumeDVFS();
+                       eError = ResumeDVFS(psDeviceNode);
                        if (eError != PVRSRV_OK)
                        {
                                PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: Failed to resume DVFS"));
@@ -1146,7 +1057,9 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                         hDevHandle,
                }
        }
 
-       PDUMPCOMMENT("RGXPostPowerState: Current state: %d, New state: %d", eCurrentPowerState, eNewPowerState);
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXPostPowerState: Current state: %d, New state: %d",
+                    eCurrentPowerState, eNewPowerState);
 
        return PVRSRV_OK;
 }
@@ -1157,11 +1070,11 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                               hDevHandle,
 PVRSRV_ERROR RGXPreClockSpeedChange(IMG_HANDLE                         hDevHandle,
                                     PVRSRV_DEV_POWER_STATE     eCurrentPowerState)
 {
-       PVRSRV_ERROR            eError = PVRSRV_OK;
-       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
-       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
-       RGX_DATA                        *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
-       RGXFWIF_SYSDATA         *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       const PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
        PVR_UNREFERENCED_PARAMETER(psRGXData);
 
@@ -1184,17 +1097,18 @@ PVRSRV_ERROR RGXPreClockSpeedChange(IMG_HANDLE                          hDevHandle,
 PVRSRV_ERROR RGXPostClockSpeedChange(IMG_HANDLE                                hDevHandle,
                                      PVRSRV_DEV_POWER_STATE    eCurrentPowerState)
 {
-       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
-       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
-       RGX_DATA                        *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
-       PVRSRV_ERROR            eError = PVRSRV_OK;
-       RGXFWIF_SYSDATA         *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
-       IMG_UINT32                      ui32NewClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
-       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32NewClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
 
        /* Update runtime configuration with the new value */
-       psDevInfo->psRGXFWIfRuntimeCfg->ui32CoreClockSpeed = ui32NewClockSpeed;
-       OSWriteMemoryBarrier();
+       OSWriteDeviceMem32WithWMB(&psDevInfo->psRGXFWIfRuntimeCfg->ui32CoreClockSpeed,
+                                 ui32NewClockSpeed);
 
        if ((eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF) &&
            (psFwSysData->ePowState != RGXFWIF_POW_OFF))
@@ -1207,21 +1121,18 @@ PVRSRV_ERROR RGXPostClockSpeedChange(IMG_HANDLE                         hDevHandle,
                sCOREClkSpeedChangeCmd.eCmdType = RGXFWIF_KCCB_CMD_CORECLKSPEEDCHANGE;
                sCOREClkSpeedChangeCmd.uCmdData.sCoreClkSpeedChangeData.ui32NewClockSpeed = ui32NewClockSpeed;
 
-               /* Ensure the new clock speed is written to memory before requesting the FW to read it */
-               OSMemoryBarrier();
-
-               PDUMPCOMMENT("Scheduling CORE clock speed change command");
+               PDUMPCOMMENT(psDeviceNode, "Scheduling CORE clock speed change command");
 
-               PDUMPPOWCMDSTART();
+               PDUMPPOWCMDSTART(psDeviceNode);
                eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
                                                      &sCOREClkSpeedChangeCmd,
                                                      PDUMP_FLAGS_NONE,
                                                      &ui32CmdKCCBSlot);
-               PDUMPPOWCMDEND();
+               PDUMPPOWCMDEND(psDeviceNode);
 
                if (eError != PVRSRV_OK)
                {
-                       PDUMPCOMMENT("Scheduling CORE clock speed change command failed");
+                       PDUMPCOMMENT(psDeviceNode, "Scheduling CORE clock speed change command failed");
                        PVR_DPF((PVR_DBG_ERROR, "RGXPostClockSpeedChange: Scheduling KCCB command failed. Error:%u", eError));
                        return eError;
                }
@@ -1274,11 +1185,11 @@ PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE              hDevHandle,
        }
 
        psRuntimeCfg->ui32DefaultDustsNumInit = ui32NumberOfDusts;
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psRuntimeCfg->ui32DefaultDustsNumInit);
 
 #if !defined(NO_HARDWARE)
        {
-               RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
 
                if (psFwSysData->ePowState == RGXFWIF_POW_OFF)
                {
@@ -1308,7 +1219,9 @@ PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE                hDevHandle,
        sDustCountChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_NUM_UNITS_CHANGE;
        sDustCountChange.uCmdData.sPowData.uPowerReqData.ui32NumOfDusts = ui32NumberOfDusts;
 
-       PDUMPCOMMENT("Scheduling command to change Dust Count to %u", ui32NumberOfDusts);
+       PDUMPCOMMENT(psDeviceNode,
+                    "Scheduling command to change Dust Count to %u",
+                    ui32NumberOfDusts);
        eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
                                              &sDustCountChange,
                                              PDUMP_FLAGS_NONE,
@@ -1316,7 +1229,9 @@ PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE                hDevHandle,
 
        if (eError != PVRSRV_OK)
        {
-               PDUMPCOMMENT("Scheduling command to change Dust Count failed. Error:%u", eError);
+               PDUMPCOMMENT(psDeviceNode,
+                            "Scheduling command to change Dust Count failed. Error:%u",
+                            eError);
                PVR_DPF((PVR_DBG_ERROR,
                                 "%s: Scheduling KCCB to change Dust Count failed. Error:%u",
                                 __func__, eError));
@@ -1335,7 +1250,9 @@ PVRSRV_ERROR RGXDustCountChange(IMG_HANDLE                hDevHandle,
        }
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("RGXDustCountChange: Poll for Kernel SyncPrim [0x%p] on DM %d", psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXDustCountChange: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
 
        SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
                         1,
@@ -1376,7 +1293,7 @@ PVRSRV_ERROR RGXAPMLatencyChange(IMG_HANDLE               hDevHandle,
         */
        psRuntimeCfg->ui32ActivePMLatencyms = ui32ActivePMLatencyms;
        psRuntimeCfg->bActivePMLatencyPersistant = bActivePMLatencyPersistant;
-       OSWriteMemoryBarrier();
+       OSWriteMemoryBarrier(&psRuntimeCfg->bActivePMLatencyPersistant);
 
        eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
 
@@ -1386,7 +1303,9 @@ PVRSRV_ERROR RGXAPMLatencyChange(IMG_HANDLE               hDevHandle,
                sActivePMLatencyChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
                sActivePMLatencyChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_APM_LATENCY_CHANGE;
 
-               PDUMPCOMMENT("Scheduling command to change APM latency to %u", ui32ActivePMLatencyms);
+               PDUMPCOMMENT(psDeviceNode,
+                            "Scheduling command to change APM latency to %u",
+                            ui32ActivePMLatencyms);
                eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
                                                      &sActivePMLatencyChange,
                                                      PDUMP_FLAGS_NONE,
@@ -1394,7 +1313,9 @@ PVRSRV_ERROR RGXAPMLatencyChange(IMG_HANDLE               hDevHandle,
 
                if (eError != PVRSRV_OK)
                {
-                       PDUMPCOMMENT("Scheduling command to change APM latency failed. Error:%u", eError);
+                       PDUMPCOMMENT(psDeviceNode,
+                                   "Scheduling command to change APM latency failed. Error:%u",
+                                   eError);
                        PVR_DPF((PVR_DBG_ERROR, "RGXAPMLatencyChange: Scheduling KCCB to change APM latency failed. Error:%u", eError));
                        goto ErrorExit;
                }
@@ -1414,7 +1335,7 @@ PVRSRV_ERROR RGXActivePowerRequest(IMG_HANDLE hDevHandle)
        PVRSRV_ERROR eError = PVRSRV_OK;
        PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
-       RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
 
@@ -1447,11 +1368,11 @@ PVRSRV_ERROR RGXActivePowerRequest(IMG_HANDLE hDevHandle)
                SetFirmwareHandshakeIdleTime(RGXReadHWTimerReg(psDevInfo)-psFwSysData->ui64StartIdleTime);
 #endif
 
-               PDUMPPOWCMDSTART();
+               PDUMPPOWCMDSTART(psDeviceNode);
                eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
                                                     PVRSRV_DEV_POWER_STATE_OFF,
-                                                    IMG_FALSE); /* forced */
-               PDUMPPOWCMDEND();
+                                                    PVRSRV_POWER_FLAGS_NONE);
+               PDUMPPOWCMDEND(psDeviceNode);
 
                if (eError == PVRSRV_OK)
                {
@@ -1488,7 +1409,7 @@ PVRSRV_ERROR RGXForcedIdleRequest(IMG_HANDLE hDevHandle, IMG_BOOL bDeviceOffPerm
        IMG_UINT32            ui32RetryCount = 0;
        IMG_UINT32            ui32CmdKCCBSlot;
 #if !defined(NO_HARDWARE)
-       RGXFWIF_SYSDATA *psFwSysData;
+       const RGXFWIF_SYSDATA *psFwSysData;
 #endif
        PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
 
@@ -1519,7 +1440,8 @@ PVRSRV_ERROR RGXForcedIdleRequest(IMG_HANDLE hDevHandle, IMG_BOOL bDeviceOffPerm
        sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
        sPowCmd.uCmdData.sPowData.uPowerReqData.ePowRequestType = RGXFWIF_POWER_FORCE_IDLE;
 
-       PDUMPCOMMENT("RGXForcedIdleRequest: Sending forced idle command");
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Sending forced idle command");
 
        /* Send one forced IDLE command to GP */
        eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
@@ -1558,7 +1480,9 @@ PVRSRV_ERROR RGXForcedIdleRequest(IMG_HANDLE hDevHandle, IMG_BOOL bDeviceOffPerm
        }
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("RGXForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d", psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
 
        SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
                         1,
@@ -1603,7 +1527,8 @@ PVRSRV_ERROR RGXCancelForcedIdleRequest(IMG_HANDLE hDevHandle)
        sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
        sPowCmd.uCmdData.sPowData.uPowerReqData.ePowRequestType = RGXFWIF_POWER_CANCEL_FORCED_IDLE;
 
-       PDUMPCOMMENT("RGXForcedIdleRequest: Sending cancel forced idle command");
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Sending cancel forced idle command");
 
        /* Send cancel forced IDLE command to GP */
        eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
@@ -1613,7 +1538,9 @@ PVRSRV_ERROR RGXCancelForcedIdleRequest(IMG_HANDLE hDevHandle)
 
        if (eError != PVRSRV_OK)
        {
-               PDUMPCOMMENT("RGXCancelForcedIdleRequest: Failed to send cancel IDLE request for DM%d", RGXFWIF_DM_GP);
+               PDUMPCOMMENT(psDeviceNode,
+                            "RGXCancelForcedIdleRequest: Failed to send cancel IDLE request for DM%d",
+                            RGXFWIF_DM_GP);
                goto ErrorExit;
        }
 
@@ -1629,7 +1556,9 @@ PVRSRV_ERROR RGXCancelForcedIdleRequest(IMG_HANDLE hDevHandle)
        }
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("RGXCancelForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d", psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXCancelForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
 
        SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
                         1,
index fafef15..a6cd3f2 100644 (file)
@@ -69,7 +69,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                               hDevHandle,
                                                          PVRSRV_DEV_POWER_STATE        eNewPowerState,
                                                          PVRSRV_DEV_POWER_STATE        eCurrentPowerState,
-                                                         IMG_BOOL                                      bForced);
+                                                         PVRSRV_POWER_FLAGS            ePwrFlags);
 
 /*!
 ******************************************************************************
@@ -90,7 +90,7 @@ PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                              hDevHandle,
 PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                              hDevHandle,
                                                           PVRSRV_DEV_POWER_STATE       eNewPowerState,
                                                           PVRSRV_DEV_POWER_STATE       eCurrentPowerState,
-                                                          IMG_BOOL                                     bForced);
+                                                          PVRSRV_POWER_FLAGS           ePwrFlags);
 
 /*!
 ******************************************************************************
@@ -111,7 +111,7 @@ PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                           hDevHandle,
 PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                             hDevHandle,
                                                                PVRSRV_DEV_POWER_STATE  eNewPowerState,
                                                                PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
-                                                               IMG_BOOL                                bForced);
+                                                               PVRSRV_POWER_FLAGS              ePwrFlags);
 
 /*!
 ******************************************************************************
@@ -132,7 +132,7 @@ PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                          hDevHandle,
 PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                            hDevHandle,
                                                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
                                                                 PVRSRV_DEV_POWER_STATE eCurrentPowerState,
-                                                                IMG_BOOL                               bForced);
+                                                                PVRSRV_POWER_FLAGS             ePwrFlags);
 
 /*!
 ******************************************************************************
index f6d06ca..6025614 100644 (file)
@@ -56,6 +56,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pdump_km.h"
 
 #include "rgxinit.h"
+#include "rgxmulticore.h"
 
 #include "rgx_compat_bvnc.h"
 
@@ -82,10 +83,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "pvrsrv.h"
 
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
-
 #if defined(SUPPORT_TRUSTED_DEVICE)
 #include "rgxdevice.h"
 #include "pvrsrv_device.h"
@@ -96,6 +93,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define        HW_PERF_FILTER_DEFAULT         0x00000000 /* Default to no HWPerf */
 #define HW_PERF_FILTER_DEFAULT_ALL_ON  0xFFFFFFFF /* All events */
 
+/* Kernel CCB size */
+
+#if !defined(PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE)
+#define PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE 4
+#endif
+#if !defined(PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE)
+#define PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE 16
+#endif
+
+#if PVRSRV_APPHINT_KCCB_SIZE_LOG2 < PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE
+#error PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too low.
+#elif PVRSRV_APPHINT_KCCB_SIZE_LOG2 > PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE
+#error PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too high.
+#endif
+
 #if defined(SUPPORT_VALIDATION)
 #include "pvrsrv_apphint.h"
 #endif
@@ -158,11 +170,15 @@ typedef struct _RGX_SRVINIT_APPHINTS_
        IMG_BOOL   bAssertOnOutOfMem;
 #if defined(SUPPORT_VALIDATION)
        IMG_BOOL   bValidateIrq;
+       IMG_BOOL   bValidateSOCUSCTimer;
 #endif
        IMG_BOOL   bAssertOnHWRTrigger;
 #if defined(SUPPORT_VALIDATION)
        IMG_UINT32 aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_LAST];
        IMG_UINT32 ui32FBCDCVersionOverride;
+       IMG_UINT32 ui32TFBCCompressionControlGroup;
+       IMG_UINT32 ui32TFBCCompressionControlScheme;
+       IMG_BOOL   bTFBCCompressionControlYUVFormat;
 #endif
        IMG_BOOL   bCheckMlist;
        IMG_BOOL   bDisableClockGating;
@@ -177,7 +193,7 @@ typedef struct _RGX_SRVINIT_APPHINTS_
        IMG_BOOL   bZeroFreelist;
        IMG_UINT32 ui32EnableFWContextSwitch;
        IMG_UINT32 ui32FWContextSwitchProfile;
-       IMG_UINT32 ui32VDMContextSwitchMode;
+
        IMG_UINT32 ui32HWPerfFWBufSize;
        IMG_UINT32 ui32HWPerfHostBufSize;
        IMG_UINT32 ui32HWPerfFilter0;
@@ -217,69 +233,99 @@ static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHIN
        void *pvParamState = SrvInitParamOpen();
        IMG_UINT32 ui32ParamTemp;
        IMG_BOOL bS7TopInfra = IMG_FALSE, bE42290 = IMG_FALSE, bTPUFiltermodeCtrl = IMG_FALSE;
-       IMG_BOOL bE42606 = IMG_FALSE, bAXIACELite = IMG_FALSE;
+       IMG_BOOL bE42606 = IMG_FALSE;
+#if defined(EMULATOR)
+       IMG_BOOL bAXIACELite = IMG_FALSE;
+#endif
 
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_TOP_INFRASTRUCTURE))
        {
                bS7TopInfra = IMG_TRUE;
        }
-
+#endif
+#if defined(RGX_FEATURE_TPU_FILTERING_MODE_CONTROL_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TPU_FILTERING_MODE_CONTROL))
        {
                bTPUFiltermodeCtrl = IMG_TRUE;
        }
-
+#endif
+#if defined(HW_ERN_42290_BIT_MASK)
        if (RGX_IS_ERN_SUPPORTED(psDevInfo, 42290))
        {
                bE42290 = IMG_TRUE;
        }
-
+#endif
+#if defined(HW_ERN_42606_BIT_MASK)
        if (RGX_IS_ERN_SUPPORTED(psDevInfo, 42606))
        {
                bE42606 = IMG_TRUE;
        }
-
+#endif
+#if defined(HW_FEATURE_AXI_ACELITE_BIT_MASK) && defined(EMULATOR)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, AXI_ACELITE))
        {
                bAXIACELite = IMG_TRUE;
        }
+#endif
 
        /*
         * NB AppHints initialised to a default value via SrvInitParamInit* macros above
         */
-       SrvInitParamGetUINT32(pvParamState,   DriverMode, psHints->ui32DriverMode);
-       SrvInitParamGetBOOL(pvParamState,     GPUUnitsPowerChange, psHints->bGPUUnitsPowerChange);
-       SrvInitParamGetBOOL(pvParamState,     EnableSignatureChecks, psHints->bEnableSignatureChecks);
-       SrvInitParamGetUINT32(pvParamState,   SignatureChecksBufSize, psHints->ui32SignatureChecksBufSize);
-
-       SrvInitParamGetBOOL(pvParamState,    AssertOutOfMemory, psHints->bAssertOnOutOfMem);
-       SrvInitParamGetBOOL(pvParamState,    AssertOnHWRTrigger, psHints->bAssertOnHWRTrigger);
-       SrvInitParamGetBOOL(pvParamState,    CheckMList, psHints->bCheckMlist);
-       SrvInitParamGetBOOL(pvParamState,    DisableClockGating, psHints->bDisableClockGating);
-       SrvInitParamGetBOOL(pvParamState,    DisableDMOverlap, psHints->bDisableDMOverlap);
-       SrvInitParamGetBOOL(pvParamState,    DisableFEDLogging, psHints->bDisableFEDLogging);
-       SrvInitParamGetUINT32(pvParamState,  EnableAPM, ui32ParamTemp);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    DriverMode,                         psHints->ui32DriverMode);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    GPUUnitsPowerChange,          psHints->bGPUUnitsPowerChange);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    EnableSignatureChecks,      psHints->bEnableSignatureChecks);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    SignatureChecksBufSize, psHints->ui32SignatureChecksBufSize);
+
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    AssertOutOfMemory,               psHints->bAssertOnOutOfMem);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    AssertOnHWRTrigger,            psHints->bAssertOnHWRTrigger);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    CheckMList,                            psHints->bCheckMlist);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    DisableClockGating,            psHints->bDisableClockGating);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    DisableDMOverlap,                psHints->bDisableDMOverlap);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    DisableFEDLogging,              psHints->bDisableFEDLogging);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,  pvParamState,    EnableAPM,                                    ui32ParamTemp);
        psHints->eRGXActivePMConf = ui32ParamTemp;
-       SrvInitParamGetBOOL(pvParamState,    EnableCDMKillingRandMode, psHints->bEnableCDMKillRand);
-       SrvInitParamGetBOOL(pvParamState,    EnableRandomContextSwitch, psHints->bEnableRandomCsw);
-       SrvInitParamGetBOOL(pvParamState,    EnableSoftResetContextSwitch, psHints->bEnableSoftResetCsw);
-       SrvInitParamGetUINT32(pvParamState,  EnableFWContextSwitch, psHints->ui32EnableFWContextSwitch);
-       SrvInitParamGetUINT32(pvParamState,  VDMContextSwitchMode, psHints->ui32VDMContextSwitchMode);
-       SrvInitParamGetUINT32(pvParamState,  EnableRDPowerIsland, ui32ParamTemp);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    EnableCDMKillingRandMode,       psHints->bEnableCDMKillRand);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    EnableRandomContextSwitch,        psHints->bEnableRandomCsw);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    EnableSoftResetContextSwitch,  psHints->bEnableSoftResetCsw);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    EnableFWContextSwitch,   psHints->ui32EnableFWContextSwitch);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    EnableRDPowerIsland,                          ui32ParamTemp);
        psHints->eRGXRDPowerIslandConf = ui32ParamTemp;
-       SrvInitParamGetUINT32(pvParamState,  FirmwarePerf, ui32ParamTemp);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    FirmwarePerf,                                 ui32ParamTemp);
        psHints->eFirmwarePerf = ui32ParamTemp;
-       SrvInitParamGetUINT32(pvParamState,  FWContextSwitchProfile, psHints->ui32FWContextSwitchProfile);
-       SrvInitParamGetBOOL(pvParamState,    HWPerfDisableCustomCounterFilter, psHints->bHWPerfDisableCustomCounterFilter);
-       SrvInitParamGetUINT32(pvParamState,  HWPerfHostBufSizeInKB, psHints->ui32HWPerfHostBufSize);
-       SrvInitParamGetUINT32(pvParamState,  HWPerfFWBufSizeInKB, psHints->ui32HWPerfFWBufSize);
-       SrvInitParamGetUINT32(pvParamState,  KernelCCBSizeLog2, psHints->ui32KCCBSizeLog2);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    FWContextSwitchProfile, psHints->ui32FWContextSwitchProfile);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,
+               HWPerfDisableCustomCounterFilter, psHints->bHWPerfDisableCustomCounterFilter);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    HWPerfHostBufSizeInKB,       psHints->ui32HWPerfHostBufSize);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    HWPerfFWBufSizeInKB,           psHints->ui32HWPerfFWBufSize);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,  pvParamState,    KernelCCBSizeLog2,                psHints->ui32KCCBSizeLog2);
+
+       if (psHints->ui32KCCBSizeLog2 < PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "KCCB size %u is too low, setting to %u",
+                        psHints->ui32KCCBSizeLog2, PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE));
+               psHints->ui32KCCBSizeLog2 = PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE;
+       }
+       else if (psHints->ui32KCCBSizeLog2 > PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "KCCB size %u is too high, setting to %u",
+                        psHints->ui32KCCBSizeLog2, PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE));
+               psHints->ui32KCCBSizeLog2 = PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       if (psHints->ui32KCCBSizeLog2 != PVRSRV_APPHINT_KCCB_SIZE_LOG2)
+       {
+               PVR_LOG(("KernelCCBSizeLog2 set to %u", psHints->ui32KCCBSizeLog2));
+       }
+#endif
+
 #if defined(__linux__)
        /* name changes */
        {
                IMG_UINT64 ui64Tmp;
-               SrvInitParamGetBOOL(pvParamState,    DisablePDumpPanic, psHints->bDisablePDP);
-               SrvInitParamGetUINT64(pvParamState,  HWPerfFWFilter, ui64Tmp);
+               SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    DisablePDumpPanic, psHints->bDisablePDP);
+               SrvInitParamGetUINT64(psDevInfo->psDeviceNode,  pvParamState,    HWPerfFWFilter,                 ui64Tmp);
                psHints->ui32HWPerfFilter0 = (IMG_UINT32)(ui64Tmp & 0xffffffffllu);
                psHints->ui32HWPerfFilter1 = (IMG_UINT32)((ui64Tmp >> 32) & 0xffffffffllu);
        }
@@ -288,9 +334,9 @@ static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHIN
        SrvInitParamUnreferenced(HWPerfFWFilter);
        SrvInitParamUnreferenced(RGXBVNC);
 #endif
-       SrvInitParamGetUINT32(pvParamState, HWPerfHostFilter, psHints->ui32HWPerfHostFilter);
-       SrvInitParamGetUINT32List(pvParamState, TimeCorrClock, psHints->ui32TimeCorrClock);
-       SrvInitParamGetUINT32(pvParamState, HWRDebugDumpLimit, ui32ParamTemp);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,      pvParamState,    HWPerfHostFilter, psHints->ui32HWPerfHostFilter);
+       SrvInitParamGetUINT32List(psDevInfo->psDeviceNode,  pvParamState,    TimeCorrClock,       psHints->ui32TimeCorrClock);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,      pvParamState,    HWRDebugDumpLimit,                ui32ParamTemp);
        psHints->ui32HWRDebugDumpLimit = MIN(ui32ParamTemp, RGXFWIF_HWR_DEBUG_DUMP_ALL);
 
        if (bS7TopInfra)
@@ -299,7 +345,7 @@ static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHIN
        #define RGX_CR_JONES_FIX_MT_ORDER_ISP_EN        (0X00000020U)
        #define RGX_CR_JONES_FIX_MT_ORDER_TE_EN         (0X00000010U)
 
-               SrvInitParamGetUINT32(pvParamState,  JonesDisableMask, ui32ParamTemp);
+               SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    JonesDisableMask,                 ui32ParamTemp);
                if (((ui32ParamTemp & ~RGX_CR_JONES_FIX_MT_ORDER_ISP_TE_CLRMSK) == RGX_CR_JONES_FIX_MT_ORDER_ISP_EN) ||
                        ((ui32ParamTemp & ~RGX_CR_JONES_FIX_MT_ORDER_ISP_TE_CLRMSK) == RGX_CR_JONES_FIX_MT_ORDER_TE_EN))
                {
@@ -313,40 +359,44 @@ static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHIN
 
        if ((bE42290) && (bTPUFiltermodeCtrl))
        {
-               SrvInitParamGetBOOL(pvParamState, NewFilteringMode, psHints->bFilteringMode);
+               SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    NewFilteringMode,       psHints->bFilteringMode);
        }
 
        if (bE42606)
        {
-               SrvInitParamGetUINT32(pvParamState, TruncateMode, psHints->ui32TruncateMode);
+               SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,      pvParamState,    TruncateMode,         psHints->ui32TruncateMode);
        }
 #if defined(EMULATOR)
        if (bAXIACELite)
        {
-               SrvInitParamGetBOOL(pvParamState, EnableTrustedDeviceAceConfig, psHints->bEnableTrustedDeviceAceConfig);
+               SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,        pvParamState,    EnableTrustedDeviceAceConfig, psHints->bEnableTrustedDeviceAceConfig);
        }
 #endif
 
-       SrvInitParamGetBOOL(pvParamState, ZeroFreelist, psHints->bZeroFreelist);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,        pvParamState,    ZeroFreelist,                        psHints->bZeroFreelist);
 
 #if defined(__linux__)
-       SrvInitParamGetUINT32(pvParamState, FWContextSwitchCrossDM, psHints->ui32FWContextSwitchCrossDM);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    FWContextSwitchCrossDM, psHints->ui32FWContextSwitchCrossDM);
 #else
        SrvInitParamUnreferenced(FWContextSwitchCrossDM);
 #endif
 
 #if defined(SUPPORT_PHYSMEM_TEST) && !defined(INTEGRITY_OS) && !defined(__QNXNTO__)
-       SrvInitParamGetUINT32(pvParamState, PhysMemTestPasses, psHints->ui32PhysMemTestPasses);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    PhysMemTestPasses,           psHints->ui32PhysMemTestPasses);
 #endif
 
 #if defined(SUPPORT_VALIDATION)
        /* Apphints for TPU trilinear frac masking */
-       SrvInitParamGetUINT32(pvParamState, TPUTrilinearFracMaskPDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_PDM]);
-       SrvInitParamGetUINT32(pvParamState, TPUTrilinearFracMaskVDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_VDM]);
-       SrvInitParamGetUINT32(pvParamState, TPUTrilinearFracMaskCDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_CDM]);
-       SrvInitParamGetUINT32(pvParamState, TPUTrilinearFracMaskTDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_TDM]);
-       SrvInitParamGetBOOL(pvParamState,   ValidateIrq, psHints->bValidateIrq);
-       SrvInitParamGetUINT32(pvParamState, FBCDCVersionOverride, psHints->ui32FBCDCVersionOverride);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TPUTrilinearFracMaskPDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_PDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TPUTrilinearFracMaskVDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_VDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TPUTrilinearFracMaskCDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_CDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TPUTrilinearFracMaskTDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_TDM]);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,    pvParamState,  ValidateIrq,                                              psHints->bValidateIrq);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,    pvParamState,  ValidateSOCUSCTimer,                              psHints->bValidateSOCUSCTimer);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  FBCDCVersionOverride,                         psHints->ui32FBCDCVersionOverride);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TFBCCompressionControlGroup,           psHints->ui32TFBCCompressionControlGroup);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TFBCCompressionControlScheme,         psHints->ui32TFBCCompressionControlScheme);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,  pvParamState,  TFBCCompressionControlYUVFormat,      psHints->bTFBCCompressionControlYUVFormat);
 #endif
 
        /*
@@ -355,8 +405,8 @@ static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHIN
        {
                IMG_UINT32 ui32LogGroup, ui32TraceOrTBI;
 
-               SrvInitParamGetUINT32BitField(pvParamState, EnableLogGroup, ui32LogGroup);
-               SrvInitParamGetUINT32List(pvParamState, FirmwareLogType, ui32TraceOrTBI);
+               SrvInitParamGetUINT32BitField(psDevInfo->psDeviceNode,  pvParamState,    EnableLogGroup,      ui32LogGroup);
+               SrvInitParamGetUINT32List(psDevInfo->psDeviceNode,      pvParamState,    FirmwareLogType,   ui32TraceOrTBI);
 
                /* Defaulting to TRACE */
                BITMASK_SET(ui32LogGroup, RGXFWIF_LOG_TYPE_TRACE);
@@ -398,6 +448,9 @@ static INLINE void GetFWConfigFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
                                     IMG_UINT32 *pui32FWConfigFlagsExt,
                                     IMG_UINT32 *pui32FwOsCfgFlags)
 {
+#if defined(SUPPORT_VALIDATION)
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#endif
        IMG_UINT32 ui32FWConfigFlags = 0;
        IMG_UINT32 ui32FWConfigFlagsExt = 0;
 
@@ -419,9 +472,6 @@ static INLINE void GetFWConfigFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
                ui32FWConfigFlags |= psHints->bEnableSoftResetCsw ? RGXFWIF_INICFG_CTXSWITCH_SRESET_EN : 0;
                ui32FWConfigFlags |= (psHints->ui32HWPerfFilter0 != 0 || psHints->ui32HWPerfFilter1 != 0) ? RGXFWIF_INICFG_HWPERF_EN : 0;
                ui32FWConfigFlags |= psHints->bHWPerfDisableCustomCounterFilter ? RGXFWIF_INICFG_HWP_DISABLE_FILTER : 0;
-               ui32FWConfigFlags |= (psHints->eFirmwarePerf == FW_PERF_CONF_CUSTOM_TIMER) ? RGXFWIF_INICFG_CUSTOM_PERF_TIMER_EN : 0;
-               ui32FWConfigFlags |= (psHints->eFirmwarePerf == FW_PERF_CONF_POLLS) ? RGXFWIF_INICFG_POLL_COUNTERS_EN : 0;
-               ui32FWConfigFlags |= (psHints->ui32VDMContextSwitchMode << RGXFWIF_INICFG_VDM_CTX_STORE_MODE_SHIFT) & RGXFWIF_INICFG_VDM_CTX_STORE_MODE_MASK;
                ui32FWConfigFlags |= (psHints->ui32FWContextSwitchProfile << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT) & RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK;
 
 #if defined(SUPPORT_VALIDATION)
@@ -438,6 +488,32 @@ static INLINE void GetFWConfigFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
                {
                        ui32FWConfigFlags |= psDeviceNode->pfnHasFBCDCVersion31(psDeviceNode) ? RGXFWIF_INICFG_FBCDC_V3_1_EN : 0;
                }
+
+#if defined(SUPPORT_VALIDATION)
+               ui32FWConfigFlags |= psHints->bValidateSOCUSCTimer ? RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER : 0;
+
+               if ((ui32FWConfigFlags & RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER) &&
+                   ((psHints->eRGXActivePMConf != 0) || (psHints->eRGXRDPowerIslandConf != 0)))
+               {
+                       psHints->eRGXActivePMConf = 0;
+                       psHints->eRGXRDPowerIslandConf = 0;
+                       PVR_DPF((PVR_DBG_WARNING, "SoC/USC Timer test needs to run with both EnableAPM and EnableRDPowerIsland disabled.\n"
+                                "Overriding current value for both with new value 0."));
+               }
+
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_LOSSY_37_PERCENT) ||
+                   RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_DELTA_CORRELATION) ||
+                   RGX_IS_FEATURE_SUPPORTED(psDevInfo, TFBC_NATIVE_YUV10))
+               {
+                       ui32FWConfigFlagsExt |=
+                               ((((psHints->ui32TFBCCompressionControlGroup  << RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_SHIFT) &
+                                                                                                                           ~RGX_CR_TFBC_COMPRESSION_CONTROL_GROUP_CONTROL_CLRMSK) |
+                                 ((psHints->ui32TFBCCompressionControlScheme << RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_SHIFT) &
+                                                                                                                           ~RGX_CR_TFBC_COMPRESSION_CONTROL_SCHEME_CLRMSK) |
+                                 ((psHints->bTFBCCompressionControlYUVFormat) ? RGX_CR_TFBC_COMPRESSION_CONTROL_YUV10_OVERRIDE_EN : 0))
+                               << RGXFWIF_INICFG_EXT_TFBC_CONTROL_SHIFT) & RGXFWIF_INICFG_EXT_TFBC_CONTROL_MASK;
+               }
+#endif
        }
 
        *pui32FWConfigFlags    = ui32FWConfigFlags;
@@ -522,7 +598,7 @@ static INLINE void InitDeviceFlags(RGX_SRVINIT_APPHINTS *psHints,
 ******************************************************************************/
 static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
                                         OS_FW_IMAGE *psRGXFW,
-                                        RGX_FW_BOOT_PARAMS *puFWParams)
+                                        PVRSRV_FW_BOOT_PARAMS *puFWParams)
 {
        PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
@@ -541,27 +617,18 @@ static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
        sTDFWParams.pvFirmware       = OSFirmwareData(psRGXFW);
        sTDFWParams.ui32FirmwareSize = OSFirmwareSize(psRGXFW);
 
+#if defined(RGX_FEATURE_META_IDX)
        if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
-               sTDFWParams.uFWP.sMeta.sFWCodeDevVAddr        = puFWParams->sMeta.sFWCodeDevVAddr;
-               sTDFWParams.uFWP.sMeta.sFWDataDevVAddr        = puFWParams->sMeta.sFWDataDevVAddr;
-               sTDFWParams.uFWP.sMeta.sFWCorememCodeDevVAddr = puFWParams->sMeta.sFWCorememCodeDevVAddr;
-               sTDFWParams.uFWP.sMeta.sFWCorememCodeFWAddr   = puFWParams->sMeta.sFWCorememCodeFWAddr;
-               sTDFWParams.uFWP.sMeta.uiFWCorememCodeSize    = puFWParams->sMeta.uiFWCorememCodeSize;
-               sTDFWParams.uFWP.sMeta.sFWCorememDataDevVAddr = puFWParams->sMeta.sFWCorememDataDevVAddr;
-               sTDFWParams.uFWP.sMeta.sFWCorememDataFWAddr   = puFWParams->sMeta.sFWCorememDataFWAddr;
-               sTDFWParams.uFWP.sMeta.ui32NumThreads         = puFWParams->sMeta.ui32NumThreads;
+               sTDFWParams.uFWP.sMeta = puFWParams->sMeta;
        }
-       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
+       else
+#endif
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS))
        {
-               IMG_UINT32 i;
-
-               sTDFWParams.uFWP.sMips.sGPURegAddr  = puFWParams->sMips.sGPURegAddr;
-               sTDFWParams.uFWP.sMips.sFWStackAddr = puFWParams->sMips.sFWStackAddr;
-               sTDFWParams.uFWP.sMips.ui32FWPageTableLog2PageSize = puFWParams->sMips.ui32FWPageTableLog2PageSize;
-               sTDFWParams.uFWP.sMips.ui32FWPageTableNumPages     = puFWParams->sMips.ui32FWPageTableNumPages;
+               sTDFWParams.uFWP.sMips = puFWParams->sMips;
 
-               if (puFWParams->sMips.ui32FWPageTableNumPages > TD_MAX_NUM_MIPS_PAGETABLE_PAGES)
+               if (sTDFWParams.uFWP.sMips.ui32FWPageTableNumPages > TD_MAX_NUM_MIPS_PAGETABLE_PAGES)
                {
                        PVR_DPF((PVR_DBG_ERROR, "%s: Number of page table pages %u greater "
                                         "than what is allowed by the TD interface (%u), FW might "
@@ -569,11 +636,10 @@ static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
                                         puFWParams->sMips.ui32FWPageTableNumPages,
                                         TD_MAX_NUM_MIPS_PAGETABLE_PAGES));
                }
-
-               for (i = 0; i < MIN(RGXMIPSFW_MAX_NUM_PAGETABLE_PAGES, TD_MAX_NUM_MIPS_PAGETABLE_PAGES); i++)
-               {
-                       sTDFWParams.uFWP.sMips.asFWPageTableAddr[i] = puFWParams->sMips.asFWPageTableAddr[i];
-               }
+       }
+       else
+       {
+               sTDFWParams.uFWP.sRISCV = puFWParams->sRISCV;
        }
 
        eError = psDevConfig->pfnTDSendFWImage(psDevConfig->hSysData, &sTDFWParams);
@@ -596,7 +662,7 @@ static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
 
 ******************************************************************************/
 static PVRSRV_ERROR RGXAcquireMipsBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                              RGX_FW_BOOT_PARAMS *puFWParams)
+                                              PVRSRV_FW_BOOT_PARAMS *puFWParams)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice;
        MMU_DEVICEATTRIBS *psFWMMUDevAttrs = psDevInfo->psDeviceNode->psFirmwareMMUDevAttrs;
@@ -637,10 +703,19 @@ static PVRSRV_ERROR RGXAcquireMipsBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
                return PVRSRV_ERROR_INIT_FAILURE;
        }
 
+       /* Confirm page alignment fits in 64-bits */
+       if (psFWMMUDevAttrs->ui32BaseAlign > 63)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid page alignment "
+                        "(psFWMMUDevAttrs->ui32BaseAlign = %u)",
+                        __func__, psFWMMUDevAttrs->ui32BaseAlign));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+
        for (i = 0; i < puFWParams->sMips.ui32FWPageTableNumPages; i++)
        {
                puFWParams->sMips.asFWPageTableAddr[i].uiAddr =
-                       sAddr.uiAddr + i * (1U << psFWMMUDevAttrs->ui32BaseAlign);
+                   sAddr.uiAddr + i * (1ULL << psFWMMUDevAttrs->ui32BaseAlign);
        }
 
        /* MIPS Stack Pointer Physical Address */
@@ -670,9 +745,6 @@ static PVRSRV_ERROR RGXAcquireMipsBootldrData(PVRSRV_DEVICE_NODE *psDeviceNode,
 static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
                                  RGX_SRVINIT_APPHINTS *psHints)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        OS_FW_IMAGE       *psRGXFW = NULL;
        const IMG_BYTE    *pbRGXFirmware = NULL;
 
@@ -692,14 +764,19 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
        IMG_DEVMEM_SIZE_T uiFWCorememDataAllocSize;
        void              *pvFWCorememDataHostAddr = NULL;
 
-       RGX_FW_BOOT_PARAMS uFWParams;
+       PVRSRV_FW_BOOT_PARAMS uFWParams;
        RGX_LAYER_PARAMS sLayerParams;
        PVRSRV_ERROR eError;
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
 
 #if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
-       IMG_BOOL bUseSecureFWData = RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
+       IMG_BOOL bUseSecureFWData =
+#if defined(RGX_FEATURE_META_IDX)
+                                                               RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
+#endif
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
                                    RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR) ||
+#endif
                                    (RGX_IS_FEATURE_SUPPORTED(psDevInfo, MIPS) &&
                                     RGX_GET_FEATURE_VALUE(psDevInfo, PHYS_BUS_WIDTH) > 32);
 #endif
@@ -739,7 +816,7 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
 
        psDevInfo->ui32FWCodeSizeInBytes = uiFWCodeAllocSize;
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
+#if defined(SUPPORT_TRUSTED_DEVICE) && defined(RGX_FEATURE_META_DMA_BIT_MASK)
        /* Disable META core memory allocation unless the META DMA is available */
        if (!RGX_DEVICE_HAS_FEATURE(&sLayerParams, META_DMA))
        {
@@ -812,18 +889,6 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
        {
                eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc, &pvFWCorememDataHostAddr);
                PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", release_corememcode);
-
-#ifdef CACHE_TEST
-               printk("%s...L:%d\n", __FILE__, __LINE__);
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWIfCorememDataStoreMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                       printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                       BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvFWCorememDataHostAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-               }
-#endif
-
        }
 
        /*
@@ -842,7 +907,9 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
                        goto release_fw_allocations;
                }
        }
-       else if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       else
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
        {
                uFWParams.sMeta.sFWCodeDevVAddr = psDevInfo->sFWCodeDevVAddrBase;
                uFWParams.sMeta.sFWDataDevVAddr = psDevInfo->sFWDataDevVAddrBase;
@@ -858,6 +925,7 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
 #endif
        }
        else
+#endif
        {
                uFWParams.sRISCV.sFWCorememCodeDevVAddr = psDevInfo->sFWCorememCodeDevVAddrBase;
                uFWParams.sRISCV.sFWCorememCodeFWAddr   = psDevInfo->sFWCorememCodeFWAddr;
@@ -905,7 +973,8 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
         */
 
 #if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump firmware code image");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Dump firmware code image");
        DevmemPDumpLoadMem(psDevInfo->psRGXFWCodeMemDesc,
                           0,
                           uiFWCodeAllocSize,
@@ -916,7 +985,8 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
        if (!bUseSecureFWData)
 #endif
        {
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump firmware data image");
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Dump firmware data image");
                DevmemPDumpLoadMem(psDevInfo->psRGXFWDataMemDesc,
                                   0,
                                   uiFWDataAllocSize,
@@ -926,7 +996,8 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
 #if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
        if (uiFWCorememCodeAllocSize)
        {
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump firmware coremem code image");
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Dump firmware coremem code image");
                DevmemPDumpLoadMem(psDevInfo->psRGXFWCorememCodeMemDesc,
                                                   0,
                                                   uiFWCorememCodeAllocSize,
@@ -940,7 +1011,8 @@ static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
        if (uiFWCorememDataAllocSize)
 #endif
        {
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Dump firmware coremem data store image");
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Dump firmware coremem data store image");
                DevmemPDumpLoadMem(psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
                                                   0,
                                                   uiFWCorememDataAllocSize,
@@ -964,18 +1036,6 @@ release_corememcode:
 #if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
        if (uiFWCorememCodeAllocSize)
        {
-#ifdef CACHE_TEST
-               printk("%s...L:%d\n", __FILE__, __LINE__);
-
-
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWCorememCodeMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvFWCorememCodeHostAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
        }
 #endif
@@ -987,35 +1047,11 @@ release_data:
        if (!bUseSecureFWData)
 #endif
        {
-#ifdef CACHE_TEST
-               printk("%s...L:%d\n", __FILE__, __LINE__);
-
-
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWDataMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvFWDataHostAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc);
        }
 
 release_code:
 #if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
-#ifdef CACHE_TEST
-       printk("%s...L:%d\n", __FILE__, __LINE__);
-
-
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWCodeMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvFWCodeHostAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-       }
-#endif
        DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
 #endif
 cleanup_initfw:
@@ -1044,9 +1080,13 @@ fw_load_fail:
 
 ******************************************************************************/
 
-static void InitialiseHWPerfCounters(void *pvDevice, DEVMEM_MEMDESC *psHWPerfDataMemDesc, RGXFWIF_HWPERF_CTL *psHWPerfInitDataInt)
+static void InitialiseHWPerfCounters(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     void *pvDevice,
+                                     DEVMEM_MEMDESC *psHWPerfDataMemDesc,
+                                     RGXFWIF_HWPERF_CTL *psHWPerfInitDataInt)
 {
        RGXFWIF_HWPERF_CTL_BLK *psHWPerfInitBlkData;
+       RGXFWIF_HWPERF_DA_BLK *psHWPerfInitDABlkData;
        IMG_UINT32 ui32CntBlkModelLen;
        const RGXFW_HWPERF_CNTBLK_TYPE_MODEL *asCntBlkTypeModel;
        const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc;
@@ -1054,8 +1094,15 @@ static void InitialiseHWPerfCounters(void *pvDevice, DEVMEM_MEMDESC *psHWPerfDat
        RGX_HWPERF_CNTBLK_RT_INFO sCntBlkRtInfo;
 
        ui32CntBlkModelLen = RGXGetHWPerfBlockConfig(&asCntBlkTypeModel);
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "HWPerf Counter Config starts here.");
+
        for (ui32BlkCfgIdx = 0; ui32BlkCfgIdx < ui32CntBlkModelLen; ui32BlkCfgIdx++)
        {
+               IMG_UINT32 uiUnit;
+               IMG_BOOL bDirect;
+
                /* Exit early if this core does not have any of these counter blocks
                 * due to core type/BVNC features.... */
                psBlkTypeDesc = &asCntBlkTypeModel[ui32BlkCfgIdx];
@@ -1067,57 +1114,130 @@ static void InitialiseHWPerfCounters(void *pvDevice, DEVMEM_MEMDESC *psHWPerfDat
                /* Program all counters in one block so those already on may
                 * be configured off and vice-a-versa. */
                for (ui32BlockID = psBlkTypeDesc->ui32CntBlkIdBase;
-                                        ui32BlockID < psBlkTypeDesc->ui32CntBlkIdBase+sCntBlkRtInfo.ui32NumUnits;
-                                        ui32BlockID++)
+                        ui32BlockID < psBlkTypeDesc->ui32CntBlkIdBase+sCntBlkRtInfo.ui32NumUnits;
+                        ui32BlockID++)
                {
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "Unit %d Block : %s",
+                                             ui32BlockID-psBlkTypeDesc->ui32CntBlkIdBase,
+                                             psBlkTypeDesc->pszBlockNameComment);
 
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "Unit %d Block : %s",
-                                             ui32BlockID-psBlkTypeDesc->ui32CntBlkIdBase, psBlkTypeDesc->pszBlockNameComment);
                        /* Get the block configure store to update from the global store of
                         * block configuration. This is used to remember the configuration
-                        * between configurations and core power on in APM */
-                       psHWPerfInitBlkData = rgxfw_hwperf_get_block_ctl(ui32BlockID, psHWPerfInitDataInt);
-                       /* Assert to check for HWPerf block mis-configuration */
-                       PVR_ASSERT(psHWPerfInitBlkData);
+                        * between configurations and core power on in APM.
+                        * For RGX_FEATURE_HWPERF_OCEANIC layout we have a different
+                        * structure type to decode the HWPerf block. This is indicated by
+                        * the RGX_CNTBLK_ID_DA_MASK bit being set in the block-ID value. */
 
-                       psHWPerfInitBlkData->bValid = IMG_TRUE;
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "bValid: This specifies if the layout block is valid for the given BVNC.");
-                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                       bDirect = (psBlkTypeDesc->ui32IndirectReg == 0U);
+                       uiUnit = ui32BlockID - psBlkTypeDesc->ui32CntBlkIdBase;
+
+                       if ((ui32BlockID & RGX_CNTBLK_ID_DA_MASK) == RGX_CNTBLK_ID_DA_MASK)
+                       {
+                               psHWPerfInitDABlkData = rgxfw_hwperf_get_da_block_ctl(ui32BlockID, psHWPerfInitDataInt);
+
+                               PVR_ASSERT(psHWPerfInitDABlkData);
+
+                               psHWPerfInitDABlkData->eBlockID = ui32BlockID;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "eBlockID: The Block ID for the layout block. See RGX_HWPERF_CNTBLK_ID for further information.");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                                       (size_t)&(psHWPerfInitDABlkData->eBlockID) - (size_t)(psHWPerfInitDataInt),
+                                                       psHWPerfInitDABlkData->eBlockID,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                               psHWPerfInitDABlkData->uiEnabled = 0U;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "uiEnabled: Set to 0x1 if the block needs to be enabled during playback.");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                                       (size_t)&(psHWPerfInitDABlkData->uiEnabled) - (size_t)(psHWPerfInitDataInt),
+                                                       psHWPerfInitDABlkData->uiEnabled,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                               psHWPerfInitDABlkData->uiNumCounters = 0U;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "uiNumCounters (X): Specifies the number of valid counters"
+                                             " [0..%d] which follow.", RGX_CNTBLK_COUNTERS_MAX);
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                                       (size_t)&(psHWPerfInitDABlkData->uiNumCounters) - (size_t)(psHWPerfInitDataInt),
+                                                       psHWPerfInitDABlkData->uiNumCounters,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                               for (ui32CounterIdx = 0; ui32CounterIdx < RGX_CNTBLK_COUNTERS_MAX; ui32CounterIdx++)
+                               {
+                                       psHWPerfInitDABlkData->aui32Counters[ui32CounterIdx] = IMG_UINT32_C(0x00000000);
+
+                                       if (bDirect)
+                                       {
+                                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                             "%s_COUNTER_%d",
+                                                             psBlkTypeDesc->pszBlockNameComment,
+                                                             ui32CounterIdx);
+                                       }
+                                       else
+                                       {
+                                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                             "%s%d_COUNTER_%d",
+                                                             psBlkTypeDesc->pszBlockNameComment,
+                                                             uiUnit, ui32CounterIdx);
+                                       }
+
+                                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                                       (size_t)&(psHWPerfInitDABlkData->aui32Counters[ui32CounterIdx]) - (size_t)(psHWPerfInitDataInt),
+                                               psHWPerfInitDABlkData->aui32Counters[ui32CounterIdx],
+                                                       PDUMP_FLAGS_CONTINUOUS);
+                               }
+                       }
+                       else
+                       {
+                               psHWPerfInitBlkData = rgxfw_hwperf_get_block_ctl(ui32BlockID, psHWPerfInitDataInt);
+                               /* Assert to check for HWPerf block mis-configuration */
+                               PVR_ASSERT(psHWPerfInitBlkData);
+
+                               psHWPerfInitBlkData->bValid = IMG_TRUE;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "bValid: This specifies if the layout block is valid for the given BVNC.");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                                        (size_t)&(psHWPerfInitBlkData->bValid) - (size_t)(psHWPerfInitDataInt),
                                                        psHWPerfInitBlkData->bValid,
                                                        PDUMP_FLAGS_CONTINUOUS);
 
-                       psHWPerfInitBlkData->bEnabled = IMG_FALSE;
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "bEnabled: Set to 0x1 if the block needs to be enabled during playback.");
-                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                               psHWPerfInitBlkData->bEnabled = IMG_FALSE;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "bEnabled: Set to 0x1 if the block needs to be enabled during playback.");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                                        (size_t)&(psHWPerfInitBlkData->bEnabled) - (size_t)(psHWPerfInitDataInt),
                                                        psHWPerfInitBlkData->bEnabled,
                                                        PDUMP_FLAGS_CONTINUOUS);
 
-                       psHWPerfInitBlkData->eBlockID = ui32BlockID;
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "eBlockID: The Block ID for the layout block. See RGX_HWPERF_CNTBLK_ID for further information.");
-                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                               psHWPerfInitBlkData->eBlockID = ui32BlockID;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "eBlockID: The Block ID for the layout block. See RGX_HWPERF_CNTBLK_ID for further information.");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                                        (size_t)&(psHWPerfInitBlkData->eBlockID) - (size_t)(psHWPerfInitDataInt),
                                                        psHWPerfInitBlkData->eBlockID,
                                                        PDUMP_FLAGS_CONTINUOUS);
 
-                       psHWPerfInitBlkData->uiCounterMask = 0x00;
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "uiCounterMask: Bitmask for selecting the counters that need to be configured. (Bit 0 - counter0, bit 1 - counter1 and so on.)");
-                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                               psHWPerfInitBlkData->uiCounterMask = 0x00;
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "uiCounterMask: Bitmask for selecting the counters that need to be configured. (Bit 0 - counter0, bit 1 - counter1 and so on.)");
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                                        (size_t)&(psHWPerfInitBlkData->uiCounterMask) - (size_t)(psHWPerfInitDataInt),
                                                        psHWPerfInitBlkData->uiCounterMask,
                                                        PDUMP_FLAGS_CONTINUOUS);
 
-                       for (ui32CounterIdx = RGX_CNTBLK_COUNTER0_ID; ui32CounterIdx < psBlkTypeDesc->ui8NumCounters; ui32CounterIdx++)
-                       {
-                               psHWPerfInitBlkData->aui64CounterCfg[ui32CounterIdx] = IMG_UINT64_C(0x0000000000000000);
+                               for (ui32CounterIdx = RGX_CNTBLK_COUNTER0_ID; ui32CounterIdx < psBlkTypeDesc->ui8NumCounters; ui32CounterIdx++)
+                               {
+                                       psHWPerfInitBlkData->aui64CounterCfg[ui32CounterIdx] = IMG_UINT64_C(0x0000000000000000);
 
-                               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "%s_COUNTER_%d", psBlkTypeDesc->pszBlockNameComment, ui32CounterIdx);
-                               DevmemPDumpLoadMemValue64(psHWPerfDataMemDesc,
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                     "%s_COUNTER_%d", psBlkTypeDesc->pszBlockNameComment, ui32CounterIdx);
+                                       DevmemPDumpLoadMemValue64(psHWPerfDataMemDesc,
                                                        (size_t)&(psHWPerfInitBlkData->aui64CounterCfg[ui32CounterIdx]) - (size_t)(psHWPerfInitDataInt),
                                                        psHWPerfInitBlkData->aui64CounterCfg[ui32CounterIdx],
                                                        PDUMP_FLAGS_CONTINUOUS);
 
+                               }
                        }
                }
        }
@@ -1136,11 +1256,13 @@ static void InitialiseHWPerfCounters(void *pvDevice, DEVMEM_MEMDESC *psHWPerfDat
 
 ******************************************************************************/
 
-static void InitialiseCustomCounters(DEVMEM_MEMDESC *psHWPerfDataMemDesc)
+static void InitialiseCustomCounters(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     DEVMEM_MEMDESC *psHWPerfDataMemDesc)
 {
        IMG_UINT32 ui32CustomBlock, ui32CounterID;
 
-       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "ui32SelectedCountersBlockMask - The Bitmask of the custom counters that are to be selected");
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "ui32SelectedCountersBlockMask - The Bitmask of the custom counters that are to be selected");
        DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                                offsetof(RGXFWIF_HWPERF_CTL, ui32SelectedCountersBlockMask),
                                                0,
@@ -1156,7 +1278,8 @@ static void InitialiseCustomCounters(DEVMEM_MEMDESC *psHWPerfDataMemDesc)
                const IMG_DEVMEM_OFFSET_T uiOffsetOfCustomBlockSelectedCounters
                = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_HWPERF_CTL *)0)->SelCntr[ui32CustomBlock].ui32NumSelectedCounters);
 
-               PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "ui32NumSelectedCounters - The Number of counters selected for this Custom Block: %d",ui32CustomBlock );
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "ui32NumSelectedCounters - The Number of counters selected for this Custom Block: %d",ui32CustomBlock );
                DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                        uiOffsetOfCustomBlockSelectedCounters,
                                        0,
@@ -1167,7 +1290,8 @@ static void InitialiseCustomCounters(DEVMEM_MEMDESC *psHWPerfDataMemDesc)
                        const IMG_DEVMEM_OFFSET_T uiOffsetOfCustomBlockSelectedCounterIDs
                        = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_HWPERF_CTL *)0)->SelCntr[ui32CustomBlock].aui32SelectedCountersIDs[ui32CounterID]);
 
-                       PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "CUSTOMBLK_%d_COUNTERID_%d",ui32CustomBlock, ui32CounterID);
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "CUSTOMBLK_%d_COUNTERID_%d",ui32CustomBlock, ui32CounterID);
                        DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
                                        uiOffsetOfCustomBlockSelectedCounterIDs,
                                        0,
@@ -1190,28 +1314,15 @@ static void InitialiseCustomCounters(DEVMEM_MEMDESC *psHWPerfDataMemDesc)
 ******************************************************************************/
 static PVRSRV_ERROR InitialiseAllCounters(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
        RGXFWIF_HWPERF_CTL *psHWPerfInitData;
        PVRSRV_ERROR eError;
 
        eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfCountersMemDesc, (void **)&psHWPerfInitData);
        PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", failHWPerfCountersMemDescAqCpuVirt);
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psDevInfo->psRGXFWIfHWPerfCountersMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-           printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-           BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psHWPerfInitData - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif 
 
-       InitialiseHWPerfCounters(psDevInfo, psDevInfo->psRGXFWIfHWPerfCountersMemDesc, psHWPerfInitData);
-       InitialiseCustomCounters(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
+       InitialiseHWPerfCounters(psDeviceNode, psDevInfo, psDevInfo->psRGXFWIfHWPerfCountersMemDesc, psHWPerfInitData);
+       InitialiseCustomCounters(psDeviceNode, psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
 
 failHWPerfCountersMemDescAqCpuVirt:
        DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
@@ -1244,10 +1355,10 @@ _ParseHTBAppHints(PVRSRV_DEVICE_NODE *psDeviceNode)
        if (pvParamState == NULL)
                return;
 
-       SrvInitParamGetUINT32BitField(pvParamState, EnableHTBLogGroup, ui32LogType);
+       SrvInitParamGetUINT32BitField(INITPARAM_NO_DEVICE,  pvParamState,  EnableHTBLogGroup,   ui32LogType);
        bAnyLogGroupConfigured = ui32LogType ? IMG_TRUE : IMG_FALSE;
-       SrvInitParamGetUINT32List(pvParamState, HTBOperationMode, ui32OpMode);
-       SrvInitParamGetUINT32(pvParamState, HTBufferSizeInKB, ui32BufferSize);
+       SrvInitParamGetUINT32List(INITPARAM_NO_DEVICE,      pvParamState,  HTBOperationMode,     ui32OpMode);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,  HTBufferSizeInKB, ui32BufferSize);
 
        SrvInitParamClose(pvParamState);
 }
@@ -1318,6 +1429,54 @@ PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
        PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
        RGX_LAYER_PARAMS sLayerParams;
 
+       PDUMPCOMMENT(psDeviceNode, "RGX Initialisation Part 1");
+
+       PDUMPCOMMENT(psDeviceNode, "Device Name: %s",
+                    psDeviceNode->psDevConfig->pszName);
+       PDUMPCOMMENT(psDeviceNode, "Device ID: %u (%d)",
+                    psDeviceNode->sDevId.ui32InternalID,
+                    psDeviceNode->sDevId.i32OsDeviceID);
+
+       if (psDeviceNode->psDevConfig->pszVersion)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Device Version: %s",
+                            psDeviceNode->psDevConfig->pszVersion);
+       }
+
+       /* pdump info about the core */
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGX Version Information (KM): %d.%d.%d.%d",
+                    psDevInfo->sDevFeatureCfg.ui32B,
+                    psDevInfo->sDevFeatureCfg.ui32V,
+                    psDevInfo->sDevFeatureCfg.ui32N,
+                    psDevInfo->sDevFeatureCfg.ui32C);
+
+       RGXInitMultiCoreInfo(psDeviceNode);
+
+#if defined(PDUMP)
+       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
+                                             &psDeviceNode->sDummyPage,
+                                             PVR_DUMMY_PAGE_INIT_VALUE,
+                                             DUMMY_PAGE,
+                                             IMG_TRUE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate dummy page.", __func__));
+               goto cleanup;
+       }
+
+       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
+                                             &psDeviceNode->sDevZeroPage,
+                                             PVR_ZERO_PAGE_INIT_VALUE,
+                                             DEV_ZERO_PAGE,
+                                             IMG_TRUE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate Zero page.", __func__));
+               goto cleanup;
+       }
+#endif /* defined(PDUMP) */
+
        sLayerParams.psDevInfo = psDevInfo;
 #if defined(SUPPORT_TRUSTED_DEVICE)
        eError = RGXValidateTDHeaps(psDeviceNode);
@@ -1354,11 +1513,15 @@ PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
        }
 
        /* Set which HW Safety Events will be handled by the driver */
+#if defined(RGX_FEATURE_WATCHDOG_TIMER_BIT_MASK)
        psDevInfo->ui32HostSafetyEventMask |= RGX_IS_FEATURE_SUPPORTED(psDevInfo, WATCHDOG_TIMER) ?
                                                                                  RGX_CR_SAFETY_EVENT_STATUS__ROGUEXE__WATCHDOG_TIMEOUT_EN : 0;
+#endif
+#if defined(RGX_FEATURE_ECC_RAMS_MAX_VALUE_IDX)
        psDevInfo->ui32HostSafetyEventMask |= (RGX_DEVICE_HAS_FEATURE_VALUE(&sLayerParams, ECC_RAMS)
                                                                                   && (RGX_DEVICE_GET_FEATURE_VALUE(&sLayerParams, ECC_RAMS) > 0)) ?
                                                                                  RGX_CR_SAFETY_EVENT_STATUS__ROGUEXE__FAULT_FW_EN : 0;
+#endif
 
        /* Services initialisation parameters */
        _ParseHTBAppHints(psDeviceNode);
@@ -1422,6 +1585,7 @@ PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 #endif
                                 sApphints.eRGXRDPowerIslandConf,
                                 sApphints.eFirmwarePerf,
+                                sApphints.ui32KCCBSizeLog2,
                                 ui32FWConfigFlagsExt,
                                 ui32FwOsCfgFlags);
 
@@ -1453,7 +1617,6 @@ PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
         */
        eError = RGXInitDevPart2(psDeviceNode,
                                 ui32DeviceFlags,
-                                sApphints.ui32HWPerfHostBufSize,
                                 sApphints.ui32HWPerfHostFilter,
                                 sApphints.eRGXActivePMConf);
 
@@ -1466,7 +1629,7 @@ PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
        }
 
 #if defined(SUPPORT_VALIDATION)
-       PVRSRVAppHintDumpState();
+       PVRSRVAppHintDumpState(psDeviceNode);
 #endif
 
        eError = PVRSRV_OK;
index 877b764..2d213e3 100644 (file)
@@ -54,7 +54,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #include "rgxdevice.h"
-#include "rgxdefs_km.h"
+#include "km/rgxdefs_km.h"
 
 #define SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING
 
@@ -76,6 +76,7 @@ static void RGXEnableClocks(const void *hPrivate)
        RGXCommentLog(hPrivate, "RGX clock: use default (automatic clock gating)");
 }
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
 static PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
@@ -224,7 +225,7 @@ static void RGXInitMetaProcWrapper(const void *hPrivate)
        RGXCommentLog(hPrivate, "RGXStart: Configure META wrapper");
        RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig);
 }
-
+#endif
 
 /*!
 *******************************************************************************
@@ -295,6 +296,7 @@ static void RGXInitMipsProcWrapper(const void *hPrivate)
                           ~RGX_CR_MIPS_ADDR_REMAP1_CONFIG2_ADDR_OUT_CLRMSK,
                           ui64RemapSettings);
 
+#if defined(FIX_HW_BRN_63553_BIT_MASK)
        if (RGX_DEVICE_HAS_BRN(hPrivate, 63553))
        {
                IMG_BOOL bPhysBusAbove32Bit = RGXGetDevicePhysBusWidth(hPrivate) > 32;
@@ -312,6 +314,7 @@ static void RGXInitMipsProcWrapper(const void *hPrivate)
                                        ui64RemapSettings);
                }
        }
+#endif
 
        /*
         * Data remap setup
@@ -407,6 +410,7 @@ static void RGXInitMipsProcWrapper(const void *hPrivate)
 }
 
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
 /*!
 *******************************************************************************
 
@@ -452,6 +456,7 @@ static void RGXInitRiscvProcWrapper(const void *hPrivate)
        RGXCommentLog(hPrivate, "RGXStart: Set GARTEN_IDLE type to RISCV");
        RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
 }
+#endif
 
 
 /*!
@@ -468,6 +473,7 @@ static void RGXInitRiscvProcWrapper(const void *hPrivate)
 ******************************************************************************/
 static void __RGXInitSLC(const void *hPrivate)
 {
+#if defined(RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK)
        if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_CACHE_HIERARCHY))
        {
                IMG_UINT32 ui32Reg;
@@ -536,6 +542,7 @@ static void __RGXInitSLC(const void *hPrivate)
                }
        }
        else
+#endif
        {
                IMG_UINT32 ui32Reg;
                IMG_UINT32 ui32RegVal;
@@ -547,6 +554,7 @@ static void __RGXInitSLC(const void *hPrivate)
                ui32Reg = RGX_CR_SLC_CTRL_BYPASS;
                ui64RegVal = 0;
 
+#if defined(RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN)
                if ((RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, SLC_SIZE_IN_KILOBYTES) == 8)  ||
                    RGX_DEVICE_HAS_BRN(hPrivate, 61450))
                {
@@ -554,6 +562,7 @@ static void __RGXInitSLC(const void *hPrivate)
                        ui64RegVal |= (IMG_UINT64) RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_OBJ_EN |
                                                (IMG_UINT64) RGX_CR_SLC_CTRL_BYPASS_REQ_IPF_CPF_EN;
                }
+#endif
 
                if (ui64RegVal != 0)
                {
@@ -567,9 +576,13 @@ static void __RGXInitSLC(const void *hPrivate)
                 *       32bits (RGX_CR_SLC_CTRL_MISC_SCRAMBLE_BITS) unchanged from the HW default.
                 */
                ui32Reg = RGX_CR_SLC_CTRL_MISC;
-               ui32RegVal = (RGXReadReg32(hPrivate, ui32Reg) & RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN) |
-                            RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
+               ui32RegVal = RGX_CR_SLC_CTRL_MISC_ADDR_DECODE_MODE_PVR_HASH1;
+
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
+               ui32RegVal |= RGXReadReg32(hPrivate, ui32Reg) & RGX_CR_SLC_CTRL_MISC_ENABLE_PSG_HAZARD_CHECK_EN;
+#endif
 
+#if defined(FIX_HW_BRN_60084_BIT_MASK)
                if (RGX_DEVICE_HAS_BRN(hPrivate, 60084))
                {
 #if !defined(SOC_FEATURE_STRICT_SAME_ADDRESS_WRITE_ORDERING)
@@ -581,11 +594,15 @@ static void __RGXInitSLC(const void *hPrivate)
                        }
 #endif
                }
+#endif
+
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
                /* Bypass burst combiner if SLC line size is smaller than 1024 bits */
                if (RGXGetDeviceCacheLineSize(hPrivate) < 1024)
                {
                        ui32RegVal |= RGX_CR_SLC_CTRL_MISC_BYPASS_BURST_COMBINER_EN;
                }
+#endif
 
                RGXWriteReg32(hPrivate, ui32Reg, ui32RegVal);
        }
@@ -620,6 +637,7 @@ static void RGXInitBIF(const void *hPrivate)
                 */
                RGXCommentLog(hPrivate, "RGX firmware MMU Page Catalogue");
 
+#if defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
                if (!RGX_DEVICE_HAS_FEATURE(hPrivate, SLC_VIVT))
                {
                        /* Write the cat-base address */
@@ -632,6 +650,7 @@ static void RGXInitBIF(const void *hPrivate)
                                              << RGX_CR_BIF_CAT_BASE0_ADDR_SHIFT)
                                              & ~RGX_CR_BIF_CAT_BASE0_ADDR_CLRMSK);
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
                        if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
                        {
                                /* Keep catbase registers in sync */
@@ -644,6 +663,7 @@ static void RGXInitBIF(const void *hPrivate)
                                                      << RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_SHIFT)
                                                      & ~RGX_CR_FWCORE_MEM_CAT_BASE0_ADDR_CLRMSK);
                        }
+#endif
 
                        /*
                         * Trusted Firmware boot
@@ -654,7 +674,9 @@ static void RGXInitBIF(const void *hPrivate)
 #endif
                }
                else
+#endif /* defined(RGX_FEATURE_SLC_VIVT_BIT_MASK) */
                {
+#if defined(RGX_CR_MMU_CBASE_MAPPING) // FIXME_OCEANIC
                        IMG_UINT32 uiPCAddr;
                        uiPCAddr = (((sPCAddr.uiAddr >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT)
                                     << RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
@@ -682,6 +704,7 @@ static void RGXInitBIF(const void *hPrivate)
                                              RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
                                              uiPCAddr);
 #endif
+#endif
                }
        }
        else
@@ -726,18 +749,22 @@ static void RGXAXIACELiteInit(const void *hPrivate)
                     (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_COHERENT_SHIFT) |
                     (2U << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ARCACHE_CACHE_MAINTENANCE_SHIFT);
 
+#if defined(FIX_HW_BRN_42321_BIT_MASK)
        if (RGX_DEVICE_HAS_BRN(hPrivate, 42321))
        {
                ui64RegVal |= (((IMG_UINT64) 1) << RGX_CR_AXI_ACE_LITE_CONFIGURATION_DISABLE_COHERENT_WRITELINEUNIQUE_SHIFT);
        }
+#endif
 
+#if defined(FIX_HW_BRN_68186_BIT_MASK)
        if (RGX_DEVICE_HAS_BRN(hPrivate, 68186))
        {
         /* default value for reg_enable_fence_out is zero. Force to 1 to allow core_clk < mem_clk  */
                ui64RegVal |= (IMG_UINT64)1 << RGX_CR_AXI_ACE_LITE_CONFIGURATION_ENABLE_FENCE_OUT_SHIFT;
        }
+#endif
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
+#if defined(SUPPORT_TRUSTED_DEVICE) && defined(RGX_FEATURE_SLC_VIVT_BIT_MASK)
        if (RGX_DEVICE_HAS_FEATURE(hPrivate, SLC_VIVT))
        {
                RGXCommentLog(hPrivate, "OSID 0 and 1 are trusted");
@@ -753,28 +780,27 @@ static void RGXAXIACELiteInit(const void *hPrivate)
 PVRSRV_ERROR RGXStart(const void *hPrivate)
 {
        PVRSRV_ERROR eError = PVRSRV_OK;
-       IMG_BOOL bDoFWSlaveBoot;
-       IMG_CHAR *pcRGXFW_PROCESSOR;
-       IMG_BOOL bMetaFW;
+       IMG_CHAR *pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       IMG_BOOL bDoFWSlaveBoot = IMG_FALSE;
+       IMG_BOOL bMetaFW = IMG_FALSE;
+#endif
 
-       if (RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS))
-       {
-               pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_MIPS;
-               bMetaFW = IMG_FALSE;
-               bDoFWSlaveBoot = IMG_FALSE;
-       }
-       else if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+       if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
        {
                pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_RISCV;
-               bMetaFW = IMG_FALSE;
-               bDoFWSlaveBoot = IMG_FALSE;
        }
        else
+#endif
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (RGX_DEVICE_HAS_FEATURE_VALUE(hPrivate, META))
        {
                pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
                bMetaFW = IMG_TRUE;
                bDoFWSlaveBoot = RGXDoFWSlaveBoot(hPrivate);
        }
+#endif
 
        if (RGX_DEVICE_HAS_FEATURE(hPrivate, SYS_BUS_SECURE_RESET))
        {
@@ -795,6 +821,7 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
 #define RGX_CR_SOFT_RESET_ALL  (RGX_CR_SOFT_RESET_MASKFULL)
 #endif
 
+#if defined(RGX_S7_SOFT_RESET_DUSTS)
        if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
        {
                /* Set RGX in soft-reset */
@@ -826,6 +853,7 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
                (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
        }
        else
+#endif
        {
                /* Set RGX in soft-reset */
                RGXCommentLog(hPrivate, "RGXStart: soft reset everything");
@@ -842,7 +870,12 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
 
                /* Take everything out of reset but the FW processor */
                RGXCommentLog(hPrivate, "RGXStart: Take everything out of reset but %s", pcRGXFW_PROCESSOR);
+
+#if defined(RGX_FEATURE_XE_ARCHITECTURE) && (RGX_FEATURE_XE_ARCHITECTURE > 1)
+               RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_CPU_EN);
+#else
                RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+#endif
 
                (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
        }
@@ -864,6 +897,7 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
                                        RGX_CR_SAFETY_EVENT_ENABLE__ROGUEXE__MASKFULL);
        }
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (bMetaFW)
        {
                if (bDoFWSlaveBoot)
@@ -880,19 +914,25 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
                        RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
                }
        }
+#endif
 
        /*
         * Initialise Firmware wrapper
         */
-       if (bMetaFW)
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
+       if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
        {
-               RGXInitMetaProcWrapper(hPrivate);
+               RGXInitRiscvProcWrapper(hPrivate);
        }
-       else if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
+       else
+#endif
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
+       if (bMetaFW)
        {
-               RGXInitRiscvProcWrapper(hPrivate);
+               RGXInitMetaProcWrapper(hPrivate);
        }
        else
+#endif
        {
                RGXInitMipsProcWrapper(hPrivate);
        }
@@ -919,6 +959,7 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
        /* ... and afterwards */
        RGXWaitCycles(hPrivate, 32, 3);
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (bMetaFW && bDoFWSlaveBoot)
        {
                eError = RGXFabricCoherencyTest(hPrivate);
@@ -929,9 +970,11 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
                if (eError != PVRSRV_OK) return eError;
        }
        else
+#endif
        {
                RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Master boot Start");
 
+#if defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
                if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
                {
                        /* Bring Debug Module out of reset */
@@ -941,6 +984,7 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
                        RGXWriteReg32(hPrivate, RGX_CR_FWCORE_BOOT, 1);
                        RGXWaitCycles(hPrivate, 32, 3);
                }
+#endif
        }
 
 #if defined(SUPPORT_TRUSTED_DEVICE) && !defined(SUPPORT_SECURITY_VALIDATION)
@@ -954,10 +998,12 @@ PVRSRV_ERROR RGXStart(const void *hPrivate)
 
 PVRSRV_ERROR RGXStop(const void *hPrivate)
 {
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX) || defined(RGX_FEATURE_RISCV_FW_PROCESSOR_BIT_MASK)
        IMG_BOOL bMipsFW = RGX_DEVICE_HAS_FEATURE(hPrivate, MIPS);
        IMG_BOOL bRiscvFW = RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR);
        IMG_BOOL bMetaFW = !bMipsFW && !bRiscvFW;
-       PVRSRV_ERROR eError;
+#endif
+       PVRSRV_ERROR eError = PVRSRV_OK;
        RGX_LAYER_PARAMS *psParams;
        PVRSRV_RGXDEV_INFO *psDevInfo;
        PVR_ASSERT(hPrivate != NULL);
@@ -969,25 +1015,29 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
        /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper
         * For LAYOUT_MARS = 1, SIDEKICK would have been powered down by FW
         */
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
        if (!(PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0))
        {
-               if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+               if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SIDEKICK_IDLE,
-                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
+                                       RGX_CR_JONES_IDLE,
+                                       RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
+                                       RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
                }
                else
+#endif
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_JONES_IDLE,
-                                       RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
-                                       RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
+                                       RGX_CR_SIDEKICK_IDLE,
+                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
+                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
                }
 
                if (eError != PVRSRV_OK) return eError;
        }
+#endif
 
        if (!(PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0))
        {
@@ -996,19 +1046,21 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                 * Wait for SLC to signal IDLE
                 * For LAYOUT_MARS = 1, SLC would have been powered down by FW
                 */
-               if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+               if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SLC_IDLE,
-                                       RGX_CR_SLC_IDLE_MASKFULL,
-                                       RGX_CR_SLC_IDLE_MASKFULL);
+                                       RGX_CR_SLC3_IDLE,
+                                       RGX_CR_SLC3_IDLE_MASKFULL,
+                                       RGX_CR_SLC3_IDLE_MASKFULL);
                }
                else
+#endif
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SLC3_IDLE,
-                                       RGX_CR_SLC3_IDLE_MASKFULL,
-                                       RGX_CR_SLC3_IDLE_MASKFULL);
+                                       RGX_CR_SLC_IDLE,
+                                       RGX_CR_SLC_IDLE_MASKFULL,
+                                       RGX_CR_SLC_IDLE_MASKFULL);
                }
 #endif /* SUPPORT_SHARED_SLC */
                if (eError != PVRSRV_OK) return eError;
@@ -1023,6 +1075,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                      RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
                      RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK
                      & RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL);
+#if defined(RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC) // FIXME_OCEANIC
        RGXWriteReg32(hPrivate,
                      RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
                      RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
@@ -1031,9 +1084,9 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                      RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
                      RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
                      & RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL);
+#endif
 
-
-#if defined(PDUMP)
+#if defined(PDUMP) && defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (bMetaFW)
        {
                /* Disabling threads is only required for pdumps to stop the fw gracefully */
@@ -1066,7 +1119,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
        }
 #endif
 
-
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
        /* Extra Idle checks */
        eError = RGXPollReg32(hPrivate,
                              RGX_CR_BIF_STATUS_MMU,
@@ -1079,9 +1132,12 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                              0,
                              RGX_CR_BIFPM_STATUS_MMU_MASKFULL);
        if (eError != PVRSRV_OK) return eError;
+#endif
 
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
        if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE) &&
            !RGX_DEVICE_HAS_FEATURE(hPrivate, XT_TOP_INFRASTRUCTURE))
+#endif
        {
                eError = RGXPollReg32(hPrivate,
                                      RGX_CR_BIF_READS_EXT_STATUS,
@@ -1090,12 +1146,13 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                if (eError != PVRSRV_OK) return eError;
        }
 
-
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
        eError = RGXPollReg32(hPrivate,
                              RGX_CR_BIFPM_READS_EXT_STATUS,
                              0,
                              RGX_CR_BIFPM_READS_EXT_STATUS_MASKFULL);
        if (eError != PVRSRV_OK) return eError;
+#endif
 
        {
                IMG_UINT64 ui64SLCMask = RGX_CR_SLC_STATUS1_MASKFULL;
@@ -1106,6 +1163,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                if (eError != PVRSRV_OK) return eError;
        }
 
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
        if (4 == RGXGetDeviceSLCBanks(hPrivate))
        {
                eError = RGXPollReg64(hPrivate,
@@ -1114,6 +1172,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                                      RGX_CR_SLC_STATUS2_MASKFULL);
                if (eError != PVRSRV_OK) return eError;
        }
+#endif
 
        if (!(PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0))
        {
@@ -1122,19 +1181,21 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                 * Wait for SLC to signal IDLE
                 * For LAYOUT_MARS = 1, SLC would have been powered down by FW
                 */
-               if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+               if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SLC_IDLE,
-                                       RGX_CR_SLC_IDLE_MASKFULL,
-                                       RGX_CR_SLC_IDLE_MASKFULL);
+                                       RGX_CR_SLC3_IDLE,
+                                       RGX_CR_SLC3_IDLE_MASKFULL,
+                                       RGX_CR_SLC3_IDLE_MASKFULL);
                }
                else
+#endif
                {
                        eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SLC3_IDLE,
-                                       RGX_CR_SLC3_IDLE_MASKFULL,
-                                       RGX_CR_SLC3_IDLE_MASKFULL);
+                                       RGX_CR_SLC_IDLE,
+                                       RGX_CR_SLC_IDLE_MASKFULL,
+                                       RGX_CR_SLC_IDLE_MASKFULL);
                }
 #endif /* SUPPORT_SHARED_SLC */
                if (eError != PVRSRV_OK) return eError;
@@ -1143,17 +1204,13 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
        /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper
         * For LAYOUT_MARS = 1, SIDEKICK would have been powered down by FW
         */
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
        if (!(PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0))
        {
-               if (!RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
-               {
-                       eError = RGXPollReg32(hPrivate,
-                                       RGX_CR_SIDEKICK_IDLE,
-                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
-                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
-               }
-               else
+#if defined(RGX_FEATURE_S7_TOP_INFRASTRUCTURE_BIT_MASK)
+               if (RGX_DEVICE_HAS_FEATURE(hPrivate, S7_TOP_INFRASTRUCTURE))
                {
+#if defined(RGX_FEATURE_FASTRENDER_DM_BIT_MASK)
                        if (!RGX_DEVICE_HAS_FEATURE(hPrivate, FASTRENDER_DM))
                        {
                                eError = RGXPollReg32(hPrivate,
@@ -1161,11 +1218,22 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                                                RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN),
                                                RGX_CR_JONES_IDLE_MASKFULL^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN|RGX_CR_JONES_IDLE_HOSTIF_EN));
                        }
+#endif
+               }
+               else
+#endif
+               {
+                       eError = RGXPollReg32(hPrivate,
+                                       RGX_CR_SIDEKICK_IDLE,
+                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN),
+                                       RGX_CR_SIDEKICK_IDLE_MASKFULL^(RGX_CR_SIDEKICK_IDLE_GARTEN_EN|RGX_CR_SIDEKICK_IDLE_SOCIF_EN|RGX_CR_SIDEKICK_IDLE_HOSTIF_EN));
                }
 
                if (eError != PVRSRV_OK) return eError;
        }
+#endif
 
+#if defined(RGX_FEATURE_META_MAX_VALUE_IDX)
        if (bMetaFW)
        {
                IMG_UINT32 ui32RegValue;
@@ -1199,6 +1267,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                }
        }
        else
+#endif
        {
                if (PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode, LAYOUT_MARS) > 0)
                {
@@ -1212,6 +1281,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                                        RGX_CR_MARS_IDLE_CPU_EN | RGX_CR_MARS_IDLE_MH_SYSARB0_EN);
                        if (eError != PVRSRV_OK) return eError;
                }
+#if !defined(RGX_FEATURE_XE_ARCHITECTURE) || (RGX_FEATURE_XE_ARCHITECTURE == 1)
                else
                {
                        eError = RGXPollReg32(hPrivate,
@@ -1220,6 +1290,7 @@ PVRSRV_ERROR RGXStop(const void *hPrivate)
                                        RGX_CR_SIDEKICK_IDLE_GARTEN_EN);
                        if (eError != PVRSRV_OK) return eError;
                }
+#endif
        }
 
        return eError;
index 3b50deb..3b43bab 100644 (file)
@@ -76,10 +76,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "rgxtimerquery.h"
 
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
-
 #if defined(SUPPORT_BUFFER_SYNC)
 #include "pvr_buffer_sync.h"
 #endif
@@ -144,7 +140,7 @@ void _DebugSyncCheckpoints(const IMG_CHAR *pszFunction,
 #define CCB_CMD_HELPER_NUM_3D_COMMANDS 3
 
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
-#define WORKEST_CYCLES_PREDICTION_GET(x) ((x).ui64CyclesPrediction)
+#define WORKEST_CYCLES_PREDICTION_GET(x) ((x).ui32CyclesPrediction)
 #else
 #define WORKEST_CYCLES_PREDICTION_GET(x) (NO_CYCEST)
 #endif
@@ -538,7 +534,7 @@ PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
        psPMRNode->psFreeList = psFreeList;
 
        /* Allocate Memory Block */
-       PDUMPCOMMENT("Allocate PB Block (Pages %08X)", ui32NumPages);
+       PDUMPCOMMENT(psFreeList->psDevInfo->psDeviceNode, "Allocate PB Block (Pages %08X)", ui32NumPages);
        uiSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
        if (psPMRNode->bFirstPageMissing)
        {
@@ -557,7 +553,8 @@ PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
                        szAllocName,
                        psFreeList->ownerPid,
                        &psPMRNode->psPMR,
-                       PDUMP_NONE);
+                       PDUMP_NONE,
+                       NULL);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR,
@@ -656,14 +653,10 @@ PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
 
                /* Copy only the newly added memory */
                OSCachedMemCopy(pFLMapAddr + ui32FLMaxSize + ui32CopyOffset, pFLMapAddr + ui32CopyOffset , uiLength);
-
-               if (PVRSRV_CHECK_CPU_WRITE_COMBINE(PMR_Flags(psFreeList->psFreeListPMR)))
-               {
-                       OSWriteMemoryBarrier();
-               }
+               OSWriteMemoryBarrier(pFLMapAddr);
 
 #if defined(PDUMP)
-               PDUMPCOMMENT("Initialize shadow freelist");
+               PDUMPCOMMENT(psFreeList->psDevInfo->psDeviceNode, "Initialize shadow freelist");
 
                /* Translate memcpy to pdump */
                {
@@ -678,11 +671,6 @@ PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
                                                ":SYSMEM:$1",
                                                PDUMP_FLAGS_CONTINUOUS);
                        }
-
-                       if (PVRSRV_CHECK_CPU_WRITE_COMBINE(PMR_Flags(psFreeList->psFreeListPMR)))
-                       {
-                               OSWriteMemoryBarrier();
-                       }
                }
 #endif
 
@@ -957,7 +945,6 @@ void RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
                        eError = RGXScheduleCommand(psDevInfo,
                                        RGXFWIF_DM_3D,
                                        &s3DCCBCmd,
-                                       0,
                                        PDUMP_FLAGS_NONE);
                        if (eError != PVRSRV_ERROR_RETRY)
                        {
@@ -1102,16 +1089,13 @@ static PVRSRV_ERROR RGXReconstructFreeList(RGX_FREELIST *psFreeList)
 
 void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
                                               IMG_UINT32 ui32FreelistsCount,
-                                              IMG_UINT32 *paui32Freelists)
+                                              const IMG_UINT32 *paui32Freelists)
 {
        PVRSRV_ERROR      eError = PVRSRV_OK;
        DLLIST_NODE       *psNode, *psNext;
        IMG_UINT32        ui32Loop;
        RGXFWIF_KCCB_CMD  sTACCBCmd;
 #if !defined(SUPPORT_SHADOW_FREELISTS)
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        DLLIST_NODE       *psNodeHWRTData, *psNextHWRTData;
        RGX_KM_HW_RT_DATASET *psKMHWRTDataSet;
        RGXFWIF_HWRTDATA     *psHWRTData;
@@ -1231,16 +1215,6 @@ void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
                                        psHWRTData->eState = RGXFWIF_RTDATA_STATE_HWR;
                                        psHWRTData->ui32HWRTDataFlags &= ~HWRTDATA_HAS_LAST_TA;
 
-#ifdef CACHE_TEST
-                                       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psKMHWRTDataSet->psHWRTDataFwMemDesc;
-                                   printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-                                       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-                                       {
-                                               printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                                               BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psHWRTData - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-                                       }
-#endif
-
                                        DevmemReleaseCpuVirtAddr(psKMHWRTDataSet->psHWRTDataFwMemDesc);
                                }
 #endif
@@ -1280,7 +1254,6 @@ void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
                eError = RGXScheduleCommand(psDevInfo,
                                RGXFWIF_DM_GEOM,
                                &sTACCBCmd,
-                               0,
                                PDUMP_FLAGS_NONE);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -1300,28 +1273,10 @@ static PVRSRV_ERROR RGXCreateHWRTData_aux(
                IMG_DEV_VIRTADDR        psVHeapTableDevVAddr,
                IMG_DEV_VIRTADDR                psPMMListDevVAddr, /* per-HWRTData */
                RGX_FREELIST                    *apsFreeLists[RGXFW_MAX_FREELISTS],
-               IMG_UINT32           ui32ScreenPixelMax,
-               IMG_UINT64           ui64MultiSampleCtl,
-               IMG_UINT64           ui64FlippedMultiSampleCtl,
-               IMG_UINT32           ui32TPCStride,
                IMG_DEV_VIRTADDR                sTailPtrsDevVAddr,
-               IMG_UINT32           ui32TPCSize,
-               IMG_UINT32           ui32TEScreen,
-               IMG_UINT32           ui32TEAA,
-               IMG_UINT32           ui32TEMTILE1,
-               IMG_UINT32           ui32TEMTILE2,
-               IMG_UINT32           ui32MTileStride,
-               IMG_UINT32                 ui32ISPMergeLowerX,
-               IMG_UINT32                 ui32ISPMergeLowerY,
-               IMG_UINT32                 ui32ISPMergeUpperX,
-               IMG_UINT32                 ui32ISPMergeUpperY,
-               IMG_UINT32                 ui32ISPMergeScaleX,
-               IMG_UINT32                 ui32ISPMergeScaleY,
                IMG_DEV_VIRTADDR        sMacrotileArrayDevVAddr, /* per-HWRTData */
                IMG_DEV_VIRTADDR        sRgnHeaderDevVAddr, /* per-HWRTData */
                IMG_DEV_VIRTADDR        sRTCDevVAddr,
-               IMG_UINT64                      uiRgnHeaderSize,
-               IMG_UINT32                      ui32ISPMtileSize,
                IMG_UINT16                      ui16MaxRTs,
                RGX_HWRTDATA_COMMON_COOKIE      *psHWRTDataCommonCookie,
                RGX_KM_HW_RT_DATASET **ppsKMHWRTDataSet) /* per-HWRTData */
@@ -1394,28 +1349,10 @@ static PVRSRV_ERROR RGXCreateHWRTData_aux(
 
        psHWRTData->psPMMListDevVAddr = psPMMListDevVAddr;
 
-       psHWRTData->ui32ScreenPixelMax    = ui32ScreenPixelMax;
-       psHWRTData->ui64MultiSampleCtl = ui64MultiSampleCtl;
-       psHWRTData->ui64FlippedMultiSampleCtl = ui64FlippedMultiSampleCtl;
-       psHWRTData->ui32TPCStride         = ui32TPCStride;
        psHWRTData->sTailPtrsDevVAddr     = sTailPtrsDevVAddr;
-       psHWRTData->ui32TPCSize           = ui32TPCSize;
-       psHWRTData->ui32TEScreen          = ui32TEScreen;
-       psHWRTData->ui32TEAA              = ui32TEAA;
-       psHWRTData->ui32TEMTILE1          = ui32TEMTILE1;
-       psHWRTData->ui32TEMTILE2          = ui32TEMTILE2;
-       psHWRTData->ui32MTileStride       = ui32MTileStride;
-       psHWRTData->ui32ISPMergeLowerX = ui32ISPMergeLowerX;
-       psHWRTData->ui32ISPMergeLowerY = ui32ISPMergeLowerY;
-       psHWRTData->ui32ISPMergeUpperX = ui32ISPMergeUpperX;
-       psHWRTData->ui32ISPMergeUpperY = ui32ISPMergeUpperY;
-       psHWRTData->ui32ISPMergeScaleX = ui32ISPMergeScaleX;
-       psHWRTData->ui32ISPMergeScaleY = ui32ISPMergeScaleY;
        psHWRTData->sMacrotileArrayDevVAddr = sMacrotileArrayDevVAddr;
        psHWRTData->sRgnHeaderDevVAddr          = sRgnHeaderDevVAddr;
        psHWRTData->sRTCDevVAddr                        = sRTCDevVAddr;
-       psHWRTData->uiRgnHeaderSize                     = uiRgnHeaderSize;
-       psHWRTData->ui32ISPMtileSize            = ui32ISPMtileSize;
 
        OSLockAcquire(psDevInfo->hLockFreeList);
        for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
@@ -1444,15 +1381,14 @@ static PVRSRV_ERROR RGXCreateHWRTData_aux(
 
                if (ui16MaxRTs > 1)
                {
-                       PDUMPCOMMENT("Allocate memory for shadow render target cache");
+                       PDUMPCOMMENT(psDeviceNode, "Allocate memory for shadow render target cache");
                        eError = DevmemFwAllocate(psDevInfo,
                                        ui16MaxRTs * sizeof(IMG_UINT32),
                                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
                                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
                                        PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                                        PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-                                       PVRSRV_MEMALLOCFLAG_UNCACHED|
+                                       PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
                                        PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                                        PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
                                        "FwShadowRTCache",
@@ -1473,15 +1409,14 @@ static PVRSRV_ERROR RGXCreateHWRTData_aux(
                                        RFW_FWADDR_FLAG_NONE);
                        PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", FWAllocateRTArryFwAddrError);
 
-                       PDUMPCOMMENT("Allocate memory for tracking renders accumulation");
+                       PDUMPCOMMENT(psDeviceNode, "Allocate memory for tracking renders accumulation");
                        eError = DevmemFwAllocate(psDevInfo,
                                        ui16MaxRTs * sizeof(IMG_UINT32),
                                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
                                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
                                        PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                                        PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
-                                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
-                                       PVRSRV_MEMALLOCFLAG_UNCACHED|
+                                       PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
                                        PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                                        PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
                                        "FwRendersAccumulation",
@@ -1504,7 +1439,7 @@ static PVRSRV_ERROR RGXCreateHWRTData_aux(
        }
 
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump HWRTData 0x%08X", psKMHWRTDataSet->sHWRTDataFwAddr.ui32Addr);
+       PDUMPCOMMENT(psDeviceNode, "Dump HWRTData 0x%08X", psKMHWRTDataSet->sHWRTDataFwAddr.ui32Addr);
        DevmemPDumpLoadMem(psKMHWRTDataSet->psHWRTDataFwMemDesc, 0, sizeof(*psHWRTData), PDUMP_FLAGS_CONTINUOUS);
 #endif
 
@@ -1585,15 +1520,14 @@ static void RGXDestroyHWRTData_aux(RGX_KM_HW_RT_DATASET *psKMHWRTDataSet)
 /* Create set of HWRTData(s) and bind it with a shared FW HWRTDataCommon */
 PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
                PVRSRV_DEVICE_NODE      *psDeviceNode,
-               IMG_DEV_VIRTADDR        psVHeapTableDevVAddr,
-               IMG_DEV_VIRTADDR                psPMMListDevVAddr_0,
-               IMG_DEV_VIRTADDR                psPMMListDevVAddr_1,
-               RGX_FREELIST                    *apsFreeLists[RGXFW_MAX_FREELISTS],
+               IMG_DEV_VIRTADDR        asVHeapTableDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+               IMG_DEV_VIRTADDR                asPMMListDevVAddr[RGXMKIF_NUM_RTDATAS],
+               RGX_FREELIST                    *apsFreeLists[RGXMKIF_NUM_RTDATA_FREELISTS],
                IMG_UINT32           ui32ScreenPixelMax,
                IMG_UINT64           ui64MultiSampleCtl,
                IMG_UINT64           ui64FlippedMultiSampleCtl,
                IMG_UINT32           ui32TPCStride,
-               IMG_DEV_VIRTADDR                sTailPtrsDevVAddr,
+               IMG_DEV_VIRTADDR                asTailPtrsDevVAddr[RGXMKIF_NUM_GEOMDATAS],
                IMG_UINT32           ui32TPCSize,
                IMG_UINT32           ui32TEScreen,
                IMG_UINT32           ui32TEAA,
@@ -1606,18 +1540,16 @@ PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
                IMG_UINT32                 ui32ISPMergeUpperY,
                IMG_UINT32                 ui32ISPMergeScaleX,
                IMG_UINT32                 ui32ISPMergeScaleY,
-               IMG_DEV_VIRTADDR        sMacrotileArrayDevVAddr_0,
-               IMG_DEV_VIRTADDR        sMacrotileArrayDevVAddr_1,
-               IMG_DEV_VIRTADDR        sRgnHeaderDevVAddr_0,
-               IMG_DEV_VIRTADDR        sRgnHeaderDevVAddr_1,
-               IMG_DEV_VIRTADDR        sRTCDevVAddr,
-               IMG_UINT64                      uiRgnHeaderSize,
+               IMG_DEV_VIRTADDR        asMacrotileArrayDevVAddr[RGXMKIF_NUM_RTDATAS],
+               IMG_DEV_VIRTADDR        asRgnHeaderDevVAddr[RGXMKIF_NUM_RTDATAS],
+               IMG_DEV_VIRTADDR        asRTCDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+               IMG_UINT32                      uiRgnHeaderSize,
                IMG_UINT32                      ui32ISPMtileSize,
                IMG_UINT16                      ui16MaxRTs,
-               RGX_KM_HW_RT_DATASET **ppsKMHWRTDataSet_0,
-               RGX_KM_HW_RT_DATASET **ppsKMHWRTDataSet_1)
+               RGX_KM_HW_RT_DATASET *pasKMHWRTDataSet[RGXMKIF_NUM_RTDATAS])
 {
        PVRSRV_ERROR eError;
+       IMG_UINT32 ui32RTDataID;
        PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
 
        RGX_HWRTDATA_COMMON_COOKIE      *psHWRTDataCommonCookie;
@@ -1657,8 +1589,26 @@ PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
        PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", err_HWRTDataCommonVA);
 
        psHWRTDataCommon->bTACachesNeedZeroing = IMG_FALSE;
+       psHWRTDataCommon->ui32ScreenPixelMax    = ui32ScreenPixelMax;
+       psHWRTDataCommon->ui64MultiSampleCtl = ui64MultiSampleCtl;
+       psHWRTDataCommon->ui64FlippedMultiSampleCtl = ui64FlippedMultiSampleCtl;
+       psHWRTDataCommon->ui32TPCStride         = ui32TPCStride;
+       psHWRTDataCommon->ui32TPCSize           = ui32TPCSize;
+       psHWRTDataCommon->ui32TEScreen          = ui32TEScreen;
+       psHWRTDataCommon->ui32TEAA              = ui32TEAA;
+       psHWRTDataCommon->ui32TEMTILE1          = ui32TEMTILE1;
+       psHWRTDataCommon->ui32TEMTILE2          = ui32TEMTILE2;
+       psHWRTDataCommon->ui32MTileStride       = ui32MTileStride;
+       psHWRTDataCommon->ui32ISPMergeLowerX = ui32ISPMergeLowerX;
+       psHWRTDataCommon->ui32ISPMergeLowerY = ui32ISPMergeLowerY;
+       psHWRTDataCommon->ui32ISPMergeUpperX = ui32ISPMergeUpperX;
+       psHWRTDataCommon->ui32ISPMergeUpperY = ui32ISPMergeUpperY;
+       psHWRTDataCommon->ui32ISPMergeScaleX = ui32ISPMergeScaleX;
+       psHWRTDataCommon->ui32ISPMergeScaleY = ui32ISPMergeScaleY;
+       psHWRTDataCommon->uiRgnHeaderSize                       = uiRgnHeaderSize;
+       psHWRTDataCommon->ui32ISPMtileSize              = ui32ISPMtileSize;
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump HWRTDataCommon");
+       PDUMPCOMMENT(psDeviceNode, "Dump HWRTDataCommon");
        DevmemPDumpLoadMem(psHWRTDataCommonFwMemDesc, 0, sizeof(*psHWRTDataCommon), PDUMP_FLAGS_CONTINUOUS);
 #endif
        DevmemReleaseCpuVirtAddr(psHWRTDataCommonFwMemDesc);
@@ -1671,96 +1621,50 @@ PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
           the number of elements in the set equals RGXMKIF_NUM_RTDATAS.
        */
 
-       eError = RGXCreateHWRTData_aux(
-               psConnection,
-               psDeviceNode,
-               psVHeapTableDevVAddr,
-               psPMMListDevVAddr_0,
-               apsFreeLists,
-               ui32ScreenPixelMax,
-               ui64MultiSampleCtl,
-               ui64FlippedMultiSampleCtl,
-               ui32TPCStride,
-               sTailPtrsDevVAddr,
-               ui32TPCSize,
-               ui32TEScreen,
-               ui32TEAA,
-               ui32TEMTILE1,
-               ui32TEMTILE2,
-               ui32MTileStride,
-               ui32ISPMergeLowerX,
-               ui32ISPMergeLowerY,
-               ui32ISPMergeUpperX,
-               ui32ISPMergeUpperY,
-               ui32ISPMergeScaleX,
-               ui32ISPMergeScaleY,
-               sMacrotileArrayDevVAddr_0,
-               sRgnHeaderDevVAddr_0,
-               sRTCDevVAddr,
-               uiRgnHeaderSize,
-               ui32ISPMtileSize,
-               ui16MaxRTs,
-               psHWRTDataCommonCookie,
-               ppsKMHWRTDataSet_0);
-
-       if (eError != PVRSRV_OK)
+       for (ui32RTDataID = 0; ui32RTDataID < RGXMKIF_NUM_RTDATAS; ui32RTDataID++)
        {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Failed to create HWRTData [slot 0] (%s)",
-                               __func__,
-                               PVRSRVGetErrorString(eError)));
-               goto err_HWRTDataAlloc_0;
-       }
-       psHWRTDataCommonCookie->ui32RefCount += 1;
-
-       eError = RGXCreateHWRTData_aux(
-               psConnection,
-               psDeviceNode,
-               psVHeapTableDevVAddr,
-               psPMMListDevVAddr_1,
-               apsFreeLists,
-               ui32ScreenPixelMax,
-               ui64MultiSampleCtl,
-               ui64FlippedMultiSampleCtl,
-               ui32TPCStride,
-               sTailPtrsDevVAddr,
-               ui32TPCSize,
-               ui32TEScreen,
-               ui32TEAA,
-               ui32TEMTILE1,
-               ui32TEMTILE2,
-               ui32MTileStride,
-               ui32ISPMergeLowerX,
-               ui32ISPMergeLowerY,
-               ui32ISPMergeUpperX,
-               ui32ISPMergeUpperY,
-               ui32ISPMergeScaleX,
-               ui32ISPMergeScaleY,
-               sMacrotileArrayDevVAddr_1,
-               sRgnHeaderDevVAddr_1,
-               sRTCDevVAddr,
-               uiRgnHeaderSize,
-               ui32ISPMtileSize,
-               ui16MaxRTs,
-               psHWRTDataCommonCookie,
-               ppsKMHWRTDataSet_1);
+               eError = RGXCreateHWRTData_aux(
+                       psConnection,
+                       psDeviceNode,
+                       asVHeapTableDevVAddr[ui32RTDataID % RGXMKIF_NUM_GEOMDATAS],
+                       asPMMListDevVAddr[ui32RTDataID],
+                       &apsFreeLists[(ui32RTDataID % RGXMKIF_NUM_GEOMDATAS) * RGXFW_MAX_FREELISTS],
+                       asTailPtrsDevVAddr[ui32RTDataID % RGXMKIF_NUM_GEOMDATAS],
+                       asMacrotileArrayDevVAddr[ui32RTDataID],
+                       asRgnHeaderDevVAddr[ui32RTDataID],
+                       asRTCDevVAddr[ui32RTDataID % RGXMKIF_NUM_GEOMDATAS],
+                       ui16MaxRTs,
+                       psHWRTDataCommonCookie,
+                       &pasKMHWRTDataSet[ui32RTDataID]);
 
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: Failed to create HWRTData [slot 1] (%s)",
-                               __func__,
-                               PVRSRVGetErrorString(eError)));
-               goto err_HWRTDataAlloc_1;
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to create HWRTData [slot %u] (%s)",
+                                       __func__,
+                                       ui32RTDataID,
+                                       PVRSRVGetErrorString(eError)));
+                       goto err_HWRTDataAlloc;
+               }
+               psHWRTDataCommonCookie->ui32RefCount += 1;
        }
-       psHWRTDataCommonCookie->ui32RefCount += 1;
 
        return PVRSRV_OK;
 
-err_HWRTDataAlloc_1:
-       RGXDestroyHWRTData_aux(*ppsKMHWRTDataSet_0);
-       *ppsKMHWRTDataSet_0 = NULL;
-err_HWRTDataAlloc_0:
+err_HWRTDataAlloc:
+       PVR_DPF((PVR_DBG_WARNING, "%s: err_HWRTDataAlloc %u",
+                        __func__, psHWRTDataCommonCookie->ui32RefCount));
+       if (pasKMHWRTDataSet)
+       {
+               for (ui32RTDataID = psHWRTDataCommonCookie->ui32RefCount; ui32RTDataID > 0; ui32RTDataID--)
+               {
+                       if (pasKMHWRTDataSet[ui32RTDataID-1] != NULL)
+                       {
+                               RGXDestroyHWRTData_aux(pasKMHWRTDataSet[ui32RTDataID-1]);
+                               pasKMHWRTDataSet[ui32RTDataID-1] = NULL;
+                       }
+               }
+       }
 err_HWRTDataCommonVA:
        RGXUnsetFirmwareAddress(psHWRTDataCommonFwMemDesc);
 err_HWRTDataCommonFwAddr:
@@ -1796,7 +1700,7 @@ PVRSRV_ERROR RGXDestroyHWRTDataSet(RGX_KM_HW_RT_DATASET *psKMHWRTDataSet)
 
        /* Cleanup HWRTData */
        eError = RGXFWRequestHWRTDataCleanUp(psDevNode, psHWRTData);
-       if (eError == PVRSRV_ERROR_RETRY)
+       if (eError != PVRSRV_OK)
        {
                return eError;
        }
@@ -1906,6 +1810,7 @@ PVRSRV_ERROR RGXCreateFreeList(CONNECTION_DATA      *psConnection,
        eError = DevmemFwAllocate(psDevInfo,
                        sizeof(*psFWFreeList),
                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
                        PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                        PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                        PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
@@ -2007,19 +1912,19 @@ PVRSRV_ERROR RGXCreateFreeList(CONNECTION_DATA      *psConnection,
                        sFreeListDevVAddr.uiAddr,
                        psFWFreeList->ui64CurrentDevVAddr));
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump FW FreeList");
+       PDUMPCOMMENT(psDeviceNode, "Dump FW FreeList");
        DevmemPDumpLoadMem(psFreeList->psFWFreelistMemDesc, 0, sizeof(*psFWFreeList), PDUMP_FLAGS_CONTINUOUS);
 
        /*
         * Separate dump of the Freelist's number of Pages and stack pointer.
         * This allows to easily modify the PB size in the out2.txt files.
         */
-       PDUMPCOMMENT("FreeList TotalPages");
+       PDUMPCOMMENT(psDeviceNode, "FreeList TotalPages");
        DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
                        offsetof(RGXFWIF_FREELIST, ui32CurrentPages),
                        psFWFreeList->ui32CurrentPages,
                        PDUMP_FLAGS_CONTINUOUS);
-       PDUMPCOMMENT("FreeList StackPointer");
+       PDUMPCOMMENT(psDeviceNode, "FreeList StackPointer");
        DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
                        offsetof(RGXFWIF_FREELIST, ui32CurrentStackTop),
                        psFWFreeList->ui32CurrentStackTop,
@@ -2214,10 +2119,11 @@ PVRSRV_ERROR RGXCreateZSBufferKM(CONNECTION_DATA * psConnection,
        }
 
        /* Allocate firmware memory for ZS-Buffer. */
-       PDUMPCOMMENT("Allocate firmware ZS-Buffer data structure");
+       PDUMPCOMMENT(psDeviceNode, "Allocate firmware ZS-Buffer data structure");
        eError = DevmemFwAllocate(psDevInfo,
                        sizeof(*psFWZSBuffer),
                        PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
                        PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
                        PVRSRV_MEMALLOCFLAG_GPU_READABLE |
                        PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
@@ -2262,7 +2168,7 @@ PVRSRV_ERROR RGXCreateZSBufferKM(CONNECTION_DATA * psConnection,
 
        /* Dump the ZS-Buffer and the memory content */
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump firmware ZS-Buffer");
+       PDUMPCOMMENT(psDeviceNode, "Dump firmware ZS-Buffer");
        DevmemPDumpLoadMem(psFWZSBufferMemDesc, 0, sizeof(*psFWZSBuffer), PDUMP_FLAGS_CONTINUOUS);
 #endif
 
@@ -2311,7 +2217,7 @@ PVRSRV_ERROR RGXDestroyZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer)
        /* Request ZS Buffer cleanup */
        eError = RGXFWRequestZSBufferCleanUp(psZSBuffer->psDevInfo,
                        psZSBuffer->sZSBufferFWDevVAddr);
-       if (eError != PVRSRV_ERROR_RETRY)
+       if (eError == PVRSRV_OK)
        {
                /* Free the firmware render context. */
                RGXUnsetFirmwareAddress(psZSBuffer->psFWZSBufferMemDesc);
@@ -2588,7 +2494,6 @@ void RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
                        eError = RGXScheduleCommand(psDevInfo,
                                        RGXFWIF_DM_GEOM,
                                        &sTACCBCmd,
-                                       0,
                                        PDUMP_FLAGS_NONE);
                        if (eError != PVRSRV_ERROR_RETRY)
                        {
@@ -2650,7 +2555,6 @@ void RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
                        eError = RGXScheduleCommand(psDevInfo,
                                        RGXFWIF_DM_GEOM,
                                        &sTACCBCmd,
-                                       0,
                                        PDUMP_FLAGS_NONE);
                        if (eError != PVRSRV_ERROR_RETRY)
                        {
@@ -2678,6 +2582,7 @@ PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
                IMG_UINT32 ui32AllocatedOffset,
                DEVMEM_MEMDESC *psFWMemContextMemDesc,
                IMG_DEV_VIRTADDR sVDMCallStackAddr,
+               IMG_UINT32 ui32CallStackDepth,
                IMG_UINT32 ui32Priority,
                IMG_UINT32 ui32MaxDeadlineMS,
                IMG_UINT64 ui64RobustnessAddress,
@@ -2689,12 +2594,13 @@ PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        RGXFWIF_TACTX_STATE *psContextState;
+       IMG_UINT32 uiCoreIdx;
        PVRSRV_ERROR eError;
        /*
                Allocate device memory for the firmware GPU context suspend state.
                Note: the FW reads/writes the state to memory by accessing the GPU register interface.
         */
-       PDUMPCOMMENT("Allocate RGX firmware TA context suspend state");
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware TA context suspend state");
 
        eError = DevmemFwAllocate(psDevInfo,
                        sizeof(RGXFWIF_TACTX_STATE),
@@ -2720,7 +2626,13 @@ PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
                                PVRSRVGetErrorString(eError)));
                goto fail_suspendcpuvirtacquire;
        }
-       psContextState->uTAReg_VDM_CALL_STACK_POINTER_Init = sVDMCallStackAddr.uiAddr;
+
+       for (uiCoreIdx = 0; uiCoreIdx < RGX_NUM_GEOM_CORES; uiCoreIdx++)
+       {
+               psContextState->asGeomCore[uiCoreIdx].uTAReg_VDM_CALL_STACK_POINTER_Init =
+                       sVDMCallStackAddr.uiAddr + (uiCoreIdx * ui32CallStackDepth * sizeof(IMG_UINT64));
+       }
+
        DevmemReleaseCpuVirtAddr(psTAData->psContextStateMemDesc);
 
        eError = FWCommonContextAllocate(psConnection,
@@ -2753,7 +2665,7 @@ PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
         * Dump the FW 3D context suspend state buffer
         */
 #if defined(PDUMP)
-       PDUMPCOMMENT("Dump the TA context suspend state buffer");
+       PDUMPCOMMENT(psDeviceNode, "Dump the TA context suspend state buffer");
        DevmemPDumpLoadMem(psTAData->psContextStateMemDesc,
                        0,
                        sizeof(RGXFWIF_TACTX_STATE),
@@ -2796,7 +2708,7 @@ PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
                Allocate device memory for the firmware GPU context suspend state.
                Note: the FW reads/writes the state to memory by accessing the GPU register interface.
         */
-       PDUMPCOMMENT("Allocate RGX firmware 3D context suspend state");
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware 3D context suspend state");
 
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, XE_MEMORY_HIERARCHY))
        {
@@ -2862,7 +2774,7 @@ PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
        /*
         * Dump the FW 3D context suspend state buffer
         */
-       PDUMPCOMMENT("Dump the 3D context suspend state buffer");
+       PDUMPCOMMENT(psDeviceNode, "Dump the 3D context suspend state buffer");
        DevmemPDumpLoadMem(ps3DData->psContextStateMemDesc,
                        0,
                        sizeof(RGXFWIF_3DCTX_STATE),
@@ -2887,6 +2799,7 @@ PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                               *psConnection,
                PVRSRV_DEVICE_NODE                      *psDeviceNode,
                IMG_UINT32                                      ui32Priority,
                IMG_DEV_VIRTADDR                        sVDMCallStackAddr,
+               IMG_UINT32                                      ui32CallStackDepth,
                IMG_UINT32                                      ui32FrameworkRegisterSize,
                IMG_PBYTE                                       pabyFrameworkRegisters,
                IMG_HANDLE                                      hMemCtxPrivData,
@@ -2964,7 +2877,8 @@ PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                               *psConnection,
                }
 
                /* Copy the Framework client data into the framework buffer */
-               eError = PVRSRVRGXFrameworkCopyCommand(psRenderContext->psFWFrameworkMemDesc,
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psRenderContext->psFWFrameworkMemDesc,
                                pabyFrameworkRegisters,
                                ui32FrameworkRegisterSize);
                if (eError != PVRSRV_OK)
@@ -3003,6 +2917,7 @@ PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                               *psConnection,
                        offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),
                        psFWMemContextMemDesc,
                        sVDMCallStackAddr,
+                       ui32CallStackDepth,
                        ui32Priority,
                        ui32MaxTADeadlineMS,
                        ui64RobustnessAddress,
@@ -3350,7 +3265,6 @@ static void DumpUfoList(IMG_UINT32 ui32ClientTAFenceCount,
  * PVRSRVRGXKickTA3DKM
  */
 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT     *psRenderContext,
-               IMG_UINT32                                      ui32ClientCacheOpSeqNum,
                IMG_UINT32                                      ui32ClientTAFenceCount,
                SYNC_PRIMITIVE_BLOCK            **apsClientTAFenceSyncPrimBlock,
                IMG_UINT32                                      *paui32ClientTAFenceSyncOffset,
@@ -3409,7 +3323,7 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
        RGXFWIF_UFO                             sPRUFO;
        IMG_UINT32                              i;
        PVRSRV_ERROR                    eError = PVRSRV_OK;
-       PVRSRV_ERROR                    eError2;
+       PVRSRV_ERROR                    eError2 = PVRSRV_OK;
 
        PVRSRV_RGXDEV_INFO      *psDevInfo = FWCommonContextGetRGXDevInfo(psRenderContext->s3DData.psServerCommonContext);
        IMG_UINT32              ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
@@ -3880,6 +3794,7 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                          __func__, ui32TAFenceCount, ui32TAUpdateCount));
 
                RGXCmdHelperInitCmdCCB_CommandSize(
+                       psDevInfo,
                    0,
                    ui32TAFenceCount,
                    ui32TAUpdateCount,
@@ -3898,6 +3813,7 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                          ui323DFenceCount));
 
                RGXCmdHelperInitCmdCCB_CommandSize(
+                       psDevInfo,
                        0,
                    ui323DFenceCount,
                    0,
@@ -3916,6 +3832,7 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                          ui32PRUpdateCount));
 
                RGXCmdHelperInitCmdCCB_CommandSize(
+                       psDevInfo,
                    0,
                    0,
                    ui32PRUpdateCount,
@@ -3939,6 +3856,7 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                }
 
                RGXCmdHelperInitCmdCCB_CommandSize(
+                       psDevInfo,
                        0,
                        bKickTA ? 0 : ui323DFenceCount,
                    ui323DUpdateCount,
@@ -5010,7 +4928,6 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                                eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
                                                RGXFWIF_DM_GEOM,
                                                &sTAKCCBCmd,
-                                               ui32ClientCacheOpSeqNum,
                                                ui32PDumpFlags);
                                if (eError2 != PVRSRV_ERROR_RETRY)
                                {
@@ -5020,6 +4937,16 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT       *psRenderContext,
                        } END_LOOP_UNTIL_TIMEOUT();
                }
 
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKicKTA3DKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_taacquirecmd;
+               }
+
                PVRGpuTraceEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
                                        ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
                                        RGX_HWPERF_KICK_TYPE_TA3D);
@@ -5102,7 +5029,6 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT        *psRenderContext,
                        eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
                                        RGXFWIF_DM_3D,
                                        &s3DKCCBCmd,
-                                       ui32ClientCacheOpSeqNum,
                                        ui32PDumpFlags);
                        if (eError2 != PVRSRV_ERROR_RETRY)
                        {
@@ -5112,6 +5038,15 @@ PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT       *psRenderContext,
                } END_LOOP_UNTIL_TIMEOUT();
        }
 
+       if (eError2 != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKicKTA3DKM failed to schedule kernel CCB command. (0x%x)", eError2));
+               if (eError == PVRSRV_OK)
+               {
+                       eError = eError2;
+               }
+       }
+
        /*
         * Now check eError (which may have returned an error from our earlier calls
         * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
@@ -5284,6 +5219,10 @@ err_not_enough_space:
         * resolved input fence.
         * NOTE: 3D fence is always submitted, either via 3D or TA(PR).
         */
+#if defined(SUPPORT_BUFFER_SYNC)
+       SyncAddrListDeRefCheckpoints(ui32BufferFenceSyncCheckpointCount,
+                                    apsBufferFenceSyncCheckpoints);
+#endif
        SyncAddrListDeRefCheckpoints(ui32Fence3DSyncCheckpointCount, apsFence3DSyncCheckpoints);
 fail_resolve_input_3d_fence:
        if (bKickTA)
@@ -5390,24 +5329,23 @@ PVRSRV_ERROR PVRSRVRGXSetRenderContextPropertyKM(RGX_SERVER_RENDER_CONTEXT *psRe
                                                  IMG_UINT64 ui64Input,
                                                  IMG_UINT64 *pui64Output)
 {
-       PVRSRV_ERROR eError;
-       PVRSRV_ERROR eError2 = PVRSRV_OK;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (eContextProperty)
        {
                case RGX_CONTEXT_PROPERTY_FLAGS:
                {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
                        OSLockAcquire(psRenderContext->hLock);
                        eError = FWCommonContextSetFlags(psRenderContext->sTAData.psServerCommonContext,
-                                                        (IMG_UINT32)ui64Input);
+                                                        ui32ContextFlags);
                        if (eError == PVRSRV_OK)
                        {
-                               eError2 = FWCommonContextSetFlags(psRenderContext->s3DData.psServerCommonContext,
-                                                                 (IMG_UINT32)ui64Input);
+                               eError = FWCommonContextSetFlags(psRenderContext->s3DData.psServerCommonContext,
+                                                            ui32ContextFlags);
                        }
                        OSLockRelease(psRenderContext->hLock);
-                       PVR_LOG_IF_ERROR(eError, "FWCommonContextSetFlags eError");
-                       PVR_LOG_IF_ERROR(eError2, "FWCommonContextSetFlags eError2");
                        break;
                }
 
index 33d315c..89a5b22 100644 (file)
@@ -225,15 +225,14 @@ IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList);
 /* Create set of HWRTData(s) */
 PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
                                                           PVRSRV_DEVICE_NODE   *psDeviceNode,
-                                                          IMG_DEV_VIRTADDR             psVHeapTableDevVAddr,
-                                                          IMG_DEV_VIRTADDR             psPMMListDevVAddr_0,
-                                                          IMG_DEV_VIRTADDR             psPMMListDevVAddr_1,
-                                                          RGX_FREELIST                 *apsFreeLists[RGXFW_MAX_FREELISTS],
+                                                          IMG_DEV_VIRTADDR             asVHeapTableDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+                                                          IMG_DEV_VIRTADDR             psPMMListDevVAddr[RGXMKIF_NUM_RTDATAS],
+                                                          RGX_FREELIST                 *apsFreeLists[RGXMKIF_NUM_RTDATA_FREELISTS],
                                                           IMG_UINT32                   ui32ScreenPixelMax,
                                                           IMG_UINT64                   ui64MultiSampleCtl,
                                                           IMG_UINT64                   ui64FlippedMultiSampleCtl,
                                                           IMG_UINT32                   ui32TPCStride,
-                                                          IMG_DEV_VIRTADDR             sTailPtrsDevVAddr,
+                                                          IMG_DEV_VIRTADDR             asTailPtrsDevVAddr[RGXMKIF_NUM_GEOMDATAS],
                                                           IMG_UINT32                   ui32TPCSize,
                                                           IMG_UINT32                   ui32TEScreen,
                                                           IMG_UINT32                   ui32TEAA,
@@ -246,16 +245,13 @@ PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA *psConnection,
                                                           IMG_UINT32                   ui32ISPMergeUpperY,
                                                           IMG_UINT32                   ui32ISPMergeScaleX,
                                                           IMG_UINT32                   ui32ISPMergeScaleY,
-                                                          IMG_DEV_VIRTADDR             sMacrotileArrayDevVAddr_0,
-                                                          IMG_DEV_VIRTADDR             sMacrotileArrayDevVAddr_1,
-                                                          IMG_DEV_VIRTADDR             sRgnHeaderDevVAddr_0,
-                                                          IMG_DEV_VIRTADDR             sRgnHeaderDevVAddr_1,
-                                                          IMG_DEV_VIRTADDR             sRTCDevVAddr,
-                                                          IMG_UINT64                   uiRgnHeaderSize,
+                                                          IMG_DEV_VIRTADDR             sMacrotileArrayDevVAddr[RGXMKIF_NUM_RTDATAS],
+                                                          IMG_DEV_VIRTADDR             sRgnHeaderDevVAddr[RGXMKIF_NUM_RTDATAS],
+                                                          IMG_DEV_VIRTADDR             asRTCDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+                                                          IMG_UINT32                   uiRgnHeaderSize,
                                                           IMG_UINT32                   ui32ISPMtileSize,
                                                           IMG_UINT16                   ui16MaxRTs,
-                                                          RGX_KM_HW_RT_DATASET **ppsKMHWRTDataSet_0,
-                                                          RGX_KM_HW_RT_DATASET **ppsKMHWRTDataSet_1);
+                                                          RGX_KM_HW_RT_DATASET *pasKMHWRTDataSet[RGXMKIF_NUM_RTDATAS]);
 
 /* Destroy HWRTDataSet */
 PVRSRV_ERROR RGXDestroyHWRTDataSet(RGX_KM_HW_RT_DATASET *psKMHWRTDataSet);
@@ -353,7 +349,7 @@ void RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
 /* Reconstruct free list after Hardware Recovery */
 void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
                                                                                          IMG_UINT32 ui32FreelistsCount,
-                                                                                         IMG_UINT32 *paui32Freelists);
+                                                                                         const IMG_UINT32 *paui32Freelists);
 
 /*!
 *******************************************************************************
@@ -367,6 +363,7 @@ void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
  @Input psDeviceNode - device node
  @Input ui32Priority - context priority
  @Input sVDMCallStackAddr - VDM call stack device virtual address
+ @Input ui32CallStackDepth - VDM call stack depth
  @Input ui32FrameworkCommandSize - framework command size
  @Input pabyFrameworkCommand - ptr to framework command
  @Input hMemCtxPrivData - memory context private data
@@ -387,6 +384,7 @@ PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                         *psConnection,
                                                                                        PVRSRV_DEVICE_NODE                      *psDeviceNode,
                                                                                        IMG_UINT32                                      ui32Priority,
                                                                                        IMG_DEV_VIRTADDR                        sVDMCallStackAddr,
+                                                                                       IMG_UINT32                                      ui32CallStackDepth,
                                                                                        IMG_UINT32                                      ui32FrameworkCommandSize,
                                                                                        IMG_PBYTE                                       pabyFrameworkCommand,
                                                                                        IMG_HANDLE                                      hMemCtxPrivData,
@@ -432,7 +430,6 @@ PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRender
 
 ******************************************************************************/
 PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT     *psRenderContext,
-                                                                IMG_UINT32                                     ui32ClientCacheOpSeqNum,
                                                                 IMG_UINT32                                     ui32ClientTAFenceCount,
                                                                 SYNC_PRIMITIVE_BLOCK           **apsClientTAFenceSyncPrimBlock,
                                                                 IMG_UINT32                                     *paui32ClientTAFenceSyncOffset,
index 85647bb..f341464 100644 (file)
@@ -61,9 +61,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "ospvr_gputrace.h"
 #include "htbuffer.h"
 #include "rgxshader.h"
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
-
 
 #include "pdump_km.h"
 
@@ -127,7 +124,8 @@ static PVRSRV_ERROR _CreateTDMTransferContext(
                RGX_SERVER_TQ_TDM_DATA  * psTDMData,
                IMG_UINT32                                ui32CCBAllocSizeLog2,
                IMG_UINT32                                ui32CCBMaxAllocSizeLog2,
-               IMG_UINT32                                ui32ContextFlags)
+               IMG_UINT32                                ui32ContextFlags,
+               IMG_UINT64                ui64RobustnessAddress)
 {
        PVRSRV_ERROR eError;
 
@@ -161,7 +159,7 @@ static PVRSRV_ERROR _CreateTDMTransferContext(
                        ui32ContextFlags,
                        ui32Priority,
                        UINT_MAX, /* max deadline MS */
-                       0, /* robustness address */
+                       ui64RobustnessAddress,
                        psInfo,
                        &psTDMData->psServerCommonContext);
        if (eError != PVRSRV_OK)
@@ -230,6 +228,7 @@ PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
                IMG_HANDLE                   hMemCtxPrivData,
                IMG_UINT32                                       ui32PackedCCBSizeU88,
                IMG_UINT32                   ui32ContextFlags,
+               IMG_UINT64                   ui64RobustnessAddress,
                RGX_SERVER_TQ_TDM_CONTEXT ** ppsTransferContext)
 {
        RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext;
@@ -291,7 +290,8 @@ PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
                }
 
                /* Copy the Framework client data into the framework buffer */
-               eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc,
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psTransferContext->psFWFrameworkMemDesc,
                                pabyFrameworkCommand,
                                ui32FrameworkCommandSize);
                if (eError != PVRSRV_OK)
@@ -316,7 +316,8 @@ PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
                                           &psTransferContext->sTDMData,
                                                                           U32toU8_Unpack1(ui32PackedCCBSizeU88),
                                                                           U32toU8_Unpack2(ui32PackedCCBSizeU88),
-                                          ui32ContextFlags);
+                                          ui32ContextFlags,
+                                          ui64RobustnessAddress);
        if (eError != PVRSRV_OK)
        {
                goto fail_tdmtransfercontext;
@@ -376,11 +377,6 @@ PVRSRV_ERROR PVRSRVRGXTDMReleaseSharedMemoryKM(PMR * psPMRMem)
 
 PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext)
 {
-#if defined(SUPPORT_WORKLOAD_ESTIMATION)
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
-#endif
        PVRSRV_ERROR eError;
        PVRSRV_RGXDEV_INFO *psDevInfo = psTransferContext->psDeviceNode->pvDevice;
 #if defined(SUPPORT_WORKLOAD_ESTIMATION)
@@ -399,15 +395,6 @@ PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psT
                                        PVRSRVGetErrorString(eError)));
                        return eError;
                }
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psTransferContext->psFWTransferContextMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psFWTransferContext - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-               }
-#endif
 
                ui32WorkEstCCBSubmitted = psFWTransferContext->ui32WorkEstCCBSubmitted;
 
@@ -482,7 +469,6 @@ fail_destroyTDM:
 PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
                RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext,
                IMG_UINT32                  ui32PDumpFlags,
-               IMG_UINT32                  ui32ClientCacheOpSeqNum,
                IMG_UINT32                  ui32ClientUpdateCount,
                SYNC_PRIMITIVE_BLOCK     ** pauiClientUpdateUFODevVarBlock,
                IMG_UINT32                * paui32ClientUpdateSyncOffset,
@@ -930,7 +916,8 @@ PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
                /*
                        Create the command helper data for this command
                */
-               RGXCmdHelperInitCmdCCB(psClientCCB,
+               RGXCmdHelperInitCmdCCB(psDevInfo,
+                                      psClientCCB,
                                       0,
                                       ui32IntClientFenceCount,
                                       pauiIntFenceUFOAddress,
@@ -1057,7 +1044,6 @@ PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
                        eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
                                                     RGXFWIF_DM_TDM,
                                                     & sTDMKCCBCmd,
-                                                    ui32ClientCacheOpSeqNum,
                                                     ui32PDumpFlags);
                        if (eError2 != PVRSRV_ERROR_RETRY)
                        {
@@ -1066,6 +1052,16 @@ PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
                        OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
                } END_LOOP_UNTIL_TIMEOUT();
 
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXTDMSubmitTransferKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_2dcmdacquire;
+               }
+
                PVRGpuTraceEnqueueEvent(psDeviceNode->pvDevice, ui32FWAddr, ui32ExtJobRef,
                                        ui32IntJobRef, RGX_HWPERF_KICK_TYPE_TQTDM);
        }
@@ -1203,7 +1199,6 @@ PVRSRV_ERROR PVRSRVRGXTDMNotifyWriteOffsetUpdateKM(
                eError = RGXScheduleCommand(psTransferContext->psDeviceNode->pvDevice,
                                            RGXFWIF_DM_TDM,
                                            &sKCCBCmd,
-                                           0,
                                            ui32PDumpFlags);
                if (eError != PVRSRV_ERROR_RETRY)
                {
@@ -1259,21 +1254,18 @@ PVRSRV_ERROR PVRSRVRGXTDMSetTransferContextPropertyKM(RGX_SERVER_TQ_TDM_CONTEXT
                                                                                                          IMG_UINT64 ui64Input,
                                                                                                          IMG_UINT64 *pui64Output)
 {
-       PVRSRV_ERROR eError;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (eContextProperty)
        {
                case RGX_CONTEXT_PROPERTY_FLAGS:
                {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
                        OSLockAcquire(psTransferContext->hLock);
                        eError = FWCommonContextSetFlags(psTransferContext->sTDMData.psServerCommonContext,
-                                                        (IMG_UINT32)ui64Input);
-                       if (eError == PVRSRV_OK)
-                       {
-                               psTransferContext->ui32Flags = (IMG_UINT32)ui64Input;
-                       }
+                                                        ui32ContextFlags);
                        OSLockRelease(psTransferContext->hLock);
-                       PVR_LOG_IF_ERROR(eError, "FWCommonContextSetFlags");
                        break;
                }
 
index a691cf0..91b3b8d 100644 (file)
@@ -137,7 +137,8 @@ static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
                                                                                         RGX_SERVER_TQ_3D_DATA *ps3DData,
                                                                                         IMG_UINT32 ui32CCBAllocSizeLog2,
                                                                                         IMG_UINT32 ui32CCBMaxAllocSizeLog2,
-                                                                                        IMG_UINT32 ui32ContextFlags)
+                                                                                        IMG_UINT32 ui32ContextFlags,
+                                                                                        IMG_UINT64 ui64RobustnessAddress)
 {
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        PVRSRV_ERROR eError;
@@ -147,7 +148,7 @@ static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
                Allocate device memory for the firmware GPU context suspend state.
                Note: the FW reads/writes the state to memory by accessing the GPU register interface.
        */
-       PDUMPCOMMENT("Allocate RGX firmware TQ/3D context suspend state");
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware TQ/3D context suspend state");
 
        if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, XE_MEMORY_HIERARCHY))
        {
@@ -198,7 +199,7 @@ static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
                                         ui32ContextFlags,
                                         ui32Priority,
                                         UINT_MAX, /* max deadline MS */
-                                        0, /* robustness address */
+                                        ui64RobustnessAddress,
                                         psInfo,
                                         &ps3DData->psServerCommonContext);
        if (eError != PVRSRV_OK)
@@ -207,7 +208,7 @@ static PVRSRV_ERROR _Create3DTransferContext(CONNECTION_DATA *psConnection,
        }
 
 
-       PDUMPCOMMENT("Dump 3D context suspend state buffer");
+       PDUMPCOMMENT(psDeviceNode, "Dump 3D context suspend state buffer");
        DevmemPDumpLoadMem(ps3DData->psFWContextStateMemDesc, 0, sizeof(RGXFWIF_3DCTX_STATE), PDUMP_FLAGS_CONTINUOUS);
 
        ps3DData->ui32Priority = ui32Priority;
@@ -226,6 +227,7 @@ fail_buffer_sync_context_create:
 }
 
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
 static PVRSRV_ERROR _Create2DTransferContext(CONNECTION_DATA *psConnection,
                                                                                         PVRSRV_DEVICE_NODE *psDeviceNode,
                                                                                         DEVMEM_MEMDESC *psFWMemContextMemDesc,
@@ -234,7 +236,8 @@ static PVRSRV_ERROR _Create2DTransferContext(CONNECTION_DATA *psConnection,
                                                                                         RGX_SERVER_TQ_2D_DATA *ps2DData,
                                                                                         IMG_UINT32 ui32CCBAllocSizeLog2,
                                                                                         IMG_UINT32 ui32CCBMaxAllocSizeLog2,
-                                                                                        IMG_UINT32 ui32ContextFlags)
+                                                                                        IMG_UINT32 ui32ContextFlags,
+                                                                                        IMG_UINT64 ui64RobustnessAddress)
 {
        PVRSRV_ERROR eError;
 
@@ -267,7 +270,7 @@ static PVRSRV_ERROR _Create2DTransferContext(CONNECTION_DATA *psConnection,
                                         ui32ContextFlags,
                                         ui32Priority,
                                         UINT_MAX, /* max deadline MS */
-                                        0, /* robustness address */
+                                        ui64RobustnessAddress,
                                         psInfo,
                                         &ps2DData->psServerCommonContext);
        if (eError != PVRSRV_OK)
@@ -312,7 +315,7 @@ static PVRSRV_ERROR _Destroy2DTransferContext(RGX_SERVER_TQ_2D_DATA *ps2DData,
                return eError;
        }
 
-       /* ... it has so we can free it's resources */
+       /* ... it has so we can free its resources */
        FWCommonContextFree(ps2DData->psServerCommonContext);
        ps2DData->psServerCommonContext = NULL;
 
@@ -323,6 +326,7 @@ static PVRSRV_ERROR _Destroy2DTransferContext(RGX_SERVER_TQ_2D_DATA *ps2DData,
 
        return PVRSRV_OK;
 }
+#endif /* #if defined(RGX_FEATURE_TLA_BIT_MASK) */
 
 static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData,
                                                                                          PVRSRV_DEVICE_NODE *psDeviceNode,
@@ -347,7 +351,7 @@ static PVRSRV_ERROR _Destroy3DTransferContext(RGX_SERVER_TQ_3D_DATA *ps3DData,
                return eError;
        }
 
-       /* ... it has so we can free it's resources */
+       /* ... it has so we can free its resources */
        DevmemFwUnmapAndFree(psDeviceNode->pvDevice, ps3DData->psFWContextStateMemDesc);
        FWCommonContextFree(ps3DData->psServerCommonContext);
        ps3DData->psServerCommonContext = NULL;
@@ -372,6 +376,7 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA               *psConnection,
                                                                                   IMG_HANDLE                           hMemCtxPrivData,
                                                                                   IMG_UINT32                           ui32PackedCCBSizeU8888,
                                                                                   IMG_UINT32                           ui32ContextFlags,
+                                                                                  IMG_UINT64                           ui64RobustnessAddress,
                                                                                   RGX_SERVER_TQ_CONTEXT        **ppsTransferContext,
                                                                                   PMR                                          **ppsCLIPMRMem,
                                                                                   PMR                                          **ppsUSCPMRMem)
@@ -379,7 +384,7 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA               *psConnection,
        RGX_SERVER_TQ_CONTEXT   *psTransferContext;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        DEVMEM_MEMDESC                  *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
-       RGX_COMMON_CONTEXT_INFO sInfo;
+       RGX_COMMON_CONTEXT_INFO sInfo = {NULL};
        PVRSRV_ERROR                    eError = PVRSRV_OK;
 
        /* Allocate the server side structure */
@@ -434,7 +439,8 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA               *psConnection,
                }
 
                /* Copy the Framework client data into the framework buffer */
-               eError = PVRSRVRGXFrameworkCopyCommand(psTransferContext->psFWFrameworkMemDesc,
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psTransferContext->psFWFrameworkMemDesc,
                                pabyFrameworkCommand,
                                ui32FrameworkCommandSize);
                if (eError != PVRSRV_OK)
@@ -459,13 +465,15 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA             *psConnection,
                                                                          &psTransferContext->s3DData,
                                                                          U32toU8_Unpack3(ui32PackedCCBSizeU8888),
                                                                          U32toU8_Unpack4(ui32PackedCCBSizeU8888),
-                                                                         ui32ContextFlags);
+                                                                         ui32ContextFlags,
+                                                                         ui64RobustnessAddress);
        if (eError != PVRSRV_OK)
        {
                goto fail_3dtransfercontext;
        }
        psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_3D;
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA))
        {
                eError = _Create2DTransferContext(psConnection,
@@ -476,13 +484,15 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA             *psConnection,
                                                                                  &psTransferContext->s2DData,
                                                                                  U32toU8_Unpack1(ui32PackedCCBSizeU8888),
                                                                                  U32toU8_Unpack2(ui32PackedCCBSizeU8888),
-                                                                                 ui32ContextFlags);
+                                                                                 ui32ContextFlags,
+                                                                                 ui64RobustnessAddress);
                if (eError != PVRSRV_OK)
                {
                        goto fail_2dtransfercontext;
                }
                psTransferContext->ui32Flags |= RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
        }
+#endif
 
        PVRSRVTQAcquireShaders(psDeviceNode, ppsCLIPMRMem, ppsUSCPMRMem);
 
@@ -497,10 +507,12 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA             *psConnection,
 
        return PVRSRV_OK;
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
 fail_2dtransfercontext:
        _Destroy3DTransferContext(&psTransferContext->s3DData,
                                                          psTransferContext->psDeviceNode,
                                                          psTransferContext->ui32PDumpFlags);
+#endif
 fail_3dtransfercontext:
 fail_frameworkcopy:
        if (psTransferContext->psFWFrameworkMemDesc)
@@ -532,6 +544,7 @@ PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransfer
        dllist_remove_node(&(psTransferContext->sListNode));
        OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if ((psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) &&
                        (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
        {
@@ -545,6 +558,7 @@ PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransfer
                /* We've freed the 2D context, don't try to free it again */
                psTransferContext->ui32Flags &= ~RGX_SERVER_TQ_CONTEXT_FLAGS_2D;
        }
+#endif
 
        if (psTransferContext->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D)
        {
@@ -580,8 +594,10 @@ PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransfer
        return PVRSRV_OK;
 
 fail_destroy3d:
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
 
 fail_destroy2d:
+#endif
        OSWRLockAcquireWrite(psDevInfo->hTransferCtxListLock);
        dllist_add_to_tail(&(psDevInfo->sTransferCtxtListHead), &(psTransferContext->sListNode));
        OSWRLockReleaseWrite(psDevInfo->hTransferCtxListLock);
@@ -593,7 +609,6 @@ fail_destroy2d:
  * PVRSRVSubmitTQ3DKickKM
  */
 PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT   *psTransferContext,
-                                                                          IMG_UINT32                           ui32ClientCacheOpSeqNum,
                                                                           IMG_UINT32                           ui32PrepareCount,
                                                                           IMG_UINT32                           *paui32ClientUpdateCount,
                                                                           SYNC_PRIMITIVE_BLOCK         ***papauiClientUpdateUFODevVarBlock,
@@ -616,30 +631,38 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
        PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode;
        PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
        RGX_CCB_CMD_HELPER_DATA *pas3DCmdHelper;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        RGX_CCB_CMD_HELPER_DATA *pas2DCmdHelper;
+#endif
        IMG_UINT32 ui323DCmdCount = 0;
-       IMG_UINT32 ui322DCmdCount = 0;
        IMG_UINT32 ui323DCmdLast = 0;
-       IMG_UINT32 ui322DCmdLast = 0;
        IMG_UINT32 ui323DCmdOffset = 0;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
+       IMG_UINT32 ui322DCmdCount = 0;
+       IMG_UINT32 ui322DCmdLast = 0;
        IMG_UINT32 ui322DCmdOffset = 0;
+#endif
        IMG_UINT32 ui32PDumpFlags = PDUMP_FLAGS_NONE;
        IMG_UINT32 i;
        IMG_UINT64 uiCheckFenceUID = 0;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        IMG_UINT64 ui2DUpdateFenceUID = 0;
+#endif
        IMG_UINT64 ui3DUpdateFenceUID = 0;
 
-       PSYNC_CHECKPOINT ps2DUpdateSyncCheckpoint = NULL;
        PSYNC_CHECKPOINT ps3DUpdateSyncCheckpoint = NULL;
        PSYNC_CHECKPOINT *apsFenceSyncCheckpoints = NULL;
        IMG_UINT32 ui32FenceSyncCheckpointCount = 0;
-       IMG_UINT32 *pui322DIntAllocatedUpdateValues = NULL;
        IMG_UINT32 *pui323DIntAllocatedUpdateValues = NULL;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
+       PSYNC_CHECKPOINT ps2DUpdateSyncCheckpoint = NULL;
+       IMG_UINT32 *pui322DIntAllocatedUpdateValues = NULL;
        PVRSRV_CLIENT_SYNC_PRIM *ps2DFenceTimelineUpdateSync = NULL;
-       PVRSRV_CLIENT_SYNC_PRIM *ps3DFenceTimelineUpdateSync = NULL;
        IMG_UINT32 ui322DFenceTimelineUpdateValue = 0;
-       IMG_UINT32 ui323DFenceTimelineUpdateValue = 0;
        void *pv2DUpdateFenceFinaliseData = NULL;
+#endif
+       PVRSRV_CLIENT_SYNC_PRIM *ps3DFenceTimelineUpdateSync = NULL;
+       IMG_UINT32 ui323DFenceTimelineUpdateValue = 0;
        void *pv3DUpdateFenceFinaliseData = NULL;
 #if defined(SUPPORT_BUFFER_SYNC)
        PSYNC_CHECKPOINT psBufferUpdateSyncCheckpoint = NULL;
@@ -650,7 +673,9 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT        *psTransferContext,
 
        PVRSRV_ERROR eError = PVRSRV_OK;
        PVRSRV_ERROR eError2;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        PVRSRV_FENCE i2DUpdateFence = PVRSRV_NO_FENCE;
+#endif
        PVRSRV_FENCE i3DUpdateFence = PVRSRV_NO_FENCE;
        IMG_UINT32   ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
        IMG_UINT32   ui32PreparesDone = 0;
@@ -660,15 +685,21 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
        PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
        PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
 
+#if !defined(RGX_FEATURE_TLA_BIT_MASK)
+       PVR_UNREFERENCED_PARAMETER(i2DUpdateTimeline);
+       PVR_UNREFERENCED_PARAMETER(pi2DUpdateFence);
+#endif
+
        RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psDeviceNode->pvDevice,
                                  &pPreAddr,
                                  &pPostAddr,
                                  &pRMWUFOAddr);
-
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (i2DUpdateTimeline != PVRSRV_NO_TIMELINE && !pi2DUpdateFence)
        {
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
+#endif
        if (i3DUpdateTimeline != PVRSRV_NO_TIMELINE && !pi3DUpdateFence)
        {
                return PVRSRV_ERROR_INVALID_PARAMS;
@@ -742,12 +773,15 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                eError = PVRSRV_ERROR_OUT_OF_MEMORY;
                goto fail_alloc3dhelper;
        }
+
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        pas2DCmdHelper = OSAllocMem(sizeof(*pas2DCmdHelper) * ui32PrepareCount);
        if (pas2DCmdHelper == NULL)
        {
                eError = PVRSRV_ERROR_OUT_OF_MEMORY;
                goto fail_alloc2dhelper;
        }
+#endif
 
        if (iCheckFence != PVRSRV_NO_FENCE)
        {
@@ -785,11 +819,14 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 3D))
                {
                        ui323DCmdLast++;
-               } else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D) &&
+               }
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
+               else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D) &&
                                (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
                {
                        ui322DCmdLast++;
                }
+#endif
        }
 
        /*
@@ -852,7 +889,9 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT        *psTransferContext,
                                puiUpdateFenceUID = &ui3DUpdateFenceUID;
                        }
                }
-               else if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D) &&
+               else
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
+               if (TQ_PREP_FLAGS_COMMAND_IS(pui32TQPrepareFlags[i], 2D) &&
                                (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
                {
                        psServerCommonCtx = psTransferContext->s2DData.psServerCommonContext;
@@ -880,6 +919,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT        *psTransferContext,
                        }
                }
                else
+#endif
                {
                        eError = PVRSRV_ERROR_INVALID_PARAMS;
                        goto fail_prepare_loop;
@@ -888,7 +928,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT        *psTransferContext,
                if (i == 0)
                {
                        ui32PDumpFlags = ((pui32TQPrepareFlags[i] & TQ_PREP_FLAGS_PDUMPCONTINUOUS) != 0) ? PDUMP_FLAGS_CONTINUOUS : PDUMP_FLAGS_NONE;
-                       PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, ui32PDumpFlags,
                                        "%s Command Server Submit on FWCtx %08x", pszCommandName, FWCommonContextGetFWAddress(psServerCommonCtx).ui32Addr);
                        psTransferContext->ui32PDumpFlags |= ui32PDumpFlags;
                }
@@ -1189,7 +1229,8 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                /*
                        Create the command helper data for this command
                */
-               RGXCmdHelperInitCmdCCB(psClientCCB,
+               RGXCmdHelperInitCmdCCB(psDevInfo,
+                                      psClientCCB,
                                       0,
                                       ui32IntClientFenceCount,
                                       pauiIntFenceUFOAddress,
@@ -1225,7 +1266,8 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                }
        }
 
-       if (ui322DCmdCount)
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
+       if ((ui322DCmdCount) && (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
        {
                eError = RGXCmdHelperAcquireCmdCCB(ui322DCmdCount,
                                                                                   &pas2DCmdHelper[0]);
@@ -1234,6 +1276,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                        goto fail_cmdacquire;
                }
        }
+#endif
 
        /*
                We should acquire the kernel CCB(s) space here as the schedule could fail
@@ -1249,6 +1292,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                                                                  FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext).ui32Addr);
        }
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if ((ui322DCmdCount) && (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
        {
                ui322DCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->s2DData.psServerCommonContext));
@@ -1257,6 +1301,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                                                                  "TQ_2D",
                                                                  FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext).ui32Addr);
        }
+#endif
 
        if (ui323DCmdCount)
        {
@@ -1264,7 +1309,11 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT     *psTransferContext,
                IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psTransferContext->s3DData.psServerCommonContext).ui32Addr;
                RGX_CLIENT_CCB *ps3DTQCCB = FWCommonContextGetClientCCB(psTransferContext->s3DData.psServerCommonContext);
 
-               RGX_CCB_CMD_HELPER_DATA *psCmdHelper = &pas3DCmdHelper[ui323DCmdCount];
+               /* Take one of the helper data structs and extract the common cmd struct,
+                * this is used to obtain the frame num. Each command should share the same
+                * frame number so we can just get the first.
+                */
+               RGX_CCB_CMD_HELPER_DATA *psCmdHelper = &pas3DCmdHelper[0];
                CMD_COMMON *psTransferCmdCmn = IMG_OFFSET_ADDR(psCmdHelper->pui8DMCmd, 0);
 
                /* Construct the kernel 3D CCB command. */
@@ -1302,7 +1351,6 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                        eError2 = RGXScheduleCommand(psDevInfo,
                                                                                RGXFWIF_DM_3D,
                                                                                &s3DKCCBCmd,
-                                                                               ui32ClientCacheOpSeqNum,
                                                                                ui32PDumpFlags);
                        if (eError2 != PVRSRV_ERROR_RETRY)
                        {
@@ -1311,16 +1359,32 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT    *psTransferContext,
                        OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
                } END_LOOP_UNTIL_TIMEOUT();
 
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSubmitTransferKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_cmdacquire;
+               }
+
                PVRGpuTraceEnqueueEvent(psDeviceNode, ui32FWCtx, ui32ExtJobRef,
                                        ui32IntJobRef, RGX_HWPERF_KICK_TYPE_TQ3D);
        }
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if ((ui322DCmdCount) && (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
        {
                RGXFWIF_KCCB_CMD s2DKCCBCmd;
                IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psTransferContext->s2DData.psServerCommonContext).ui32Addr;
                RGX_CLIENT_CCB *ps2DTQCCB = FWCommonContextGetClientCCB(psTransferContext->s2DData.psServerCommonContext);
-               RGX_CCB_CMD_HELPER_DATA *psCmdHelper = &pas2DCmdHelper[ui322DCmdCount];
+
+               /* Take one of the helper data structs and extract the common cmd struct,
+                * this is used to obtain the frame num. Each command should share the same
+                * frame number so we can just get the first.
+                */
+               RGX_CCB_CMD_HELPER_DATA *psCmdHelper = &pas2DCmdHelper[0];
                CMD_COMMON *psTransferCmdCmn = IMG_OFFSET_ADDR(psCmdHelper->pui8DMCmd, 0);
 
                /* Construct the kernel 2D CCB command. */
@@ -1356,7 +1420,6 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                        eError2 = RGXScheduleCommand(psDevInfo,
                                                                                RGXFWIF_DM_2D,
                                                                                &s2DKCCBCmd,
-                                                                               ui32ClientCacheOpSeqNum,
                                                                                ui32PDumpFlags);
                        if (eError2 != PVRSRV_ERROR_RETRY)
                        {
@@ -1365,9 +1428,20 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT     *psTransferContext,
                        OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
                } END_LOOP_UNTIL_TIMEOUT();
 
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXSubmitTransferKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_cmdacquire;
+               }
+
                PVRGpuTraceEnqueueEvent(psDeviceNode, ui32FWCtx, ui32ExtJobRef,
                                        ui32IntJobRef, RGX_HWPERF_KICK_TYPE_TQ2D);
        }
+#endif
 
        /*
         * Now check eError (which may have returned an error from our earlier calls
@@ -1381,6 +1455,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
 
 #if defined(NO_HARDWARE)
        /* If NO_HARDWARE, signal the output fence's sync checkpoint and sync prim */
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (ps2DUpdateSyncCheckpoint)
        {
                CHKPT_DBG((PVR_DBG_ERROR, "%s:   Signalling TLA NOHW sync checkpoint<%p>, ID:%d, FwAddr=0x%x", __func__, (void*)ps2DUpdateSyncCheckpoint, SyncCheckpointGetId(ps2DUpdateSyncCheckpoint), SyncCheckpointGetFirmwareAddr(ps2DUpdateSyncCheckpoint)));
@@ -1391,6 +1466,7 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT      *psTransferContext,
                CHKPT_DBG((PVR_DBG_ERROR, "%s:   Updating TLA NOHW sync prim<%p> to %d", __func__, (void*)ps2DFenceTimelineUpdateSync, ui322DFenceTimelineUpdateValue));
                SyncPrimNoHwUpdate(ps2DFenceTimelineUpdateSync, ui322DFenceTimelineUpdateValue);
        }
+#endif
        if (ps3DUpdateSyncCheckpoint)
        {
                CHKPT_DBG((PVR_DBG_ERROR, "%s:   Signalling TQ3D NOHW sync checkpoint<%p>, ID:%d, FwAddr=0x%x", __func__, (void*)ps3DUpdateSyncCheckpoint, SyncCheckpointGetId(ps3DUpdateSyncCheckpoint), SyncCheckpointGetFirmwareAddr(ps3DUpdateSyncCheckpoint)));
@@ -1415,26 +1491,32 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT    *psTransferContext,
        }
 #endif /* defined(SUPPORT_BUFFER_SYNC) */
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (pi2DUpdateFence)
        {
                *pi2DUpdateFence = i2DUpdateFence;
        }
+#endif
        if (pi3DUpdateFence)
        {
                *pi3DUpdateFence = i3DUpdateFence;
        }
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (pv2DUpdateFenceFinaliseData && (i2DUpdateFence != PVRSRV_NO_FENCE))
        {
                SyncCheckpointFinaliseFence(psDeviceNode, i2DUpdateFence, pv2DUpdateFenceFinaliseData,
                                            ps2DUpdateSyncCheckpoint, szFenceName);
        }
+#endif
        if (pv3DUpdateFenceFinaliseData && (i3DUpdateFence != PVRSRV_NO_FENCE))
        {
                SyncCheckpointFinaliseFence(psDeviceNode, i3DUpdateFence, pv3DUpdateFenceFinaliseData,
                                            ps3DUpdateSyncCheckpoint, szFenceName);
        }
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        OSFreeMem(pas2DCmdHelper);
+#endif
        OSFreeMem(pas3DCmdHelper);
 
        /* Drop the references taken on the sync checkpoints in the
@@ -1447,11 +1529,13 @@ PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT    *psTransferContext,
                SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
        }
        /* Free memory allocated to hold the internal list of update values */
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (pui322DIntAllocatedUpdateValues)
        {
                OSFreeMem(pui322DIntAllocatedUpdateValues);
                pui322DIntAllocatedUpdateValues = NULL;
        }
+#endif
        if (pui323DIntAllocatedUpdateValues)
        {
                OSFreeMem(pui323DIntAllocatedUpdateValues);
@@ -1486,21 +1570,24 @@ fail_prepare_loop:
 #endif
 
        /* Free memory allocated to hold the internal list of update values */
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (pui322DIntAllocatedUpdateValues)
        {
                OSFreeMem(pui322DIntAllocatedUpdateValues);
                pui322DIntAllocatedUpdateValues = NULL;
        }
+#endif
        if (pui323DIntAllocatedUpdateValues)
        {
                OSFreeMem(pui323DIntAllocatedUpdateValues);
                pui323DIntAllocatedUpdateValues = NULL;
        }
-
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if (i2DUpdateFence != PVRSRV_NO_FENCE)
        {
                SyncCheckpointRollbackFenceData(i2DUpdateFence, pv2DUpdateFenceFinaliseData);
        }
+#endif
        if (i3DUpdateFence != PVRSRV_NO_FENCE)
        {
                SyncCheckpointRollbackFenceData(i3DUpdateFence, pv3DUpdateFenceFinaliseData);
@@ -1531,8 +1618,10 @@ fail_resolve_buffersync_input_fence:
                SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
        }
 fail_resolve_fencesync_input_fence:
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        OSFreeMem(pas2DCmdHelper);
 fail_alloc2dhelper:
+#endif
        OSFreeMem(pas3DCmdHelper);
 fail_alloc3dhelper:
 
@@ -1547,12 +1636,14 @@ PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection
                                                    IMG_UINT32 ui32Priority)
 {
        PVRSRV_ERROR eError;
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
-
+#endif
        PVR_UNREFERENCED_PARAMETER(psDevNode);
 
        OSLockAcquire(psTransferContext->hLock);
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
        if ((psTransferContext->s2DData.ui32Priority != ui32Priority) &&
                        (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
        {
@@ -1571,6 +1662,7 @@ PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection
                }
                psTransferContext->s2DData.ui32Priority = ui32Priority;
        }
+#endif
 
        if (psTransferContext->s3DData.ui32Priority != ui32Priority)
        {
@@ -1594,8 +1686,10 @@ PVRSRV_ERROR PVRSRVRGXSetTransferContextPriorityKM(CONNECTION_DATA *psConnection
        return PVRSRV_OK;
 
 fail_3dcontext:
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
 
 fail_2dcontext:
+#endif
        OSLockRelease(psTransferContext->hLock);
        PVR_ASSERT(eError != PVRSRV_OK);
        return eError;
@@ -1606,28 +1700,23 @@ PVRSRV_ERROR PVRSRVRGXSetTransferContextPropertyKM(RGX_SERVER_TQ_CONTEXT *psTran
                                                                                                   IMG_UINT64 ui64Input,
                                                                                                   IMG_UINT64 *pui64Output)
 {
-       PVRSRV_ERROR eError;
-       PVRSRV_ERROR eError2 = PVRSRV_OK;
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        switch (eContextProperty)
        {
                case RGX_CONTEXT_PROPERTY_FLAGS:
                {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
                        OSLockAcquire(psTransferContext->hLock);
                        eError = FWCommonContextSetFlags(psTransferContext->s2DData.psServerCommonContext,
-                                                        (IMG_UINT32)ui64Input);
+                                                        ui32ContextFlags);
                        if (eError == PVRSRV_OK)
                        {
-                               eError2 = FWCommonContextSetFlags(psTransferContext->s3DData.psServerCommonContext,
-                                                                 (IMG_UINT32)ui64Input);
-                       }
-                       if ((eError == PVRSRV_OK) && (eError2 == PVRSRV_OK))
-                       {
-                               psTransferContext->ui32Flags = (IMG_UINT32)ui64Input;
+                               eError = FWCommonContextSetFlags(psTransferContext->s3DData.psServerCommonContext,
+                                                            ui32ContextFlags);
                        }
                        OSLockRelease(psTransferContext->hLock);
-                       PVR_LOG_IF_ERROR(eError, "FWCommonContextSetFlags eError");
-                       PVR_LOG_IF_ERROR(eError2, "FWCommonContextSetFlags eError2");
                        break;
                }
 
@@ -1655,12 +1744,14 @@ void DumpTransferCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
                RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx =
                        IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
                if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) &&
                                (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
                {
                        DumpFWCommonContextInfo(psCurrentServerTransferCtx->s2DData.psServerCommonContext,
                                                pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
                }
+#endif
 
                if (psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D)
                {
@@ -1684,6 +1775,7 @@ IMG_UINT32 CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
                RGX_SERVER_TQ_CONTEXT *psCurrentServerTransferCtx =
                        IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_CONTEXT, sListNode);
 
+#if defined(RGX_FEATURE_TLA_BIT_MASK)
                if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_2D) &&
                                (NULL != psCurrentServerTransferCtx->s2DData.psServerCommonContext) &&
                                (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TLA)))
@@ -1693,6 +1785,7 @@ IMG_UINT32 CheckForStalledClientTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
                                ui32ContextBitMask |= RGX_KICK_TYPE_DM_TQ2D;
                        }
                }
+#endif
 
                if ((psCurrentServerTransferCtx->ui32Flags & RGX_SERVER_TQ_CONTEXT_FLAGS_3D) && (NULL != psCurrentServerTransferCtx->s3DData.psServerCommonContext))
                {
index bd763f7..cbc5b73 100644 (file)
@@ -78,6 +78,7 @@ PVRSRV_ERROR PVRSRVRGXCreateTransferContextKM(CONNECTION_DATA         *psConnection,
                                                                                   IMG_HANDLE                           hMemCtxPrivData,
                                                                                   IMG_UINT32                           ui32PackedCCBSizeU8888,
                                                                                   IMG_UINT32                           ui32ContextFlags,
+                                                                                  IMG_UINT64                           ui64RobustnessAddress,
                                                                                   RGX_SERVER_TQ_CONTEXT        **ppsTransferContext,
                                                                                   PMR                                          **ppsCLIPMRMem,
                                                                                   PMR                                          **ppsUSCPMRMem);
@@ -111,7 +112,6 @@ PVRSRV_ERROR PVRSRVRGXDestroyTransferContextKM(RGX_SERVER_TQ_CONTEXT *psTransfer
 
 ******************************************************************************/
 PVRSRV_ERROR PVRSRVRGXSubmitTransferKM(RGX_SERVER_TQ_CONTEXT   *psTransferContext,
-                                                                       IMG_UINT32                              ui32ClientCacheOpSeqNum,
                                                                        IMG_UINT32                              ui32PrepareCount,
                                                                        IMG_UINT32                              *paui32ClientUpdateCount,
                                                                        SYNC_PRIMITIVE_BLOCK            ***papauiClientUpdateUFODevVarBlock,
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/rogueall_symbols.csv b/drivers/gpu/drm/img/img-rogue/services/server/devices/rogueall_symbols.csv
deleted file mode 100755 (executable)
index 2abf34d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/rgxtdmtransfer.c,_CreateTDMTransferContext 127,_DestroyTDMTransferContext 185,PVRSRVRGXTDMCreateTransferContextKM 230,PVRSRVRGXTDMGetSharedMemoryKM 360,PVRSRVRGXTDMReleaseSharedMemoryKM 367,PVRSRVRGXTDMDestroyTransferContextKM 374,PVRSRVRGXTDMNotifyWriteOffsetUpdateKM 1173,PVRSRVRGXTDMSetTransferContextPriorityKM 1212,PVRSRVRGXTDMSetTransferContextPropertyKM 1243,DumpTDMTransferCtxtsInfo 1276,CheckForStalledClientTDMTransferCtxt 1295
-/rgxmipsmmuinit.c,RGXMipsMMUInit_Register 173,RGXCheckTrampolineAddrs 688,RGXMipsMMUInit_Unregister 714,RGXDerivePCEProt4 772-0,RGXDerivePCEProt8 784-0,RGXDerivePDEProt4 799-0,RGXDerivePDEProt8 817-0,RGXDerivePTEProt4 830-0,RGXDerivePTEProt8 889-0,RGXGetPageSizeConfigCB 911-0,RGXPutPageSizeConfigCB 961-0,RGXGetPageSizeFromPDE4 993-0,RGXGetPageSizeFromPDE8 1001-0
-/rgxdebug.h,RGXDEBUG_PRINT_IRQ_COUNT 83
-/rgxfwutils.h,_SelectDevMemHeap 64,DevmemFwAllocate 123,DevmemFwAllocateExportable 164,DevmemFwAllocateSparse 226,DevmemFwUnmapAndFree 281,RGXReadHWTimerReg 296
-/rgxfwutils.c,_AllocateSLC3Fence 204,_FreeSLC3Fence 240,__MTSScheduleWrite 251,RGXSetupFwAllocation 285,GetHwPerfBufferSize 411,RGXFWSetupSignatureChecks 468,RGXFWSetupFirmwareGcovBuffer 508,RGXFWSetupCounterBuffer 543,RGXFWSetupAlignChecks 585,RGXFWFreeAlignChecks 637,RGXSetFirmwareAddress 650,RGXSetMetaDMAAddress 769,RGXUnsetFirmwareAddress 785,_CheckPriority 820,FWCommonContextAllocate 860,FWCommonContextFree 1111,FWCommonContextGetFWAddress 1156,FWCommonContextGetClientCCB 1161,FWCommonContextGetLastResetReason 1167,FWCommonContextGetRGXDevInfo 1189,RGXGetFWCommonContextAddrFromServerMMUCtx 1196,FWCommonContextSetFlags 1214,RGXFreeCCB 1234,RGXFreeCCBReturnSlots 1268,RGXSetupCCB 1311,RGXSetupFaultReadRegisterRollback 1382,RGXSetupFaultReadRegister 1397,RGXPDumpFaultReadRegister 1513,RGXTBIBufferIsInitRequired 1551,RGXTBIBufferDeinit 1577,RGXTBIBufferInitOnDemandResources 1594,RGXTraceBufferIsInitRequired 1656,RGXTraceBufferDeinit 1685,RGXTraceBufferInitOnDemandResources 1717,RGXPDumpLoadFWInitData 1780,RGXSetupFwSysData 2078,RGXSetupFwOsData 2734,RGXSetupFirmware 2904,RGXFreeFwSysData 2957,RGXFreeFwOsData 3122,RGXFreeFirmware 3230,RGXAcquireKernelCCBSlot 3284,RGXPollKernelCCBSlot 3329,RGXGetCmdMemCopySize 3377,RGXWaitForKCCBSlotUpdate 3510,RGXSendCommandRaw 3552,_AllocDeferredCommand 3750,_FreeDeferredCommand 3786,RGXSendCommandsFromDeferredList 3805,RGXSendCommandAndGetKCCBSlot 3895,RGXSendCommandWithPowLockAndGetKCCBSlot 3947,RGXScheduleProcessQueuesKM 4004,RGXScheduleRgxRegCommand 4017,RGX_MISRHandler_ScheduleProcessQueues 4056,RGXInstallProcessQueuesMISR 4115,RGXScheduleCommandAndGetKCCBSlot 4128,RGXCheckFirmwareCCB 4262,PVRSRVRGXFrameworkCopyCommand 4646,PVRSRVRGXFrameworkCreateKM 4682,RGXPollForGPCommandCompletion 4713,RGXStateFlagCtrl 4758,RGXScheduleCleanupCommand 4843,RGXFWRequestCommonContextCleanUp 4944,RGXFWRequestHWRTDataCleanUp 4996,RGXFWRequestFreeListCleanUp 5025,RGXFWRequestZSBufferCleanUp 5056,RGXFWSetHCSDeadline 5084,RGXFWHealthCheckCmd 5092,RGXFWSetFwOsState 5106,RGXFWChangeOSidPriority 5181,ContextSetPriority 5210,RGXFWConfigPHR 5314,RGXFWConfigWdg 5341,RGXReadMETAAddr 5370,RGXWriteMETAAddr 5413,RGXCheckForStalledClientContexts 5434,RGXUpdateHealthStatus 5507,RGXUpdateAutoVzWdgToken 5814,RGXUpdateAutoVzWatchdog 5827,CheckStalledClientCommonContext 5851,DumpFWCommonContextInfo 5867,AttachKickResourcesCleanupCtls 5900,RGXResetHWRLogs 5957,RGXGetPhyAddr 5996,RGXPdumpDrainKCCB 6042,RGXClientConnectCompatCheck_ClientAgainstFW 6092,RGXFwRawHeapAllocMap 6195,RGXFwRawHeapUnmapFree 6287,RGXRiscvHalt 6315,RGXRiscvResume 6378,RGXRiscvCheckAbstractCmdError 6441,RGXRiscvReadReg 6490,RGXRiscvPollReg 6550,RGXRiscvWriteReg 6610,RGXRiscvCheckSysBusError 6675,RGXRiscvReadAbstractMem 6722,RGXRiscvPollAbstractMem 6784,RGXRiscvReadSysBusMem 6847,RGXRiscvPollSysBusMem 6908,RGXRiscvReadMem 6972,RGXRiscvPollMem 6996,RGXRiscvWriteAbstractMem 7020,RGXRiscvWriteSysBusMem 7093,RGXRiscvWriteMem 7162
-/rgxmmuinit.c,RGXMMUInit_Register 183,RGXMMUInit_Unregister 721,RGXDerivePCEProt4 779-1,RGXDerivePCEProt8 790-1,RGXDerivePDEProt4 805-1,RGXDerivePDEProt8 823-1,RGXDerivePTEProt4 864-1,RGXDerivePTEProt8 877-1,RGXGetPageSizeConfigCB 939-1,RGXPutPageSizeConfigCB 1001-1,RGXGetPageSizeFromPDE4 1045-1,RGXGetPageSizeFromPDE8 1053-1
-/rgxcompute.c,PVRSRVRGXCreateComputeContextKM 123,PVRSRVRGXDestroyComputeContextKM 313,PVRSRVRGXFlushComputeDataKM 1091,PVRSRVRGXNotifyComputeWriteOffsetUpdateKM 1165,PVRSRVRGXSetComputeContextPriorityKM 1216,PVRSRVRGXSetComputeContextPropertyKM 1244,DumpComputeCtxtsInfo 1273,CheckForStalledClientComputeCtxt 1287,PVRSRVRGXGetLastDeviceErrorKM 1312
-/rgxstartstop.c,RGXEnableClocks 74,RGXWriteMetaRegThroughSP 79-0,RGXReadMetaRegThroughSP 101,RGXWriteMetaCoreRegThoughSP 134,RGXStartFirmware 155,RGXInitMetaProcWrapper 194,RGXInitMipsProcWrapper 241,RGXInitRiscvProcWrapper 422,__RGXInitSLC 469,RGXInitBIF 607,RGXAXIACELiteInit 712,RGXStart 753,RGXStop 955,RGXInitSLC 1233
-/rgxpower.c,RGXFWNotifyHostTimeout 78,_RGXUpdateGPUUtilStats 97,RGXDoStop 125,RGXPrePowerState 156,_RGXWaitForGuestsToDisconnect 304,RGXVzPrePowerState 371,RGXVzPostPowerState 469,RGXCheckFWBootStage 606,RGXDoStart 662,_ValidateIrqs 728,RGXVirtualisationPowerupSidebandTest 810,RGXRiscvDebugModuleTest 891,RGXPostPowerState 996,RGXPreClockSpeedChange 1117,RGXPostClockSpeedChange 1144,RGXDustCountChange 1211,RGXAPMLatencyChange 1314,RGXActivePowerRequest 1371,RGXForcedIdleRequest 1441,RGXCancelForcedIdleRequest 1543,RGXGetNextDustCount 1632
-/rgxpdump.c,_FWDumpSignatureBufferKM 59,_FWDumpTraceBufferKM 114,_MipsDumpSignatureBufferKM 199,_MipsDumpTraceBufferKM 238,PVRSRVPDumpSignatureBufferKM 319,PVRSRVPDumpComputeCRCSignatureCheckKM 340,PVRSRVPDumpCRCSignatureCheckKM 381,PVRSRVPDumpValCheckPreCommandKM 396,PVRSRVPDumpValCheckPostCommandKM 410,PVRSRVPDumpTraceBufferKM 422,RGXPDumpPrepareOutputImageDescriptorHdr 447,RGXPDumpPrepareOutputDataDescriptorHdr 586
-/rgxinit.c,SampleIRQCount 215,RGXHostSafetyEvents 262,RGXSafetyEventCheck 283,RGXSafetyEventHandler 309,_WaitForInterruptsTimeoutCheck 392,RGX_WaitForInterruptsTimeout 418,RGXAckHwIrq 446,RGXAckIrqMETA 463,RGXAckIrqMIPS 472,RGXAckIrqDedicated 481,RGX_LISRHandler 494,RGX_MISR_ProcessKCCBDeferredList 562,RGX_MISRHandler_CheckFWActivePowerState 605,RGXGetGpuUtilStats 649,SORgxGpuUtilStatsRegister 794,SORgxGpuUtilStatsUnregister 820,RGX_MISRHandler_Main 838,RGXPDumpBootldrData 884,RGXSetPowerParams 980,RGXSystemHasFBCDCVersion31 1147,RGXDevMMUAttributes 1212,RGXInitDevPart2 1237,_GetFWFileName 1594,RGXLoadAndGetFWData 1617,RGXInitHWPerfCounters 1660,RGXInitCreateFWKernelMemoryContext 1666,RGXDeInitDestroyFWKernelMemoryContext 1801,RGXAlignmentCheck 1860,RGXAllocateFWMemoryRegion 1932,RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver 1988,RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver 2050,RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver 2116,RGXDevInitCompatCheck_BVNC_FWAgainstDriver 2180,RGXDevInitCompatCheck_BVNC_HWAgainstDriver 2297,RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver 2506,RGXDevInitCompatCheck 2608,RGXSoftReset 2731,RGXFreeTrampoline 2797,RGXAllocTrampoline 2817,RGXInitAllocFWImgMem 2910,RGXFWTraceQueryFilter 3198,RGXFWTraceQueryLogType 3210,RGXFWTraceSetFilter 3232,RGXFWTraceSetLogType 3252,RGXQueryFWPoisonOnFree 3289,RGXSetFWPoisonOnFree 3302,RGXInitFirmware 3332,RGXAllocUFOBlock 3409,RGXFreeUFOBlock 3473,DevDeInitRGX 3539,RGXResetPDump 3858,RGXHeapDerivePageSize 3870,BRN65273IsPresent 3944,BRN63142IsPresent 3958,SignalSnoopingIsPresent 3973,FWBRN65101IsPresent 3987,FWVZConfigPresent 4037,_CountRequiredHeaps 4102,_InstantiateRequiredHeaps 4129,RGXInitHeaps 4173,RGXDeInitHeaps 4282,RGXPhysMemDeviceHeapsInit 4303,_ReadNon4KHeapPageSize 4460,RGXRegisterDevice 4477,RGXDevBVNCString 4948,RGXDevVersionString 4993,RGXDevClockSpeed 5040,RGXInitFwRawHeap 5058,RGXDeInitFwRawHeap 5095
-/rgxlayer_impl.c,RGXMemCopy 60,RGXMemSet 69,RGXCommentLog 77,RGXErrorLog 93,RGXGetOSPageSize 107,RGXGetFWCorememSize 113,RGXWriteReg32 132,RGXWriteReg64 153,RGXReadReg32 174,RGXReadReg64 202,RGXReadModifyWriteReg64 233,RGXPollReg32 283,RGXPollReg64 322,RGXWaitCycles 382,RGXAcquireKernelMMUPC 394,RGXWriteKernelMMUPC64 405,RGXWriteKernelMMUPC32 429,RGXAcquireGPURegsAddr 450,RGXMIPSWrapperConfig 461,RGXAcquireBootRemapAddr 491,RGXAcquireCodeRemapAddr 497,RGXAcquireDataRemapAddr 503,RGXAcquireTrampolineRemapAddr 509,RGXWriteRemapConfig2Reg 523,RGXBootRemapConfig 552,RGXCodeRemapConfig 581,RGXDataRemapConfig 610,RGXTrampolineRemapConfig 639,RGXDoFWSlaveBoot 685,RGXWriteMetaRegThroughSP 703-1,RGXFabricCoherencyTest 730,RGXDeviceGetFeatureValue 1133,RGXDeviceHasFeature 1154,RGXDeviceHasErnBrn 1167,RGXGetDeviceSLCBanks 1179,RGXGetDeviceCacheLineSize 1195,RGXGetDevicePhysBusWidth 1211,RGXDevicePA0IsValid 1227,RGXAcquireBootCodeAddr 1239,RGXAcquireBootDataAddr 1249,RGXDeviceAckIrq 1259
-/rgxdebug.c,_GetMIPSExcString 295,RGXPollMetaRegThroughSP 355,RGXReadMetaCoreReg 373,RGXReadWithSP 401,RGXWriteWithSP 413,_ValidateWithSP 431,_ValidateWithDM 475,_ValidateFWImageForMIPS 518,_ValidateFWImageForMETA 613,_ValidateFWImageForRISCV 721,ValidateFWOnLoad 839,_RGXDecodePMPC 903,_RGXDecodeBIFReqTagsXE 950,_RGXDecodeBIFReqTagsFwcore 1281,_RGXDecodeBIFReqTags 1309,_RGXDecodeMMULevel 1724,_RGXDecodeMMUReqTags 1768,ConvertOSTimestampToSAndNS 2191,_PrintDevicememHistoryQueryResult 2232,_PrintDevicememHistoryQueryOut 2318,_PageSizeHWToBytes 2364,_GetDevicememHistoryData 2396,_FillAppForFWFaults 2493,_PrintFaultInfo 2537,_RecordFaultInfo 2603,_DumpFaultAddressHostView 2689,_RGXDumpRGXBIFBank 2774,_RGXDumpRGXMMUFaultStatus 2897,_RGXMipsExtraDebug 2979,_RGXMipsDumpCauseDecode 3108,_IsFWCodeException 3144,_RGXMipsDumpDebugDecode 3161,_GetMipsTLBPARanges 3200,_CheckMipsTLBDuplicatePAs 3243,_GetMIPSRemapRegionSize 3278,_RGXMipsDumpTLBEntry 3288,_GetRISCVException 3380,_Flags2Description 3404,_GetFwSysFlagsDescription 3420,_GetFwOsFlagsDescription 3432,_RGXDumpFWAssert 3463,_RGXDumpFWFaults 3504,_RGXDumpFWPoll 3539,_RGXDumpFWHWRInfo 3557,_CheckForPendingPage 4048,_GetPendingPageInfo 4083,RGXDumpRGXDebugSummary 4103,_RGXDumpMetaSPExtraDebugInfo 4424,_FirmwareTraceIntegrityCheck 4506,RGXPrepareExtraDebugInfo 4609,RGXDumpFirmwareTrace 4645,RGXDumpPowerMonitoring 4788,_RGXGetDebugDevStateString 4849,_RGXGetDebugDevPowerStateString 4869,RGXDumpMIPSState 4892,RGXDumpRISCVState 4993,RGXDumpRGXRegisters 5066,RGXDebugRequestProcess 5465,RGXDebugRequestNotify 5872,RGXDebugInit 5883,RGXDebugDeinit 5892
-/rgxsrvinit.c,GetApphints 211,GetFWConfigFlags 395,GetFilterFlags 458,InitDeviceFlags 490,RGXTDProcessFWImage 521,RGXAcquireMipsBootldrData 595,InitFirmware 667,InitialiseHWPerfCounters 992,InitialiseCustomCounters 1084,InitialiseAllCounters 1136,_ParseHTBAppHints 1166,RGXValidateTDHeap 1190,RGXValidateTDHeaps 1212,RGXInit 1241
-/rgxtransfer.c,_Create3DTransferContext 140,_Create2DTransferContext 237,_Destroy2DTransferContext 294,_Destroy3DTransferContext 329,PVRSRVRGXCreateTransferContextKM 377,PVRSRVRGXDestroyTransferContextKM 521,PVRSRVRGXSetTransferContextPriorityKM 1547,PVRSRVRGXSetTransferContextPropertyKM 1607,DumpTransferCtxtsInfo 1647,CheckForStalledClientTransferCtxt 1675
-/rgxmulticore.c,RGXGetMultiCoreInfo 80,RGXInitMultiCoreInfo 121,RGXDeInitMultiCoreInfo 213
-/rgxta3d.c,_DebugSyncValues 106,_DebugSyncCheckpoints 122,_DestroyTAContext 197,_Destroy3DContext 247,_RGXDumpPMRPageList 296,RGXDumpFreeListPageList 312,_CheckFreelist 341,_CalculateFreelistReadyPages 455,RGXGrowFreeList 471,RGXShrinkFreeList 761,FindFreeList 870,RGXProcessRequestGrow 893,_RGXFreeListReconstruction 978,RGXReconstructFreeList 1041,RGXProcessRequestFreelistsReconstruction 1101,RGXDestroyHWRTData_aux 1524,RGXDestroyHWRTDataSet 1762,RGXCreateFreeList 1837,RGXDestroyFreeList 2068,RGXCreateZSBufferKM 2161,RGXDestroyZSBufferKM 2286,RGXBackingZSBuffer 2325,RGXPopulateZSBufferKM 2399,RGXUnbackingZSBuffer 2441,RGXUnpopulateZSBufferKM 2495,FindZSBuffer 2515,RGXProcessRequestZSBufferBacking 2538,RGXProcessRequestZSBufferUnbacking 2602,_CreateTAContext 2671,_Create3DContext 2771,PVRSRVRGXCreateRenderContextKM 2883,PVRSRVRGXDestroyRenderContextKM 3074,DumpUfoList 3214,PVRSRVRGXSetRenderContextPriorityKM 5318,PVRSRVRGXSetRenderContextPropertyKM 5374,DumpRenderCtxtsInfo 5411,CheckForStalledClientRenderCtxt 5428,RGXRenderContextStalledKM 5463
-/rgxhwperf.c,RGXHWPerfGetPackets 96,RGXSuspendHWPerfL2DataCopy 113,RGXHWPerfIsInitRequired 137,RGXServerFeatureFlagsToHWPerfFlagsAddBlock 179,RGXServerFeatureFlagsToHWPerfFlags 200,PVRSRVRGXConfigEnableHWPerfCountersKM 299,PVRSRVRGXConfigCustomCountersKM 404,RGXHWPerfConfigureAndEnableCounters 541,RGXHWPerfConfigureAndEnableCustomCounters 582
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.c
new file mode 100644 (file)
index 0000000..12e6e77
--- /dev/null
@@ -0,0 +1,1418 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX Compute routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX Compute routines
+@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.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "srvkm.h"
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxcompute.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "rgxccb.h"
+#include "rgxhwperf.h"
+#include "ospvr_gputrace.h"
+#include "htbuffer.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+#include "rgx_memallocflags.h"
+
+#if defined(SUPPORT_BUFFER_SYNC)
+#include "pvr_buffer_sync.h"
+#endif
+
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_internal.h"
+
+#include "rgxtimerquery.h"
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+
+#define HASH_CLEAN_LIMIT 6
+#endif
+
+/* Enable this to dump the compiled list of UFOs prior to kick call */
+#define ENABLE_CMP_UFO_DUMP    0
+
+//#define CMP_CHECKPOINT_DEBUG 1
+
+#if defined(CMP_CHECKPOINT_DEBUG)
+#define CHKPT_DBG(X) PVR_DPF(X)
+#else
+#define CHKPT_DBG(X)
+#endif
+
+typedef struct {
+       DEVMEM_MEMDESC                          *psContextStateMemDesc;
+       RGX_SERVER_COMMON_CONTEXT       *psServerCommonContext;
+       IMG_UINT32                                      ui32Priority;
+} RGX_SERVER_CC_CMP_DATA;
+
+struct _RGX_SERVER_COMPUTE_CONTEXT_ {
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       //RGX_SERVER_COMMON_CONTEXT     *psServerCommonContext;
+       //DEVMEM_MEMDESC                                *psFWComputeContextStateMemDesc;
+       DEVMEM_MEMDESC                          *psFWComputeContextMemDesc;
+       DEVMEM_MEMDESC                          *psFWFrameworkMemDesc;
+       RGX_SERVER_CC_CMP_DATA          sComputeData;
+       DLLIST_NODE                                     sListNode;
+       SYNC_ADDR_LIST                          sSyncAddrListFence;
+       SYNC_ADDR_LIST                          sSyncAddrListUpdate;
+       POS_LOCK                                        hLock;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WORKEST_HOST_DATA                       sWorkEstData;
+#endif
+#if defined(SUPPORT_BUFFER_SYNC)
+       struct pvr_buffer_sync_context *psBufferSyncContext;
+#endif
+};
+
+static
+PVRSRV_ERROR _CreateComputeContext(CONNECTION_DATA *psConnection,
+                                                                  PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                  DEVMEM_MEMDESC *psAllocatedMemDesc,
+                                                                  IMG_UINT32 ui32AllocatedOffset,
+                                                                  SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                                  DEVMEM_MEMDESC *psFWMemContextMemDesc,
+                                                                  IMG_UINT32 ui32PackedCCBSizeU88,
+                                                                  IMG_UINT32 ui32ContextFlags,
+                                                                  IMG_UINT32 ui32Priority,
+                                                                  IMG_UINT64 ui64RobustnessAddress,
+                                                                  IMG_UINT32 ui32MaxDeadlineMS,
+                                                                  RGX_COMMON_CONTEXT_INFO *psInfo,
+                                                                  RGX_SERVER_CC_CMP_DATA *psComputeData)
+{
+       IMG_UINT32 ui32CCBAllocSizeLog2, ui32CCBMaxAllocSizeLog2;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       /*
+               Allocate device memory for the firmware GPU context suspend state.
+               Note: the FW reads/writes the state to memory by accessing the GPU register interface.
+        */
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware compute context suspend state");
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         sizeof(RGXFWIF_COMPUTECTX_STATE),
+                                                         RGX_FWCOMCTX_ALLOCFLAGS,
+                                                         "FwComputeContextState",
+                                                         &psComputeData->psContextStateMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to allocate firmware GPU context suspend state (%d)",
+                                __func__,
+                                eError));
+               goto fail_contextsuspendalloc;
+       }
+
+       ui32CCBAllocSizeLog2 = U32toU8_Unpack1(ui32PackedCCBSizeU88);
+       ui32CCBMaxAllocSizeLog2 = U32toU8_Unpack2(ui32PackedCCBSizeU88);
+       eError = FWCommonContextAllocate(psConnection,
+                                                                        psDeviceNode,
+                                                                        REQ_TYPE_CDM,
+                                                                        RGXFWIF_DM_CDM,
+                                                                        psServerMMUContext,
+                                                                        psAllocatedMemDesc,
+                                                                        ui32AllocatedOffset,
+                                                                        psFWMemContextMemDesc,
+                                                                        psComputeData->psContextStateMemDesc,
+                                                                        ui32CCBAllocSizeLog2 ? ui32CCBAllocSizeLog2 : RGX_CDM_CCB_SIZE_LOG2,
+                                                                        ui32CCBMaxAllocSizeLog2 ? ui32CCBMaxAllocSizeLog2 : RGX_CDM_CCB_MAX_SIZE_LOG2,
+                                                                        ui32ContextFlags,
+                                                                        ui32Priority,
+                                                                        ui32MaxDeadlineMS,
+                                                                        ui64RobustnessAddress,
+                                                                        psInfo,
+                                                                        &psComputeData->psServerCommonContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to init Compute fw common context (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError)));
+               goto fail_computecommoncontext;
+       }
+
+       /*
+        * Dump the FW compute context suspend state buffer
+       */
+       PDUMPCOMMENT(psDeviceNode, "Dump the compute context suspend state buffer");
+       DevmemPDumpLoadMem(psComputeData->psContextStateMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_COMPUTECTX_STATE),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       psComputeData->ui32Priority = ui32Priority;
+       return PVRSRV_OK;
+
+fail_computecommoncontext:
+       DevmemFree(psComputeData->psContextStateMemDesc);
+fail_contextsuspendalloc:
+       PVR_ASSERT(eError != PVRSRV_OK);
+
+       return eError;
+}
+
+static
+PVRSRV_ERROR _DestroyComputeContext(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
+{
+       RGX_SERVER_CC_CMP_DATA *psComputeData = &psComputeContext->sComputeData;
+       PVRSRV_DEVICE_NODE *psDeviceNode = psComputeContext->psDeviceNode;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       /* Check if the FW has finished with this resource ... */
+       eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+                                                                                         psComputeData->psServerCommonContext,
+                                                                                         RGXFWIF_DM_CDM,
+                                                                                         PDUMP_FLAGS_NONE);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               return eError;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+                                __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       /* ... it has so we can free its resources */
+
+       /* Remove from node list before freeing. */
+       OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock);
+       dllist_remove_node(&(psComputeContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);
+
+       FWCommonContextFree(psComputeData->psServerCommonContext);
+       DevmemFwUnmapAndFree(psDeviceNode->pvDevice, psComputeData->psContextStateMemDesc);
+       psComputeData->psServerCommonContext = NULL;
+       return PVRSRV_OK;
+       }
+
+PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                   *psConnection,
+                                                                                        PVRSRV_DEVICE_NODE                     *psDeviceNode,
+                                                                                        IMG_UINT32                                     ui32Priority,
+                                                                                        IMG_UINT32                                     ui32FrameworkCommandSize,
+                                                                                        IMG_PBYTE                                      pabyFrameworkCommand,
+                                                                                        IMG_HANDLE                                     hMemCtxPrivData,
+                                                                                        IMG_UINT32                                     ui32StaticComputeContextStateSize,
+                                                                                        IMG_PBYTE                                      pStaticComputeContextState,
+                                                                                        IMG_UINT32                                     ui32PackedCCBSizeU88,
+                                                                                        IMG_UINT32                                     ui32ContextFlags,
+                                                                                        IMG_UINT64                                     ui64RobustnessAddress,
+                                                                                        IMG_UINT32                                     ui32MaxDeadlineMS,
+                                                                                        RGX_SERVER_COMPUTE_CONTEXT     **ppsComputeContext)
+{
+       DEVMEM_MEMDESC                          *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+       RGX_SERVER_COMPUTE_CONTEXT      *psComputeContext;
+       RGX_COMMON_CONTEXT_INFO         sInfo = {NULL};
+       PVRSRV_ERROR                            eError = PVRSRV_OK;
+       RGXFWIF_FWCOMPUTECONTEXT        *psFWComputeContext;
+
+       /* Prepare cleanup struct */
+       *ppsComputeContext = NULL;
+
+       if (ui32StaticComputeContextStateSize > RGXFWIF_STATIC_COMPUTECONTEXT_SIZE)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psComputeContext = OSAllocZMem(sizeof(*psComputeContext));
+       if (psComputeContext == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       /*
+               Create the FW compute context, this has the CDM common
+               context embedded within it
+        */
+       eError = DevmemFwAllocate(psDevInfo,
+                       sizeof(RGXFWIF_FWCOMPUTECONTEXT),
+                       RGX_FWCOMCTX_ALLOCFLAGS,
+                       "FwComputeContext",
+                       &psComputeContext->psFWComputeContextMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_fwcomputecontext;
+       }
+
+       eError = OSLockCreate(&psComputeContext->hLock);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to create lock (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError)));
+               goto fail_createlock;
+       }
+
+       psComputeContext->psDeviceNode = psDeviceNode;
+
+       if (ui32FrameworkCommandSize)
+       {
+               eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+                               &psComputeContext->psFWFrameworkMemDesc,
+                               ui32FrameworkCommandSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to allocate firmware GPU framework state (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcreate;
+               }
+
+               /* Copy the Framework client data into the framework buffer */
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psComputeContext->psFWFrameworkMemDesc,
+                               pabyFrameworkCommand,
+                               ui32FrameworkCommandSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to populate the framework buffer (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcopy;
+               }
+               sInfo.psFWFrameworkMemDesc = psComputeContext->psFWFrameworkMemDesc;
+       }
+
+       eError = _CreateComputeContext(psConnection,
+                                                                        psDeviceNode,
+                                                                        psComputeContext->psFWComputeContextMemDesc,
+                                                                        offsetof(RGXFWIF_FWCOMPUTECONTEXT, sCDMContext),
+                                                                        hMemCtxPrivData,
+                                                                        psFWMemContextMemDesc,
+                                                                        ui32PackedCCBSizeU88,
+                                                                        ui32ContextFlags,
+                                                                        ui32Priority,
+                                                                        ui64RobustnessAddress,
+                                                                        ui32MaxDeadlineMS,
+                                                                        &sInfo,
+                                                                        &psComputeContext->sComputeData);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_computecontext;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psComputeContext->psFWComputeContextMemDesc,
+                       (void **)&psFWComputeContext);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_acquire_cpu_mapping;
+       }
+
+       OSDeviceMemCopy(&psFWComputeContext->sStaticComputeContextState, pStaticComputeContextState, ui32StaticComputeContextStateSize);
+       DevmemPDumpLoadMem(psComputeContext->psFWComputeContextMemDesc, 0, sizeof(RGXFWIF_FWCOMPUTECONTEXT), PDUMP_FLAGS_CONTINUOUS);
+       DevmemReleaseCpuVirtAddr(psComputeContext->psFWComputeContextMemDesc);
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       psComputeContext->psBufferSyncContext =
+                       pvr_buffer_sync_context_create(psDeviceNode->psDevConfig->pvOSDevice,
+                                       "rogue-cdm");
+       if (IS_ERR(psComputeContext->psBufferSyncContext))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: failed to create buffer_sync context (err=%ld)",
+                               __func__, PTR_ERR(psComputeContext->psBufferSyncContext)));
+
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto fail_buffer_sync_context_create;
+       }
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WorkEstInitCompute(psDevInfo, &psComputeContext->sWorkEstData);
+#endif
+
+       SyncAddrListInit(&psComputeContext->sSyncAddrListFence);
+       SyncAddrListInit(&psComputeContext->sSyncAddrListUpdate);
+
+       {
+               PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+
+               OSWRLockAcquireWrite(psDevInfo->hComputeCtxListLock);
+               dllist_add_to_tail(&(psDevInfo->sComputeCtxtListHead), &(psComputeContext->sListNode));
+               OSWRLockReleaseWrite(psDevInfo->hComputeCtxListLock);
+       }
+
+       *ppsComputeContext = psComputeContext;
+       return PVRSRV_OK;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+fail_buffer_sync_context_create:
+#endif
+fail_acquire_cpu_mapping:
+       FWCommonContextFree(psComputeContext->sComputeData.psServerCommonContext);
+fail_frameworkcopy:
+fail_computecontext:
+       if (psComputeContext->psFWFrameworkMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psComputeContext->psFWFrameworkMemDesc);
+       }
+fail_frameworkcreate:
+       OSLockDestroy(psComputeContext->hLock);
+fail_createlock:
+       DevmemFwUnmapAndFree(psDevInfo, psComputeContext->psFWComputeContextMemDesc);
+fail_fwcomputecontext:
+       OSFreeMem(psComputeContext);
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
+{
+       PVRSRV_ERROR                            eError = PVRSRV_OK;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_FWCOMPUTECONTEXT        *psFWComputeContext;
+       IMG_UINT32 ui32WorkEstCCBSubmitted;
+
+       eError = DevmemAcquireCpuVirtAddr(psComputeContext->psFWComputeContextMemDesc,
+                       (void **)&psFWComputeContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map firmware compute context (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       ui32WorkEstCCBSubmitted = psFWComputeContext->ui32WorkEstCCBSubmitted;
+
+       DevmemReleaseCpuVirtAddr(psComputeContext->psFWComputeContextMemDesc);
+
+       /* Check if all of the workload estimation CCB commands for this workload are read */
+       if (ui32WorkEstCCBSubmitted != psComputeContext->sWorkEstData.ui32WorkEstCCBReceived)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                       "%s: WorkEst # cmds submitted (%u) and received (%u) mismatch",
+                       __func__, ui32WorkEstCCBSubmitted,
+                       psComputeContext->sWorkEstData.ui32WorkEstCCBReceived));
+
+               return PVRSRV_ERROR_RETRY;
+       }
+#endif
+
+       eError = _DestroyComputeContext(psComputeContext);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       /* remove after RGXFWRequestCommonContextCleanUp() because we might return
+        * RETRY and don't want to be calling this twice */
+       if (psComputeContext->psBufferSyncContext != NULL)
+       {
+               pvr_buffer_sync_context_destroy(psComputeContext->psBufferSyncContext);
+               psComputeContext->psBufferSyncContext = NULL;
+       }
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WorkEstDeInitCompute(psDevInfo, &psComputeContext->sWorkEstData);
+#endif
+
+       if (psComputeContext->psFWFrameworkMemDesc != NULL)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psComputeContext->psFWFrameworkMemDesc);
+       }
+       DevmemFwUnmapAndFree(psDevInfo, psComputeContext->psFWComputeContextMemDesc);
+
+       OSLockDestroy(psComputeContext->hLock);
+       OSFreeMem(psComputeContext);
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT     *psComputeContext,
+                                                               IMG_UINT32                                      ui32ClientUpdateCount,
+                                                               SYNC_PRIMITIVE_BLOCK            **pauiClientUpdateUFODevVarBlock,
+                                                               IMG_UINT32                                      *paui32ClientUpdateSyncOffset,
+                                                               IMG_UINT32                                      *paui32ClientUpdateValue,
+                                                               PVRSRV_FENCE                            iCheckFence,
+                                                               PVRSRV_TIMELINE                         iUpdateTimeline,
+                                                               PVRSRV_FENCE                            *piUpdateFence,
+                                                               IMG_CHAR                                        pszUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH],
+                                                               IMG_UINT32                                      ui32CmdSize,
+                                                               IMG_PBYTE                                       pui8DMCmd,
+                                                               IMG_UINT32                                      ui32PDumpFlags,
+                                                               IMG_UINT32                                      ui32ExtJobRef,
+                                                               IMG_UINT32                                      ui32SyncPMRCount,
+                                                               IMG_UINT32                                      *paui32SyncPMRFlags,
+                                                               PMR                                                     **ppsSyncPMRs,
+                                                               IMG_UINT32                                      ui32NumWorkgroups,
+                                                               IMG_UINT32                                      ui32NumWorkitems,
+                                                               IMG_UINT64                                      ui64DeadlineInus)
+{
+       RGXFWIF_KCCB_CMD                sCmpKCCBCmd;
+       RGX_CCB_CMD_HELPER_DATA asCmdHelperData[1];
+       PVRSRV_ERROR                    eError;
+       PVRSRV_ERROR                    eError2;
+       IMG_UINT32                              ui32CDMCmdOffset = 0;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = FWCommonContextGetRGXDevInfo(psComputeContext->sComputeData.psServerCommonContext);
+       RGX_CLIENT_CCB          *psClientCCB = FWCommonContextGetClientCCB(psComputeContext->sComputeData.psServerCommonContext);
+       IMG_UINT32              ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
+       IMG_UINT32                              ui32FWCtx;
+       IMG_BOOL                                bCCBStateOpen = IMG_FALSE;
+
+       PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+       PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+       PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_WORKEST_KICK_DATA sWorkloadKickDataCompute = {0};
+       IMG_UINT32 ui32CDMWorkloadDataRO = 0;
+       IMG_UINT32 ui32CDMCmdHeaderOffset = 0;
+       IMG_UINT32 ui32CDMCmdOffsetWrapCheck = 0;
+       RGX_WORKLOAD sWorkloadCharacteristics = {0};
+#endif
+
+       IMG_UINT64                              ui64FBSCEntryMask;
+       IMG_UINT32 ui32IntClientFenceCount = 0;
+       PRGXFWIF_UFO_ADDR *pauiIntFenceUFOAddress = NULL;
+       IMG_UINT32 ui32IntClientUpdateCount = 0;
+       PRGXFWIF_UFO_ADDR *pauiIntUpdateUFOAddress = NULL;
+       IMG_UINT32 *paui32IntUpdateValue = NULL;
+       PVRSRV_FENCE  iUpdateFence = PVRSRV_NO_FENCE;
+       IMG_UINT64 uiCheckFenceUID = 0;
+       IMG_UINT64 uiUpdateFenceUID = 0;
+       PSYNC_CHECKPOINT psUpdateSyncCheckpoint = NULL;
+       PSYNC_CHECKPOINT *apsFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32FenceSyncCheckpointCount = 0;
+       IMG_UINT32 *pui32IntAllocatedUpdateValues = NULL;
+       PVRSRV_CLIENT_SYNC_PRIM *psFenceTimelineUpdateSync = NULL;
+       IMG_UINT32 ui32FenceTimelineUpdateValue = 0;
+       void *pvUpdateFenceFinaliseData = NULL;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       struct pvr_buffer_sync_append_data *psBufferSyncData = NULL;
+       PSYNC_CHECKPOINT *apsBufferFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32BufferFenceSyncCheckpointCount = 0;
+       PSYNC_CHECKPOINT psBufferUpdateSyncCheckpoint = NULL;
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+       CMD_COMMON *psComputeCmdCmn = IMG_OFFSET_ADDR(pui8DMCmd, 0);
+
+       if (iUpdateTimeline >= 0 && !piUpdateFence)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       /* Ensure we haven't been given a null ptr to
+        * update values if we have been told we
+        * have updates
+        */
+       if (ui32ClientUpdateCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32ClientUpdateValue != NULL,
+                                       "paui32ClientUpdateValue NULL but "
+                                       "ui32ClientUpdateCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       /* Ensure the string is null-terminated (Required for safety) */
+       pszUpdateFenceName[31] = '\0';
+
+       OSLockAcquire(psComputeContext->hLock);
+
+       eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListFence,
+                                                                       0,
+                                                                       NULL,
+                                                                       NULL);
+       if (eError != PVRSRV_OK)
+       {
+               goto err_populate_sync_addr_list;
+       }
+
+       ui32IntClientUpdateCount = ui32ClientUpdateCount;
+
+       eError = SyncAddrListPopulate(&psComputeContext->sSyncAddrListUpdate,
+                                                                       ui32ClientUpdateCount,
+                                                                       pauiClientUpdateUFODevVarBlock,
+                                                                       paui32ClientUpdateSyncOffset);
+       if (eError != PVRSRV_OK)
+       {
+               goto err_populate_sync_addr_list;
+       }
+       if (ui32IntClientUpdateCount && !pauiIntUpdateUFOAddress)
+       {
+               pauiIntUpdateUFOAddress = psComputeContext->sSyncAddrListUpdate.pasFWAddrs;
+       }
+       paui32IntUpdateValue = paui32ClientUpdateValue;
+
+       if (ui32SyncPMRCount != 0)
+       {
+#if defined(SUPPORT_BUFFER_SYNC)
+               int err;
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Calling "
+                         "pvr_buffer_sync_resolve_and_create_fences", __func__));
+
+               err = pvr_buffer_sync_resolve_and_create_fences(
+                   psComputeContext->psBufferSyncContext,
+                   psComputeContext->psDeviceNode->hSyncCheckpointContext,
+                   ui32SyncPMRCount,
+                   ppsSyncPMRs,
+                   paui32SyncPMRFlags,
+                   &ui32BufferFenceSyncCheckpointCount,
+                   &apsBufferFenceSyncCheckpoints,
+                   &psBufferUpdateSyncCheckpoint,
+                   &psBufferSyncData
+               );
+
+               if (unlikely(err))
+               {
+                       switch (err)
+                       {
+                               case -EINTR:
+                                       eError = PVRSRV_ERROR_RETRY;
+                                       break;
+                               case -ENOMEM:
+                                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                                       break;
+                               default:
+                                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                                       break;
+                       }
+
+                       if (eError != PVRSRV_ERROR_RETRY)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s:   "
+                                       "pvr_buffer_sync_resolve_and_create_fences failed (%d)",
+                                       __func__, eError));
+                       }
+
+                       goto fail_resolve_input_fence;
+               }
+
+               /* Append buffer sync fences */
+               if (ui32BufferFenceSyncCheckpointCount > 0)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append %d buffer sync checkpoints "
+                                 "to CDM Fence (&psTransferContext->sSyncAddrListFence=<%p>, "
+                                 "pauiIntFenceUFOAddress=<%p>)...", __func__,
+                                 ui32BufferFenceSyncCheckpointCount,
+                                 (void *) &psComputeContext->sSyncAddrListFence ,
+                                 (void *) pauiIntFenceUFOAddress));
+
+                       SyncAddrListAppendAndDeRefCheckpoints(&psComputeContext->sSyncAddrListFence,
+                                                             ui32BufferFenceSyncCheckpointCount,
+                                                             apsBufferFenceSyncCheckpoints);
+                       if (pauiIntFenceUFOAddress == NULL)
+                       {
+                               pauiIntFenceUFOAddress = psComputeContext->sSyncAddrListFence.pasFWAddrs;
+                       }
+                       ui32IntClientFenceCount += ui32BufferFenceSyncCheckpointCount;
+               }
+
+               /* Append the update (from output fence) */
+               if (psBufferUpdateSyncCheckpoint)
+               {
+                       SyncAddrListAppendCheckpoints(&psComputeContext->sSyncAddrListUpdate,
+                                                     1, &psBufferUpdateSyncCheckpoint);
+                       if (pauiIntUpdateUFOAddress == NULL)
+                       {
+                               pauiIntUpdateUFOAddress = psComputeContext->sSyncAddrListUpdate.pasFWAddrs;
+                       }
+                       ui32IntClientUpdateCount++;
+               }
+#else /* defined(SUPPORT_BUFFER_SYNC) */
+               PVR_DPF((PVR_DBG_ERROR, "%s: Buffer sync not supported but got %u buffers",
+                       __func__, ui32SyncPMRCount));
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto err_populate_sync_addr_list;
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+       }
+
+       CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointResolveFence (iCheckFence=%d), psComputeContext->psDeviceNode->hSyncCheckpointContext=<%p>...", __func__, iCheckFence, (void*)psComputeContext->psDeviceNode->hSyncCheckpointContext));
+       /* Resolve the sync checkpoints that make up the input fence */
+       eError = SyncCheckpointResolveFence(psComputeContext->psDeviceNode->hSyncCheckpointContext,
+                                                                               iCheckFence,
+                                                                               &ui32FenceSyncCheckpointCount,
+                                                                               &apsFenceSyncCheckpoints,
+                                           &uiCheckFenceUID, ui32PDumpFlags);
+       if (eError != PVRSRV_OK)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, returned ERROR (eError=%d)", __func__, eError));
+               goto fail_free_buffer_sync_data;
+       }
+       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, fence %d contained %d checkpoints (apsFenceSyncCheckpoints=<%p>)", __func__, iCheckFence, ui32FenceSyncCheckpointCount, (void*)apsFenceSyncCheckpoints));
+#if defined(CMP_CHECKPOINT_DEBUG)
+       if (ui32FenceSyncCheckpointCount > 0)
+       {
+               IMG_UINT32 ii;
+               for (ii=0; ii<ui32FenceSyncCheckpointCount; ii++)
+               {
+                       PSYNC_CHECKPOINT psNextCheckpoint = *(apsFenceSyncCheckpoints + ii);
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:    apsFenceSyncCheckpoints[%d]=<%p>", __func__, ii, (void*)psNextCheckpoint));
+               }
+       }
+#endif
+       /* Create the output fence (if required) */
+       if (iUpdateTimeline != PVRSRV_NO_TIMELINE)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointCreateFence (iUpdateFence=%d, iUpdateTimeline=%d,  psComputeContext->psDeviceNode->hSyncCheckpointContext=<%p>)...", __func__, iUpdateFence, iUpdateTimeline, (void*)psComputeContext->psDeviceNode->hSyncCheckpointContext));
+               eError = SyncCheckpointCreateFence(psComputeContext->psDeviceNode,
+                                                  pszUpdateFenceName,
+                                                                                  iUpdateTimeline,
+                                                                                  psComputeContext->psDeviceNode->hSyncCheckpointContext,
+                                                                                  &iUpdateFence,
+                                                                                  &uiUpdateFenceUID,
+                                                                                  &pvUpdateFenceFinaliseData,
+                                                                                  &psUpdateSyncCheckpoint,
+                                                                                  (void*)&psFenceTimelineUpdateSync,
+                                                                                  &ui32FenceTimelineUpdateValue,
+                                                                                  ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...returned error (%d)", __func__, eError));
+                       goto fail_create_output_fence;
+               }
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...returned from SyncCheckpointCreateFence (iUpdateFence=%d, psFenceTimelineUpdateSync=<%p>, ui32FenceTimelineUpdateValue=%u)", __func__, iUpdateFence, psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue));
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u, psFenceTimelineUpdateSync=<%p>", __func__, ui32IntClientUpdateCount, (void*)psFenceTimelineUpdateSync));
+               /* Append the sync prim update for the timeline (if required) */
+               if (psFenceTimelineUpdateSync)
+               {
+                       IMG_UINT32 *pui32TimelineUpdateWp = NULL;
+
+                       /* Allocate memory to hold the list of update values (including our timeline update) */
+                       pui32IntAllocatedUpdateValues = OSAllocMem(sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                       if (!pui32IntAllocatedUpdateValues)
+                       {
+                               /* Failed to allocate memory */
+                               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto fail_alloc_update_values_mem;
+                       }
+                       OSCachedMemSet(pui32IntAllocatedUpdateValues, 0xbb, sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                       /* Copy the update values into the new memory, then append our timeline update value */
+                       if (paui32IntUpdateValue)
+                       {
+                               OSCachedMemCopy(pui32IntAllocatedUpdateValues, paui32IntUpdateValue, sizeof(*pui32IntAllocatedUpdateValues) * ui32IntClientUpdateCount);
+                       }
+#if defined(CMP_CHECKPOINT_DEBUG)
+                       if (ui32IntClientUpdateCount > 0)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u:", __func__, ui32IntClientUpdateCount));
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+                       /* Now set the additional update value */
+                       pui32TimelineUpdateWp = pui32IntAllocatedUpdateValues + ui32IntClientUpdateCount;
+                       *pui32TimelineUpdateWp = ui32FenceTimelineUpdateValue;
+                       ui32IntClientUpdateCount++;
+                       /* Now make sure paui32ClientUpdateValue points to pui32IntAllocatedUpdateValues */
+                       paui32ClientUpdateValue = pui32IntAllocatedUpdateValues;
+
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: append the timeline sync prim addr <%p> to the compute context update list", __func__,  (void*)psFenceTimelineUpdateSync));
+                       /* Now append the timeline sync prim addr to the compute context update list */
+                       SyncAddrListAppendSyncPrim(&psComputeContext->sSyncAddrListUpdate,
+                                                  psFenceTimelineUpdateSync);
+#if defined(CMP_CHECKPOINT_DEBUG)
+                       if (ui32IntClientUpdateCount > 0)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u:", __func__, ui32IntClientUpdateCount));
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+                       /* Ensure paui32IntUpdateValue is now pointing to our new array of update values */
+                       paui32IntUpdateValue = pui32IntAllocatedUpdateValues;
+               }
+       }
+
+       /* Append the checks (from input fence) */
+       if (ui32FenceSyncCheckpointCount > 0)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append %d sync checkpoints to Compute CDM Fence (&psComputeContext->sSyncAddrListFence=<%p>)...", __func__, ui32FenceSyncCheckpointCount, (void*)&psComputeContext->sSyncAddrListFence));
+#if defined(CMP_CHECKPOINT_DEBUG)
+               if (ui32IntClientUpdateCount > 0)
+               {
+                       IMG_UINT32 iii;
+                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pauiIntFenceUFOAddress;
+
+                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                               pui32Tmp++;
+                       }
+               }
+#endif
+               SyncAddrListAppendCheckpoints(&psComputeContext->sSyncAddrListFence,
+                                                                         ui32FenceSyncCheckpointCount,
+                                                                         apsFenceSyncCheckpoints);
+               if (!pauiIntFenceUFOAddress)
+               {
+                       pauiIntFenceUFOAddress = psComputeContext->sSyncAddrListFence.pasFWAddrs;
+               }
+               ui32IntClientFenceCount += ui32FenceSyncCheckpointCount;
+       }
+#if defined(CMP_CHECKPOINT_DEBUG)
+       if (ui32IntClientUpdateCount > 0)
+       {
+               IMG_UINT32 iii;
+               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)paui32IntUpdateValue;
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Dumping %d update values (paui32IntUpdateValue=<%p>)...", __func__, ui32IntClientUpdateCount, (void*)paui32IntUpdateValue));
+               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: paui32IntUpdateValue[%d] = <%p>", __func__, iii, (void*)pui32Tmp));
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: *paui32IntUpdateValue[%d] = 0x%x", __func__, iii, *pui32Tmp));
+                       pui32Tmp++;
+               }
+       }
+#endif
+
+       if (psUpdateSyncCheckpoint)
+       {
+               /* Append the update (from output fence) */
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append 1 sync checkpoint to Compute CDM Update (&psComputeContext->sSyncAddrListUpdate=<%p>, psUpdateSyncCheckpoint=<%p>)...", __func__, (void*)&psComputeContext->sSyncAddrListUpdate , (void*)psUpdateSyncCheckpoint));
+               SyncAddrListAppendCheckpoints(&psComputeContext->sSyncAddrListUpdate,
+                                                                         1,
+                                                                         &psUpdateSyncCheckpoint);
+               if (!pauiIntUpdateUFOAddress)
+               {
+                       pauiIntUpdateUFOAddress = psComputeContext->sSyncAddrListUpdate.pasFWAddrs;
+               }
+               ui32IntClientUpdateCount++;
+#if defined(CMP_CHECKPOINT_DEBUG)
+               if (ui32IntClientUpdateCount > 0)
+               {
+                       IMG_UINT32 iii;
+                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pauiIntUpdateUFOAddress;
+
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pauiIntUpdateUFOAddress=<%p>, pui32Tmp=<%p>, ui32IntClientUpdateCount=%u", __func__, (void*)pauiIntUpdateUFOAddress, (void*)pui32Tmp, ui32IntClientUpdateCount));
+                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pauiIntUpdateUFOAddress[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                               pui32Tmp++;
+                       }
+               }
+#endif
+       }
+       CHKPT_DBG((PVR_DBG_ERROR, "%s:   (after pvr_sync) ui32IntClientFenceCount=%d, ui32IntClientUpdateCount=%d", __func__, ui32IntClientFenceCount, ui32IntClientUpdateCount));
+
+#if (ENABLE_CMP_UFO_DUMP == 1)
+               PVR_DPF((PVR_DBG_ERROR, "%s: dumping Compute (CDM) fence/updates syncs...", __func__));
+               {
+                       IMG_UINT32 ii;
+                       PRGXFWIF_UFO_ADDR *psTmpIntFenceUFOAddress = pauiIntFenceUFOAddress;
+                       PRGXFWIF_UFO_ADDR *psTmpIntUpdateUFOAddress = pauiIntUpdateUFOAddress;
+                       IMG_UINT32 *pui32TmpIntUpdateValue = paui32IntUpdateValue;
+
+                       /* Dump Fence syncs and Update syncs */
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d Compute (CDM) fence syncs (&psComputeContext->sSyncAddrListFence=<%p>, pauiIntFenceUFOAddress=<%p>):", __func__, ui32IntClientFenceCount, (void*)&psComputeContext->sSyncAddrListFence, (void*)pauiIntFenceUFOAddress));
+                       for (ii=0; ii<ui32IntClientFenceCount; ii++)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, CheckValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientFenceCount, (void*)psTmpIntFenceUFOAddress, psTmpIntFenceUFOAddress->ui32Addr));
+                               psTmpIntFenceUFOAddress++;
+                       }
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d Compute (CDM) update syncs (&psComputeContext->sSyncAddrListUpdate=<%p>, pauiIntUpdateUFOAddress=<%p>):", __func__, ui32IntClientUpdateCount, (void*)&psComputeContext->sSyncAddrListUpdate, (void*)pauiIntUpdateUFOAddress));
+                       for (ii=0; ii<ui32IntClientUpdateCount; ii++)
+                       {
+                               if (psTmpIntUpdateUFOAddress->ui32Addr & 0x1)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=%d", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr, *pui32TmpIntUpdateValue));
+                                       pui32TmpIntUpdateValue++;
+                               }
+                               psTmpIntUpdateUFOAddress++;
+                       }
+               }
+#endif
+       RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psComputeContext->psDeviceNode->pvDevice,
+                                 &pPreAddr,
+                                 &pPostAddr,
+                                 &pRMWUFOAddr);
+       /*
+        * Extract the FBSC entries from MMU Context for the deferred FBSC invalidate command,
+        * in other words, take the value and set it to zero afterwards.
+        * FBSC Entry Mask must be extracted from MMU ctx and updated just before the kick starts
+        * as it must be ready at the time of context activation.
+        */
+       {
+               eError = RGXExtractFBSCEntryMaskFromMMUContext(psComputeContext->psDeviceNode,
+                                                                                                          FWCommonContextGetServerMMUCtx(psComputeContext->sComputeData.psServerCommonContext),
+                                                                                                          &ui64FBSCEntryMask);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Failed to extract FBSC Entry Mask (%d)", eError));
+                       goto fail_cmdinvalfbsc;
+               }
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       sWorkloadCharacteristics.sCompute.ui32NumberOfWorkgroups = ui32NumWorkgroups;
+       sWorkloadCharacteristics.sCompute.ui32NumberOfWorkitems  = ui32NumWorkitems;
+
+       /* Prepare workload estimation */
+       WorkEstPrepare(psComputeContext->psDeviceNode->pvDevice,
+                       &psComputeContext->sWorkEstData,
+                       &psComputeContext->sWorkEstData.uWorkloadMatchingData.sCompute.sDataCDM,
+                       RGXFWIF_CCB_CMD_TYPE_CDM,
+                       &sWorkloadCharacteristics,
+                       ui64DeadlineInus,
+                       &sWorkloadKickDataCompute);
+#endif
+
+       RGXCmdHelperInitCmdCCB(psDevInfo,
+                              psClientCCB,
+                              ui64FBSCEntryMask,
+                              ui32IntClientFenceCount,
+                              pauiIntFenceUFOAddress,
+                              NULL,
+                              ui32IntClientUpdateCount,
+                              pauiIntUpdateUFOAddress,
+                              paui32IntUpdateValue,
+                              ui32CmdSize,
+                              pui8DMCmd,
+                           &pPreAddr,
+                           &pPostAddr,
+                           &pRMWUFOAddr,
+                              RGXFWIF_CCB_CMD_TYPE_CDM,
+                              ui32ExtJobRef,
+                              ui32IntJobRef,
+                              ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+                              &sWorkloadKickDataCompute,
+#else
+                              NULL,
+#endif
+                              "Compute",
+                              bCCBStateOpen,
+                              asCmdHelperData);
+
+       eError = RGXCmdHelperAcquireCmdCCB(ARRAY_SIZE(asCmdHelperData), asCmdHelperData);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_cmdaquire;
+       }
+
+
+       /*
+               We should reserve space in the kernel CCB here and fill in the command
+               directly.
+               This is so if there isn't space in the kernel CCB we can return with
+               retry back to services client before we take any operations
+       */
+
+       /*
+               We might only be kicking for flush out a padding packet so only submit
+               the command if the create was successful
+       */
+       if (eError == PVRSRV_OK)
+       {
+               /*
+                       All the required resources are ready at this point, we can't fail so
+                       take the required server sync operations and commit all the resources
+               */
+
+               ui32CDMCmdOffset = RGXGetHostWriteOffsetCCB(psClientCCB);
+               RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, "CDM", FWCommonContextGetFWAddress(psComputeContext->sComputeData.psServerCommonContext).ui32Addr);
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* The following is used to determine the offset of the command header containing
+          the workload estimation data so that can be accessed when the KCCB is read */
+       ui32CDMCmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(asCmdHelperData);
+
+       ui32CDMCmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psComputeContext->sComputeData.psServerCommonContext));
+
+       /* This checks if the command would wrap around at the end of the CCB and
+        * therefore would start at an offset of 0 rather than the current command
+        * offset */
+       if (ui32CDMCmdOffset < ui32CDMCmdOffsetWrapCheck)
+       {
+               ui32CDMWorkloadDataRO = ui32CDMCmdOffset;
+       }
+       else
+       {
+               ui32CDMWorkloadDataRO = 0;
+       }
+#endif
+
+       /* Construct the kernel compute CCB command. */
+       sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+       sCmpKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psComputeContext->sComputeData.psServerCommonContext);
+       sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+       sCmpKCCBCmd.uCmdData.sCmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+       sCmpKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+       /* Add the Workload data into the KCCB kick */
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Store the offset to the CCCB command header so that it can be referenced
+        * when the KCCB command reaches the FW */
+       sCmpKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = ui32CDMWorkloadDataRO + ui32CDMCmdHeaderOffset;
+#else
+       sCmpKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+#endif
+
+       ui32FWCtx = FWCommonContextGetFWAddress(psComputeContext->sComputeData.psServerCommonContext).ui32Addr;
+
+       if (psComputeCmdCmn)
+       {
+               HTBLOGK(HTB_SF_MAIN_KICK_CDM,
+                               sCmpKCCBCmd.uCmdData.sCmdKickData.psContext,
+                               ui32CDMCmdOffset,
+                               psComputeCmdCmn->ui32FrameNum,
+                               ui32ExtJobRef,
+                               ui32IntJobRef
+                               );
+       }
+
+       RGXSRV_HWPERF_ENQ(psComputeContext, OSGetCurrentClientProcessIDKM(),
+                         ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
+                         RGX_HWPERF_KICK_TYPE_CDM,
+                         iCheckFence,
+                         iUpdateFence,
+                         iUpdateTimeline,
+                         uiCheckFenceUID,
+                         uiUpdateFenceUID,
+                         NO_DEADLINE,
+                         NO_CYCEST);
+
+       /*
+        * Submit the compute command to the firmware.
+        */
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError2 = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
+                                                                       RGXFWIF_DM_CDM,
+                                                                       &sCmpKCCBCmd,
+                                                                       ui32PDumpFlags);
+               if (eError2 != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError2 != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s failed to schedule kernel CCB command (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError2)));
+               if (eError == PVRSRV_OK)
+               {
+                       eError = eError2;
+               }
+       }
+       else
+       {
+               PVRGpuTraceEnqueueEvent(psComputeContext->psDeviceNode->pvDevice,
+                                       ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
+                                       RGX_HWPERF_KICK_TYPE_CDM);
+       }
+       /*
+        * Now check eError (which may have returned an error from our earlier call
+        * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
+        * so we check it now...
+        */
+       if (eError != PVRSRV_OK )
+       {
+               goto fail_cmdaquire;
+       }
+
+#if defined(NO_HARDWARE)
+       /* If NO_HARDWARE, signal the output fence's sync checkpoint and sync prim */
+       if (psUpdateSyncCheckpoint)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Signalling NOHW sync checkpoint<%p>, ID:%d, FwAddr=0x%x", __func__, (void*)psUpdateSyncCheckpoint, SyncCheckpointGetId(psUpdateSyncCheckpoint), SyncCheckpointGetFirmwareAddr(psUpdateSyncCheckpoint)));
+               SyncCheckpointSignalNoHW(psUpdateSyncCheckpoint);
+       }
+       if (psFenceTimelineUpdateSync)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Updating NOHW sync prim<%p> to %d", __func__, (void*)psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue));
+               SyncPrimNoHwUpdate(psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue);
+       }
+       SyncCheckpointNoHWUpdateTimelines(NULL);
+#endif /* defined(NO_HARDWARE) */
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               pvr_buffer_sync_kick_succeeded(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+       *piUpdateFence = iUpdateFence;
+
+       if (pvUpdateFenceFinaliseData && (iUpdateFence != PVRSRV_NO_FENCE))
+       {
+               SyncCheckpointFinaliseFence(psComputeContext->psDeviceNode, iUpdateFence,
+                                           pvUpdateFenceFinaliseData,
+                                                                       psUpdateSyncCheckpoint, pszUpdateFenceName);
+       }
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                                                apsFenceSyncCheckpoints);
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       /* Free memory allocated to hold the internal list of update values */
+       if (pui32IntAllocatedUpdateValues)
+       {
+               OSFreeMem(pui32IntAllocatedUpdateValues);
+               pui32IntAllocatedUpdateValues = NULL;
+       }
+
+       OSLockRelease(psComputeContext->hLock);
+
+       return PVRSRV_OK;
+
+fail_cmdaquire:
+fail_cmdinvalfbsc:
+       SyncAddrListRollbackCheckpoints(psComputeContext->psDeviceNode, &psComputeContext->sSyncAddrListFence);
+       SyncAddrListRollbackCheckpoints(psComputeContext->psDeviceNode, &psComputeContext->sSyncAddrListUpdate);
+fail_alloc_update_values_mem:
+       if (iUpdateFence != PVRSRV_NO_FENCE)
+       {
+               SyncCheckpointRollbackFenceData(iUpdateFence, pvUpdateFenceFinaliseData);
+       }
+fail_create_output_fence:
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                                                apsFenceSyncCheckpoints);
+
+fail_free_buffer_sync_data:
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               pvr_buffer_sync_kick_failed(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+
+fail_resolve_input_fence:
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+err_populate_sync_addr_list:
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       /* Free memory allocated to hold the internal list of update values */
+       if (pui32IntAllocatedUpdateValues)
+       {
+               OSFreeMem(pui32IntAllocatedUpdateValues);
+               pui32IntAllocatedUpdateValues = NULL;
+       }
+       OSLockRelease(psComputeContext->hLock);
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext)
+{
+       RGXFWIF_KCCB_CMD sFlushCmd;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32kCCBCommandSlot;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psComputeContext->psDeviceNode->pvDevice;
+
+#if defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psComputeContext->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Submit Compute flush");
+#endif
+       sFlushCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+       sFlushCmd.uCmdData.sSLCFlushInvalData.ui64Size = 0;
+       sFlushCmd.uCmdData.sSLCFlushInvalData.ui64Address = 0;
+       sFlushCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_FALSE;
+       sFlushCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_TRUE;
+       sFlushCmd.uCmdData.sSLCFlushInvalData.psContext = FWCommonContextGetFWAddress(psComputeContext->sComputeData.psServerCommonContext);
+
+       OSLockAcquire(psComputeContext->hLock);
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
+                                                                       RGXFWIF_DM_CDM,
+                                                                       &sFlushCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS,
+                                                                       &ui32kCCBCommandSlot);
+               /* Iterate if we hit a PVRSRV_ERROR_KERNEL_CCB_FULL error */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError != PVRSRV_OK)
+       {
+               /* If we hit a temporary KCCB exhaustion, return a RETRY to caller */
+               if (eError == PVRSRV_ERROR_KERNEL_CCB_FULL)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                "%s: Returning RETRY to caller", __func__));
+                       eError = PVRSRV_ERROR_RETRY;
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to schedule SLC flush command (%s)",
+                                        __func__,
+                                        PVRSRVGetErrorString(eError)));
+               }
+       }
+       else
+       {
+               /* Wait for the SLC flush to complete */
+               eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Compute flush aborted (%s)",
+                                        __func__,
+                                        PVRSRVGetErrorString(eError)));
+               }
+               else if (unlikely(psDevInfo->pui32KernelCCBRtnSlots[ui32kCCBCommandSlot] &
+                                 RGXFWIF_KCCB_RTN_SLOT_POLL_FAILURE))
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: FW poll on a HW operation failed", __func__));
+               }
+       }
+
+       OSLockRelease(psComputeContext->hLock);
+       return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(RGX_SERVER_COMPUTE_CONTEXT  *psComputeContext)
+{
+       RGXFWIF_KCCB_CMD  sKCCBCmd;
+       PVRSRV_ERROR      eError;
+
+       OSLockAcquire(psComputeContext->hLock);
+
+       /* Schedule the firmware command */
+       sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE;
+       sKCCBCmd.uCmdData.sWriteOffsetUpdateData.psContext = FWCommonContextGetFWAddress(psComputeContext->sComputeData.psServerCommonContext);
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psComputeContext->psDeviceNode->pvDevice,
+                                                                       RGXFWIF_DM_CDM,
+                                                                       &sKCCBCmd,
+                                                                       PDUMP_FLAGS_NONE);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to schedule the FW command %d (%s)",
+                               __func__,
+                               eError,
+                               PVRSRVGETERRORSTRING(eError)));
+       }
+
+       OSLockRelease(psComputeContext->hLock);
+
+       return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                  PVRSRV_DEVICE_NODE * psDeviceNode,
+                                                                                                 RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+                                                                                                 IMG_UINT32 ui32Priority)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+       OSLockAcquire(psComputeContext->hLock);
+
+       eError = ContextSetPriority(psComputeContext->sComputeData.psServerCommonContext,
+                                                               psConnection,
+                                                               psComputeContext->psDeviceNode->pvDevice,
+                                                               ui32Priority,
+                                                               RGXFWIF_DM_CDM);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority of the compute context (%s)", __func__, PVRSRVGetErrorString(eError)));
+       }
+
+       OSLockRelease(psComputeContext->hLock);
+       return eError;
+}
+
+/*
+ * PVRSRVRGXSetComputeContextPropertyKM
+ */
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPropertyKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+                                                  RGX_CONTEXT_PROPERTY eContextProperty,
+                                                  IMG_UINT64 ui64Input,
+                                                  IMG_UINT64 *pui64Output)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       switch (eContextProperty)
+       {
+               case RGX_CONTEXT_PROPERTY_FLAGS:
+               {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
+                       OSLockAcquire(psComputeContext->hLock);
+                       eError = FWCommonContextSetFlags(psComputeContext->sComputeData.psServerCommonContext,
+                                                        ui32ContextFlags);
+                       OSLockRelease(psComputeContext->hLock);
+                       break;
+               }
+
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_ERROR_NOT_SUPPORTED - asked to set unknown property (%d)", __func__, eContextProperty));
+                       eError = PVRSRV_ERROR_NOT_SUPPORTED;
+               }
+       }
+
+       return eError;
+}
+
+void DumpComputeCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                          DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                          void *pvDumpDebugFile,
+                          IMG_UINT32 ui32VerbLevel)
+{
+       DLLIST_NODE *psNode, *psNext;
+       OSWRLockAcquireRead(psDevInfo->hComputeCtxListLock);
+       dllist_foreach_node(&psDevInfo->sComputeCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_COMPUTE_CONTEXT *psCurrentServerComputeCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_COMPUTE_CONTEXT, sListNode);
+               DumpFWCommonContextInfo(psCurrentServerComputeCtx->sComputeData.psServerCommonContext,
+                                       pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+       }
+       OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
+}
+
+IMG_UINT32 CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_UINT32 ui32ContextBitMask = 0;
+       DLLIST_NODE *psNode, *psNext;
+       OSWRLockAcquireRead(psDevInfo->hComputeCtxListLock);
+       dllist_foreach_node(&psDevInfo->sComputeCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_COMPUTE_CONTEXT *psCurrentServerComputeCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_COMPUTE_CONTEXT, sListNode);
+
+               if (CheckStalledClientCommonContext(psCurrentServerComputeCtx->sComputeData.psServerCommonContext, RGX_KICK_TYPE_DM_CDM)
+                       == PVRSRV_ERROR_CCCB_STALLED)
+               {
+                       ui32ContextBitMask |= RGX_KICK_TYPE_DM_CDM;
+               }
+       }
+       OSWRLockReleaseRead(psDevInfo->hComputeCtxListLock);
+       return ui32ContextBitMask;
+}
+
+/*
+ * PVRSRVRGXGetLastDeviceErrorKM
+ */
+PVRSRV_ERROR PVRSRVRGXGetLastDeviceErrorKM(CONNECTION_DATA    *psConnection,
+                                           PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           IMG_UINT32         *ui32Error)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       *ui32Error = psDevInfo->eLastDeviceError;
+       psDevInfo->eLastDeviceError = RGX_CONTEXT_RESET_REASON_NONE;
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (rgxcompute.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxcompute.h
new file mode 100644 (file)
index 0000000..35d7dc1
--- /dev/null
@@ -0,0 +1,182 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX compute functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX compute functionality
+@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(RGXCOMPUTE_H)
+#define RGXCOMPUTE_H
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgxdebug.h"
+#include "pvr_notifier.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "connection_server.h"
+
+
+typedef struct _RGX_SERVER_COMPUTE_CONTEXT_ RGX_SERVER_COMPUTE_CONTEXT;
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXCreateComputeContextKM
+
+ @Description
+       Creates a RGX device context for submitting commands to CDM.
+
+ @Input pvDeviceNode - Services-managed device
+ @Input        ui32Priority - Scheduling priority for commands on this context
+ @Input hMemCtxPrivData - private data
+ @Input ui32PackedCCBSizeU88 - packed CCB size. The first byte contains the
+               log2 CCB size and the second byte the log2 maximum CCB size.
+ @Input ui32ComputeCtxSwitchSize - Context control size
+ @Input pComputeCtxSwitch_Regs - Context control registers
+ @Output ppsComputeContext - cleanup data
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXCreateComputeContextKM(CONNECTION_DATA                   *psConnection,
+                                                                                        PVRSRV_DEVICE_NODE                     *psDeviceNode,
+                                                                                        IMG_UINT32                                     ui32Priority,
+                                                                                        IMG_UINT32                                     ui32FrameworkCommandSize,
+                                                                                        IMG_PBYTE                                      pabyFrameworkCommand,
+                                                                                        IMG_HANDLE                                     hMemCtxPrivData,
+                                                                                        IMG_UINT32                                     ui32StaticComputeContextStateSize,
+                                                                                        IMG_PBYTE                                      pStaticComputeContextState,
+                                                                                        IMG_UINT32                                     ui32PackedCCBSizeU88,
+                                                                                        IMG_UINT32                                     ui32ContextFlags,
+                                                                                        IMG_UINT64                                     ui64RobustnessAddress,
+                                                                                        IMG_UINT32                                     ui32MaxDeadlineMS,
+                                                                                        RGX_SERVER_COMPUTE_CONTEXT     **ppsComputeContext);
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXDestroyComputeContextKM
+
+ @Description
+       Server-side implementation of RGXDestroyComputeContext
+
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXDestroyComputeContextKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXKickCDMKM
+
+ @Description
+       Server-side implementation of RGXKickCDM
+
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXKickCDMKM(RGX_SERVER_COMPUTE_CONTEXT     *psComputeContext,
+                                                               IMG_UINT32                                      ui32ClientUpdateCount,
+                                                               SYNC_PRIMITIVE_BLOCK            **pauiClientUpdateUFODevVarBlock,
+                                                               IMG_UINT32                                      *paui32ClientUpdateSyncOffset,
+                                                               IMG_UINT32                                      *paui32ClientUpdateValue,
+                                                               PVRSRV_FENCE                            iCheckFence,
+                                                               PVRSRV_TIMELINE                         iUpdateTimeline,
+                                                               PVRSRV_FENCE                            *piUpdateFence,
+                                                               IMG_CHAR                                        pcszUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH],
+                                                               IMG_UINT32                                      ui32CmdSize,
+                                                               IMG_PBYTE                                       pui8DMCmd,
+                                                               IMG_UINT32                                      ui32PDumpFlags,
+                                                               IMG_UINT32                                      ui32ExtJobRef,
+                                                               IMG_UINT32                                      ui32SyncPMRCount,
+                                                               IMG_UINT32                                      *paui32SyncPMRFlags,
+                                                               PMR                                                     **ppsSyncPMRs,
+                                                               IMG_UINT32                                      ui32NumWorkgroups,
+                                                               IMG_UINT32                                      ui32NumWorkitems,
+                                                               IMG_UINT64                                      ui64DeadlineInus);
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXFlushComputeDataKM
+
+ @Description
+       Server-side implementation of RGXFlushComputeData
+
+ @Input psComputeContext - Compute context to flush
+
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXFlushComputeDataKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
+/*!
+*******************************************************************************
+
+ @Function         PVRSRVRGXNotifyComputeWriteOffsetUpdateKM
+ @Description   Server-side implementation of RGXNotifyComputeWriteOffsetUpdate
+
+ @Input         psComputeContext - Compute context to flush
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXNotifyComputeWriteOffsetUpdateKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext);
+
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                                                                 PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                                 RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+                                                                                                 IMG_UINT32 ui32Priority);
+
+PVRSRV_ERROR PVRSRVRGXSetComputeContextPropertyKM(RGX_SERVER_COMPUTE_CONTEXT *psComputeContext,
+                                                                                                 RGX_CONTEXT_PROPERTY eContextProperty,
+                                                                                                 IMG_UINT64 ui64Input,
+                                                                                                 IMG_UINT64 *pui64Output);
+
+PVRSRV_ERROR PVRSRVRGXGetLastDeviceErrorKM(CONNECTION_DATA    *psConnection,
+                                           PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           IMG_UINT32         *ui32Error);
+
+/* Debug - Dump debug info of compute contexts on this device */
+void DumpComputeCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                          DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                          void *pvDumpDebugFile,
+                          IMG_UINT32 ui32VerbLevel);
+
+/* Debug/Watchdog - check if client compute contexts are stalled */
+IMG_UINT32 CheckForStalledClientComputeCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+#endif /* RGXCOMPUTE_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.c
new file mode 100644 (file)
index 0000000..3f0a353
--- /dev/null
@@ -0,0 +1,3809 @@
+/*************************************************************************/ /*!
+@File
+@Title          Rgx debug information
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX debugging functions
+@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.
+*/ /**************************************************************************/
+//#define PVR_DPF_FUNCTION_TRACE_ON 1
+#undef PVR_DPF_FUNCTION_TRACE_ON
+
+#include "img_defs.h"
+#include "rgxdefs_km.h"
+#include "rgxdevice.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "cache_km.h"
+#include "osfunc.h"
+
+#include "rgxdebug.h"
+#include "pvrversion.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "rgxutils.h"
+#include "tlstream.h"
+#include "rgxfwutils.h"
+#include "pvrsrv.h"
+#include "services_km.h"
+
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "devicemem_utils.h"
+#include "rgx_fwif_km.h"
+#include "rgx_fwif_sf.h"
+#include "rgxfw_log_helper.h"
+#include "fwtrace_string.h"
+#include "rgxfwimageutils.h"
+#include "fwload.h"
+
+#include "rgxta3d.h"
+#include "rgxkicksync.h"
+#include "rgxcompute.h"
+#include "rgxtdmtransfer.h"
+#include "rgxtimecorr.h"
+#include "rgx_options.h"
+#include "rgxinit.h"
+#include "rgxlayer_impl.h"
+#include "devicemem_history_server.h"
+#include "info_page.h"
+
+#define PVR_DUMP_FIRMWARE_INFO(x)                                                                                                              \
+       PVR_DUMPDEBUG_LOG("FW info: %d.%d @ %8d (%s) build options: 0x%08x",                            \
+                                               PVRVERSION_UNPACK_MAJ((x).ui32DDKVersion),                                              \
+                                               PVRVERSION_UNPACK_MIN((x).ui32DDKVersion),                                              \
+                                               (x).ui32DDKBuild,                                                                                               \
+                                               ((x).ui32BuildOptions & OPTIONS_DEBUG_MASK) ? "debug":"release",\
+                                               (x).ui32BuildOptions);
+
+#define DD_SUMMARY_INDENT  ""
+#define DD_NORMAL_INDENT   "    "
+
+#define RGX_DEBUG_STR_SIZE                     (150U)
+#define MAX_FW_DESCRIPTION_LENGTH      (600U)
+
+
+#define RGX_TEXAS_BIF0_ID                              (0)
+#define RGX_TEXAS_BIF1_ID                              (1)
+
+/*
+ *  The first 7 or 8 cat bases are memory contexts used for PM
+ *  or firmware. The rest are application contexts. The numbering
+ *  is zero-based.
+ */
+#if defined(SUPPORT_TRUSTED_DEVICE)
+#define MAX_RESERVED_FW_MMU_CONTEXT            (7)
+#else
+#define MAX_RESERVED_FW_MMU_CONTEXT            (6)
+#endif
+
+static const IMG_CHAR *const pszPowStateName[] =
+{
+#define X(NAME)        #NAME,
+       RGXFWIF_POW_STATES
+#undef X
+};
+
+typedef struct _IMG_FLAGS2DESC_
+{
+       IMG_UINT32              uiFlag;
+       const IMG_CHAR  *pszLabel;
+} IMG_FLAGS2DESC;
+
+static const IMG_CHAR * const apszFwOsStateName[RGXFW_CONNECTION_FW_STATE_COUNT] =
+{
+       "offline",
+       "ready",
+       "active",
+       "offloading"
+};
+
+#if defined(PVR_ENABLE_PHR)
+static const IMG_FLAGS2DESC asPHRConfig2Description[] =
+{
+       {BIT_ULL(RGXFWIF_PHR_MODE_OFF), "off"},
+       {BIT_ULL(RGXFWIF_PHR_MODE_RD_RESET), "reset RD hardware"},
+       {BIT_ULL(RGXFWIF_PHR_MODE_FULL_RESET), "full gpu reset "},
+};
+#endif
+
+#if !defined(NO_HARDWARE)
+static PVRSRV_ERROR
+RGXPollMetaRegThroughSP(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegOffset,
+                        IMG_UINT32 ui32PollValue, IMG_UINT32 ui32Mask)
+{
+       IMG_UINT32 ui32RegValue, ui32NumPolls = 0;
+       PVRSRV_ERROR eError;
+
+       do
+       {
+               eError = RGXReadFWModuleAddr(psDevInfo, ui32RegOffset, &ui32RegValue);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+       } while (((ui32RegValue & ui32Mask) != ui32PollValue) && (ui32NumPolls++ < 1000));
+
+       return ((ui32RegValue & ui32Mask) == ui32PollValue) ? PVRSRV_OK : PVRSRV_ERROR_RETRY;
+}
+
+static PVRSRV_ERROR
+RGXReadMetaCoreReg(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32RegAddr, IMG_UINT32 *pui32RegVal)
+{
+       PVRSRV_ERROR eError;
+
+       /* Core Read Ready? */
+       eError = RGXPollMetaRegThroughSP(psDevInfo,
+                                        META_CR_TXUXXRXRQ_OFFSET,
+                                        META_CR_TXUXXRXRQ_DREADY_BIT,
+                                                                        META_CR_TXUXXRXRQ_DREADY_BIT);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXPollMetaRegThroughSP");
+
+       /* Set the reg we are interested in reading */
+       eError = RGXWriteFWModuleAddr(psDevInfo, META_CR_TXUXXRXRQ_OFFSET,
+                               ui32RegAddr | META_CR_TXUXXRXRQ_RDnWR_BIT);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXWriteFWModuleAddr");
+
+       /* Core Read Done? */
+       eError = RGXPollMetaRegThroughSP(psDevInfo,
+                                        META_CR_TXUXXRXRQ_OFFSET,
+                                        META_CR_TXUXXRXRQ_DREADY_BIT,
+                                                                        META_CR_TXUXXRXRQ_DREADY_BIT);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXPollMetaRegThroughSP");
+
+       /* Read the value */
+       return RGXReadFWModuleAddr(psDevInfo, META_CR_TXUXXRXDT_OFFSET, pui32RegVal);
+}
+#endif
+
+#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
+static PVRSRV_ERROR _ValidateWithFWModule(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile,
+                                               PVRSRV_RGXDEV_INFO *psDevInfo,
+                                               RGXFWIF_DEV_VIRTADDR *psFWAddr,
+                                               void *pvHostCodeAddr,
+                                               IMG_UINT32 ui32MaxLen,
+                                               const IMG_CHAR *pszDesc,
+                                               IMG_UINT32 ui32StartOffset)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32Value = 0;
+       IMG_UINT32 ui32FWCodeDevVAAddr = psFWAddr->ui32Addr + ui32StartOffset;
+       IMG_UINT32 *pui32FWCode = (IMG_PUINT32) ((IMG_PBYTE)pvHostCodeAddr + ui32StartOffset);
+       IMG_UINT32 i;
+
+#if defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               return PVRSRV_OK;
+       }
+#endif
+
+       ui32MaxLen -= ui32StartOffset;
+       ui32MaxLen /= sizeof(IMG_UINT32); /* Byte -> 32 bit words */
+
+       for (i = 0; i < ui32MaxLen; i++)
+       {
+               eError = RGXReadFWModuleAddr(psDevInfo, ui32FWCodeDevVAAddr, &ui32Value);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: %s", __func__, PVRSRVGetErrorString(eError)));
+                       return eError;
+               }
+
+#if defined(EMULATOR)
+               if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+#endif
+               {
+                       PVR_DPF((PVR_DBG_VERBOSE, "0x%x: CPU 0x%08x, FW 0x%08x", i * 4, pui32FWCode[i], ui32Value));
+
+                       if (pui32FWCode[i] != ui32Value)
+                       {
+                               PVR_DUMPDEBUG_LOG("%s: Mismatch while validating %s at offset 0x%x: CPU 0x%08x (%p), FW 0x%08x (%x)",
+                                        __func__, pszDesc,
+                                        (i * 4) + ui32StartOffset, pui32FWCode[i], pui32FWCode, ui32Value, ui32FWCodeDevVAAddr);
+                               return PVRSRV_ERROR_FW_IMAGE_MISMATCH;
+                       }
+               }
+
+               ui32FWCodeDevVAAddr += 4;
+       }
+
+       PVR_DUMPDEBUG_LOG("Match between Host and Firmware view of the %s", pszDesc);
+       return PVRSRV_OK;
+}
+#endif
+
+#if !defined(NO_HARDWARE)
+static PVRSRV_ERROR _ValidateFWImage(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile,
+                                               PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
+       PVRSRV_ERROR eError;
+       IMG_UINT32 *pui32HostFWCode = NULL, *pui32HostFWCoremem = NULL;
+       OS_FW_IMAGE *psRGXFW = NULL;
+       const IMG_BYTE *pbRGXFirmware = NULL;
+       RGXFWIF_DEV_VIRTADDR sFWAddr;
+       IMG_UINT32 ui32StartOffset = 0;
+       RGX_LAYER_PARAMS sLayerParams;
+       sLayerParams.psDevInfo = psDevInfo;
+
+#if defined(EMULATOR)
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               PVR_DUMPDEBUG_LOG("Validation of RISC-V FW code is disabled on emulator");
+               return PVRSRV_OK;
+       }
+#endif
+
+       if (psDevInfo->pvRegsBaseKM == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: RGX registers not mapped yet!", __func__));
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       /* Load FW from system for code verification */
+       pui32HostFWCode = OSAllocZMem(psDevInfo->ui32FWCodeSizeInBytes);
+       if (pui32HostFWCode == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed in allocating memory for FW code. "
+                               "So skipping FW code verification",
+                               __func__));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       {
+               pui32HostFWCoremem = OSAllocZMem(psDevInfo->ui32FWCorememCodeSizeInBytes);
+               if (pui32HostFWCoremem == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed in allocating memory for FW core code. "
+                                       "So skipping FW code verification",
+                                       __func__));
+                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                       goto freeHostFWCode;
+               }
+       }
+
+       /* Load FW image */
+       eError = RGXLoadAndGetFWData(psDevInfo->psDeviceNode, &psRGXFW, &pbRGXFirmware);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to load FW image file (%s).",
+                        __func__, PVRSRVGetErrorString(eError)));
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto cleanup_initfw;
+       }
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               eError = ProcessLDRCommandStream(&sLayerParams, pbRGXFirmware,
+                                               (void*) pui32HostFWCode, NULL,
+                                               (void*) pui32HostFWCoremem, NULL, NULL);
+       }
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               eError = ProcessELFCommandStream(&sLayerParams, pbRGXFirmware,
+                                                pui32HostFWCode, NULL,
+                                                pui32HostFWCoremem, NULL);
+       }
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed in parsing FW image file.", __func__));
+               goto cleanup_initfw;
+       }
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               /* starting checking after BOOT LOADER config */
+               sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
+
+               ui32StartOffset = RGXFW_MAX_BOOTLDR_OFFSET;
+       }
+       else
+       {
+               /* Use bootloader code remap which is always configured before the FW is started */
+               sFWAddr.ui32Addr = RGXRISCVFW_BOOTLDR_CODE_BASE;
+       }
+
+       eError = _ValidateWithFWModule(pfnDumpDebugPrintf, pvDumpDebugFile,
+                                       psDevInfo, &sFWAddr,
+                                       pui32HostFWCode, psDevInfo->ui32FWCodeSizeInBytes,
+                                       "FW code", ui32StartOffset);
+       if (eError != PVRSRV_OK)
+       {
+               goto cleanup_initfw;
+       }
+
+       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       {
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
+               }
+               else
+               {
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, RISCV_COREMEM_CODE);
+
+                       /* Core must be halted while issuing abstract commands */
+                       eError = RGXRiscvHalt(psDevInfo);
+                       PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+               }
+
+               eError = _ValidateWithFWModule(pfnDumpDebugPrintf, pvDumpDebugFile,
+                                               psDevInfo, &sFWAddr,
+                                               pui32HostFWCoremem, psDevInfo->ui32FWCorememCodeSizeInBytes,
+                                               "FW coremem code", 0);
+
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+               {
+                       eError = RGXRiscvResume(psDevInfo);
+                       PVR_GOTO_IF_ERROR(eError, cleanup_initfw);
+               }
+       }
+
+cleanup_initfw:
+       if (psRGXFW)
+       {
+               OSUnloadFirmware(psRGXFW);
+       }
+
+       if (pui32HostFWCoremem)
+       {
+               OSFreeMem(pui32HostFWCoremem);
+       }
+freeHostFWCode:
+       if (pui32HostFWCode)
+       {
+               OSFreeMem(pui32HostFWCode);
+       }
+       return eError;
+#else
+       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
+       PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       return PVRSRV_OK;
+#endif
+}
+#endif /* !defined(NO_HARDWARE) */
+
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
+PVRSRV_ERROR ValidateFWOnLoad(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if !defined(NO_HARDWARE) && !defined(SUPPORT_TRUSTED_DEVICE)
+       IMG_PBYTE pbCodeMemoryPointer;
+       PVRSRV_ERROR eError;
+       RGXFWIF_DEV_VIRTADDR sFWAddr;
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc, (void **)&pbCodeMemoryPointer);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               sFWAddr.ui32Addr = RGXFW_BOOTLDR_META_ADDR;
+       }
+       else
+       {
+               PVR_ASSERT(RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR));
+               sFWAddr.ui32Addr = RGXRISCVFW_BOOTLDR_CODE_BASE;
+       };
+
+       eError = _ValidateWithFWModule(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer, psDevInfo->ui32FWCodeSizeInBytes, "FW code", 0);
+       if (eError != PVRSRV_OK)
+       {
+               goto releaseFWCodeMapping;
+       }
+
+       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       {
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc, (void **)&pbCodeMemoryPointer);
+               if (eError != PVRSRV_OK)
+               {
+                       goto releaseFWCoreCodeMapping;
+               }
+
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, META_COREMEM_CODE);
+               }
+               else
+               {
+                       PVR_ASSERT(RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR));
+                       sFWAddr.ui32Addr = RGXGetFWImageSectionAddress(NULL, RISCV_COREMEM_CODE);
+               }
+
+               eError = _ValidateWithFWModule(NULL, NULL, psDevInfo, &sFWAddr, pbCodeMemoryPointer,
+                                               psDevInfo->ui32FWCorememCodeSizeInBytes, "FW coremem code", 0);
+       }
+
+releaseFWCoreCodeMapping:
+       if (psDevInfo->ui32FWCorememCodeSizeInBytes)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
+       }
+releaseFWCodeMapping:
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+
+       return eError;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       return PVRSRV_OK;
+#endif
+}
+#endif
+
+
+/*!
+*******************************************************************************
+
+ @Function     _RGXDecodeMMULevel
+
+ @Description
+
+ Return the name for the MMU level that faulted.
+
+ @Input ui32MMULevel    - MMU level
+
+ @Return   IMG_CHAR* to the sting describing the MMU level that faulted.
+
+******************************************************************************/
+static const IMG_CHAR* _RGXDecodeMMULevel(IMG_UINT32 ui32MMULevel)
+{
+       const IMG_CHAR* pszMMULevel = "";
+
+       switch (ui32MMULevel)
+       {
+               case 0x0: pszMMULevel = " (Page Table)"; break;
+               case 0x1: pszMMULevel = " (Page Directory)"; break;
+               case 0x2: pszMMULevel = " (Page Catalog)"; break;
+               case 0x3: pszMMULevel = " (Cat Base Reg)"; break;
+       }
+
+       return pszMMULevel;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function     _RGXDecodeMMUReqTags
+
+ @Description
+
+ Decodes the MMU Tag ID and Sideband data fields from RGX_CR_MMU_FAULT_META_STATUS and
+ RGX_CR_MMU_FAULT_STATUS regs.
+
+ @Input ui32TagID           - Tag ID value
+ @Input ui32BIFModule       - BIF module
+ @Input bRead               - Read flag
+ @Input bWriteBack          - Write Back flag
+ @Output ppszTagID          - Decoded string from the Tag ID
+ @Output ppszTagSB          - Decoded string from the Tag SB
+ @Output pszScratchBuf      - Buffer provided to the function to generate the debug strings
+ @Input ui32ScratchBufSize  - Size of the provided buffer
+
+ @Return   void
+
+******************************************************************************/
+#define RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__SERIES8                (12)
+#define RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST__SERIES8  (15)
+#define RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__ALBIORIX               (6)
+#define RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST__ALBIORIX (9)
+#define RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_LAST    (33)
+#define RGX_TEXAS_BIF0_TAG_RTU_RAC_FIRST       (41)
+#define RGX_TEXAS_BIF0_TAG_RTU_RAC_LAST                (48)
+#define RGX_TEXAS_BIF0_TAG_LAST                                (51)
+
+#define RGX_TEXAS_BIF1_TAG_LAST                                (26)
+
+#define RGX_JONES_BIF_IPP_TAG                          (0)
+#define RGX_JONES_BIF_DCE_TAG_FIRST                    (1)
+#define RGX_JONES_BIF_DCE_TAG_LAST                     (14)
+#define RGX_JONES_BIF_TDM_TAG_FIRST                    (15)
+#define RGX_JONES_BIF_TDM_TAG_LAST                     (19)
+#define RGX_JONES_BIF_PM_TAG                           (20)
+#define RGX_JONES_BIF_CDM_TAG_FIRST                    (21)
+#define RGX_JONES_BIF_CDM_TAG_LAST                     (31)
+#define RGX_JONES_BIF_META_TAG                         (32)
+#define RGX_JONES_BIF_META_DMA_TAG                     (33)
+#define RGX_JONES_BIF_TE_TAG_FIRST                     (34)
+#define RGX_JONES_BIF_TE_TAG_LAST                      (47)
+#define RGX_JONES_BIF_RTU_TAG_FIRST                    (48)
+#define RGX_JONES_BIF_RTU_TAG_LAST                     (53)
+#define RGX_JONES_BIF_RPM_TAG                          (54)
+#define RGX_JONES_BIF_TAG_LAST                         (54)
+
+
+/* The MCU L1 requestors are common to all Texas BIFs so put them
+ * in their own function. */
+static INLINE void _RGXDecodeMMUReqMCULevel1(PVRSRV_RGXDEV_INFO    *psDevInfo,
+                                                                                        IMG_UINT32  ui32TagID,
+                                                                                        IMG_CHAR    **ppszTagSB)
+{
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+       {
+               switch (ui32TagID)
+               {
+                       case  0: *ppszTagSB = "IP0 PDS"; break;
+                       case  1: *ppszTagSB = "IP0 Global"; break;
+                       case  2: *ppszTagSB = "IP1 PDS"; break;
+                       case  3: *ppszTagSB = "IP1 Global"; break;
+                       case  4: *ppszTagSB = "IP2 PDS"; break;
+                       case  5: *ppszTagSB = "IP2 Global"; break;
+               }
+       }
+       else
+       {
+               switch (ui32TagID)
+               {
+                       case  0: *ppszTagSB = "IP0 PDS"; break;
+                       case  1: *ppszTagSB = "IP0 Global"; break;
+                       case  2: *ppszTagSB = "IP0 BSC"; break;
+                       case  3: *ppszTagSB = "IP0 Constants"; break;
+
+                       case  4: *ppszTagSB = "IP1 PDS"; break;
+                       case  5: *ppszTagSB = "IP1 Global"; break;
+                       case  6: *ppszTagSB = "IP1 BSC"; break;
+                       case  7: *ppszTagSB = "IP1 Constants"; break;
+
+                       case  8: *ppszTagSB = "IP2 PDS"; break;
+                       case  9: *ppszTagSB = "IP2 Global"; break;
+                       case 10: *ppszTagSB = "IP2 BSC"; break;
+                       case 11: *ppszTagSB = "IP2 Constants"; break;
+               }
+       }
+}
+
+static void _RGXDecodeMMUReqTags(PVRSRV_RGXDEV_INFO    *psDevInfo,
+                                                                IMG_UINT32  ui32TagID,
+                                                                IMG_UINT32  ui32BIFModule,
+                                                                IMG_BOOL    bRead,
+                                                                IMG_BOOL    bWriteBack,
+                                                                IMG_BOOL    bFBMFault,
+                                                                IMG_CHAR    **ppszTagID,
+                                                                IMG_CHAR    **ppszTagSB,
+                                                                IMG_CHAR    *pszScratchBuf,
+                                                                IMG_UINT32  ui32ScratchBufSize)
+{
+       IMG_UINT32 ui32BIFsPerSPU = 2;
+       IMG_CHAR   *pszTagID = "-";
+       IMG_CHAR   *pszTagSB = "-";
+
+       PVR_ASSERT(ppszTagID != NULL);
+       PVR_ASSERT(ppszTagSB != NULL);
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+       {
+               ui32BIFsPerSPU = 4;
+       }
+
+       if (bFBMFault)
+       {
+               pszTagID = "FBM";
+               if (bWriteBack)
+               {
+                       pszTagSB = "Header/state cache request";
+               }
+       }
+       else if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, NUM_SPU) &&
+                ui32BIFModule <  RGX_GET_FEATURE_VALUE(psDevInfo, NUM_SPU)*ui32BIFsPerSPU)
+       {
+               if ((ui32BIFModule % ui32BIFsPerSPU) == 0)
+               {
+                       IMG_UINT32 ui32Tag_RGX_TEXAS_BIF0_MCU_L1_TAG_LAST =
+                               (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+                               ? RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__ALBIORIX
+                               : RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__SERIES8;
+                       IMG_UINT32 ui32Tag_RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST =
+                               (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+                               ? RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST__ALBIORIX
+                               : RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST__SERIES8;
+
+                       /* Texas 0 BIF */
+                       if (ui32TagID < ui32Tag_RGX_TEXAS_BIF0_MCU_L1_TAG_LAST)
+                       {
+                               pszTagID = "MCU L1";
+                               _RGXDecodeMMUReqMCULevel1(psDevInfo, ui32TagID, &pszTagSB);
+                       }
+                       else if (ui32TagID < ui32Tag_RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_FIRST)
+                       {
+                               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+                               {
+                                       switch (ui32TagID)
+                                       {
+                                               case 6: pszTagID = "TCU L1"; break;
+                                               case 7:
+                                               case 8: pszTagID = "PBE0"; break;
+                                       }
+                               }
+                               else
+                               {
+                                       switch (ui32TagID)
+                                       {
+                                               case 12: pszTagID = "TCU L1"; break;
+                                               case 13:
+                                               case 14: pszTagID = "PBE0"; break;
+                                       }
+                               }
+                       }
+                       else if (ui32TagID <= RGX_TEXAS_BIF0_TAG_IPFID_ARRAY_LAST)
+                       {
+                               pszTagID = "IPF ID Array";
+                       }
+                       else if (ui32TagID < RGX_TEXAS_BIF0_TAG_RTU_RAC_FIRST)
+                       {
+                               switch (ui32TagID)
+                               {
+                                       case 34: pszTagID = "IPF_CPF"; break;
+                                       case 35: pszTagID = "PPP"; break;
+                                       case 36:
+                                       case 37: pszTagID = "ISP0 ID Array"; break;
+                                       case 38:
+                                       case 39: pszTagID = "ISP2 ID Array"; break;
+                                       case 40: pszTagID = "VCE RTC"; break;
+                               }
+                       }
+                       else if (ui32TagID <= RGX_TEXAS_BIF0_TAG_RTU_RAC_LAST)
+                       {
+                               pszTagID = "RTU RAC";
+                       }
+                       else if (ui32TagID <= RGX_TEXAS_BIF0_TAG_LAST)
+                       {
+                               switch (ui32TagID)
+                               {
+                                       case 49: pszTagID = "VCE AMC"; break;
+                                       case 50:
+                                       case 51: pszTagID = "SHF"; break;
+                               }
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Unidentified Texas BIF Tag ID: %d", __func__, ui32TagID));
+                       }
+               }
+               else if ((ui32BIFModule % ui32BIFsPerSPU) == 1)
+               {
+                       IMG_UINT32 ui32Tag_RGX_TEXAS_BIF0_MCU_L1_TAG_LAST =
+                               (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+                               ? RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__ALBIORIX
+                               : RGX_TEXAS_BIF0_MCU_L1_TAG_LAST__SERIES8;
+
+                       /* Texas 1 BIF */
+                       if (ui32TagID < ui32Tag_RGX_TEXAS_BIF0_MCU_L1_TAG_LAST)
+                       {
+                               pszTagID = "MCU L1";
+                               _RGXDecodeMMUReqMCULevel1(psDevInfo, ui32TagID, &pszTagSB);
+                       }
+                       else if (ui32TagID <= RGX_TEXAS_BIF1_TAG_LAST)
+                       {
+                               switch (ui32TagID)
+                               {
+                                       /** Albiorix/NUM_TPU_PER_SPU > 1 **/
+                                       case 6:
+                                       case 7:  pszTagID = "BSC"; break;
+                                       /** All cores **/
+                                       case 12: pszTagID = "TCU L1"; break;
+                                       case 13: pszTagID = "TPF"; break;
+                                       case 14: pszTagID = "TPF CPF"; break;
+                                       case 15:
+                                       case 16: pszTagID = "PBE1"; break;
+                                       case 17: pszTagID = "PDSRW cache"; break;
+                                       case 18: pszTagID = "PDS"; break;
+                                       case 19:
+                                       case 20: pszTagID = "ISP1 ID Array"; break;
+                                       case 21: pszTagID = "USC L2"; break;
+                                       case 22: pszTagID = "VDM L2"; break;
+                                       case 23: pszTagID = "RTU FBA L2"; break;
+                                       case 24: pszTagID = "RTU SHR L2"; break;
+                                       case 25: pszTagID = "RTU SHG L2"; break;
+                                       case 26: pszTagID = "RTU TUL L2"; break;
+                               }
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Unidentified Texas BIF Tag ID: %d", __func__, ui32TagID));
+                       }
+               }
+       }
+       else if (ui32BIFModule == RGX_GET_FEATURE_VALUE(psDevInfo, NUM_SPU)*ui32BIFsPerSPU)
+       {
+               /* Jones BIF */
+
+               if ((ui32TagID >= RGX_JONES_BIF_DCE_TAG_FIRST) && (ui32TagID <= RGX_JONES_BIF_DCE_TAG_LAST))
+               {
+                       pszTagID = "DCE";
+               }
+               else if ((ui32TagID >= RGX_JONES_BIF_TDM_TAG_FIRST) && (ui32TagID <= RGX_JONES_BIF_TDM_TAG_LAST))
+               {
+                       pszTagID = "TDM";
+               }
+               else if ((ui32TagID >= RGX_JONES_BIF_CDM_TAG_FIRST) && (ui32TagID <= RGX_JONES_BIF_CDM_TAG_LAST))
+               {
+                       pszTagID = "CDM";
+               }
+               else if ((ui32TagID >= RGX_JONES_BIF_TE_TAG_FIRST) && (ui32TagID <= RGX_JONES_BIF_TE_TAG_LAST))
+               {
+                       pszTagID = "Tiling Engine (TE3)";
+               }
+               else if ((ui32TagID >= RGX_JONES_BIF_RTU_TAG_FIRST) && (ui32TagID <= RGX_JONES_BIF_RTU_TAG_LAST))
+               {
+                       pszTagID = "RTU";
+               }
+               else if (ui32TagID <= RGX_JONES_BIF_TAG_LAST)
+               {
+                       switch (ui32TagID)
+                       {
+                               case RGX_JONES_BIF_IPP_TAG:             pszTagID = "IPP"; break;
+                               case RGX_JONES_BIF_PM_TAG:              pszTagID = "PM"; break;
+                               case RGX_JONES_BIF_META_TAG:    pszTagID = "META"; break;
+                               case RGX_JONES_BIF_META_DMA_TAG:pszTagID = "META DMA"; break;
+                               case RGX_JONES_BIF_RPM_TAG:             pszTagID = "RPM"; break;
+                       }
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Unidentified Jones BIF Tag ID: %d", __func__, ui32TagID));
+               }
+       }
+       else if (bWriteBack)
+       {
+               pszTagID = "";
+               pszTagSB = "Writeback of dirty cacheline";
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: Unidentified BIF Module: %d", __func__, ui32BIFModule));
+       }
+
+       *ppszTagID = pszTagID;
+       *ppszTagSB = pszTagSB;
+}
+
+
+static void ConvertOSTimestampToSAndNS(IMG_UINT64 ui64OSTimer,
+                                                       IMG_UINT64 *pui64Seconds,
+                                                       IMG_UINT64 *pui64Nanoseconds)
+{
+       IMG_UINT32 ui32Remainder;
+
+       *pui64Seconds = OSDivide64r64(ui64OSTimer, 1000000000, &ui32Remainder);
+       *pui64Nanoseconds = ui64OSTimer - (*pui64Seconds * 1000000000ULL);
+}
+
+
+typedef enum _DEVICEMEM_HISTORY_QUERY_INDEX_
+{
+       DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING,
+       DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED,
+       DEVICEMEM_HISTORY_QUERY_INDEX_NEXT,
+       DEVICEMEM_HISTORY_QUERY_INDEX_COUNT,
+} DEVICEMEM_HISTORY_QUERY_INDEX;
+
+
+/*!
+*******************************************************************************
+
+ @Function     _PrintDevicememHistoryQueryResult
+
+ @Description
+
+ Print details of a single result from a DevicememHistory query
+
+ @Input pfnDumpDebugPrintf       - Debug printf function
+ @Input pvDumpDebugFile          - Optional file identifier to be passed to the
+                                   'printf' function if required
+ @Input psFaultProcessInfo       - The process info derived from the page fault
+ @Input psResult                 - The DevicememHistory result to be printed
+ @Input ui32Index                - The index of the result
+
+ @Return   void
+
+******************************************************************************/
+static void _PrintDevicememHistoryQueryResult(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile,
+                                               RGXMEM_PROCESS_INFO *psFaultProcessInfo,
+                                               DEVICEMEM_HISTORY_QUERY_OUT_RESULT *psResult,
+                                               IMG_UINT32 ui32Index,
+                                               const IMG_CHAR* pszIndent)
+{
+       IMG_UINT32 ui32Remainder;
+       IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+
+       ConvertOSTimestampToSAndNS(psResult->ui64When,
+                                                       &ui64Seconds,
+                                                       &ui64Nanoseconds);
+
+       if (psFaultProcessInfo->uiPID != RGXMEM_SERVER_PID_FIRMWARE)
+       {
+               PVR_DUMPDEBUG_LOG("%s    [%u] Name: %s Base address: " IMG_DEV_VIRTADDR_FMTSPEC
+                                       " Size: " IMG_DEVMEM_SIZE_FMTSPEC
+                                       " Operation: %s Modified: %" IMG_UINT64_FMTSPEC
+                                       " us ago (OS time %" IMG_UINT64_FMTSPEC
+                                       ".%09" IMG_UINT64_FMTSPEC " s)",
+                                               pszIndent,
+                                               ui32Index,
+                                               psResult->szString,
+                                               psResult->sBaseDevVAddr.uiAddr,
+                                               psResult->uiSize,
+                                               psResult->bMap ? "Map": "Unmap",
+                                               OSDivide64r64(psResult->ui64Age, 1000, &ui32Remainder),
+                                               ui64Seconds,
+                                               ui64Nanoseconds);
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("%s    [%u] Name: %s Base address: " IMG_DEV_VIRTADDR_FMTSPEC
+                                       " Size: " IMG_DEVMEM_SIZE_FMTSPEC
+                                       " Operation: %s Modified: %" IMG_UINT64_FMTSPEC
+                                       " us ago (OS time %" IMG_UINT64_FMTSPEC
+                                       ".%09" IMG_UINT64_FMTSPEC
+                                       ") PID: %u (%s)",
+                                               pszIndent,
+                                               ui32Index,
+                                               psResult->szString,
+                                               psResult->sBaseDevVAddr.uiAddr,
+                                               psResult->uiSize,
+                                               psResult->bMap ? "Map": "Unmap",
+                                               OSDivide64r64(psResult->ui64Age, 1000, &ui32Remainder),
+                                               ui64Seconds,
+                                               ui64Nanoseconds,
+                                               psResult->sProcessInfo.uiPID,
+                                               psResult->sProcessInfo.szProcessName);
+       }
+
+       if (!psResult->bRange)
+       {
+               PVR_DUMPDEBUG_LOG("%s        Whole allocation was %s", pszIndent, psResult->bMap ? "mapped": "unmapped");
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("%s        Pages %u to %u (" IMG_DEV_VIRTADDR_FMTSPEC "-" IMG_DEV_VIRTADDR_FMTSPEC ") %s%s",
+                                                                               pszIndent,
+                                                                               psResult->ui32StartPage,
+                                                                               psResult->ui32StartPage + psResult->ui32PageCount - 1,
+                                                                               psResult->sMapStartAddr.uiAddr,
+                                                                               psResult->sMapEndAddr.uiAddr,
+                                                                               psResult->bAll ? "(whole allocation) " : "",
+                                                                               psResult->bMap ? "mapped": "unmapped");
+       }
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _PrintDevicememHistoryQueryOut
+
+ @Description
+
+ Print details of all the results from a DevicememHistory query
+
+ @Input pfnDumpDebugPrintf       - Debug printf function
+ @Input pvDumpDebugFile          - Optional file identifier to be passed to the
+                                   'printf' function if required
+ @Input psFaultProcessInfo       - The process info derived from the page fault
+ @Input psQueryOut               - Storage for the query results
+
+ @Return   void
+
+******************************************************************************/
+static void _PrintDevicememHistoryQueryOut(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile,
+                                               RGXMEM_PROCESS_INFO *psFaultProcessInfo,
+                                               DEVICEMEM_HISTORY_QUERY_OUT *psQueryOut,
+                                               const IMG_CHAR* pszIndent)
+{
+       IMG_UINT32 i;
+
+       if (psQueryOut->ui32NumResults == 0)
+       {
+               PVR_DUMPDEBUG_LOG("%s    No results", pszIndent);
+       }
+       else
+       {
+               for (i = 0; i < psQueryOut->ui32NumResults; i++)
+               {
+                       _PrintDevicememHistoryQueryResult(pfnDumpDebugPrintf, pvDumpDebugFile,
+                                                                       psFaultProcessInfo,
+                                                                       &psQueryOut->sResults[i],
+                                                                       i,
+                                                                       pszIndent);
+               }
+       }
+}
+
+/* table of HW page size values and the equivalent */
+static const unsigned int aui32HWPageSizeTable[][2] =
+{
+       { 0, PVRSRV_4K_PAGE_SIZE },
+       { 1, PVRSRV_16K_PAGE_SIZE },
+       { 2, PVRSRV_64K_PAGE_SIZE },
+       { 3, PVRSRV_256K_PAGE_SIZE },
+       { 4, PVRSRV_1M_PAGE_SIZE },
+       { 5, PVRSRV_2M_PAGE_SIZE }
+};
+
+/*!
+*******************************************************************************
+
+ @Function     _PageSizeHWToBytes
+
+ @Description
+
+ Convert a HW page size value to its size in bytes
+
+ @Input ui32PageSizeHW     - The HW page size value
+
+ @Return   IMG_UINT32      The page size in bytes
+
+******************************************************************************/
+static IMG_UINT32 _PageSizeHWToBytes(IMG_UINT32 ui32PageSizeHW)
+{
+       if (ui32PageSizeHW > 5)
+       {
+               /* This is invalid, so return a default value as we cannot ASSERT in this code! */
+               return PVRSRV_4K_PAGE_SIZE;
+       }
+
+       return aui32HWPageSizeTable[ui32PageSizeHW][1];
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _GetDevicememHistoryData
+
+ @Description
+
+ Get the DevicememHistory results for the given PID and faulting device virtual address.
+ The function will query DevicememHistory for information about the faulting page, as well
+ as the page before and after.
+
+ @Input uiPID              - The process ID to search for allocations belonging to
+ @Input sFaultDevVAddr     - The device address to search for allocations at/before/after
+ @Input asQueryOut         - Storage for the query results
+ @Input ui32PageSizeBytes  - Faulted page size in bytes
+
+ @Return IMG_BOOL          - IMG_TRUE if any results were found for this page fault
+
+******************************************************************************/
+static IMG_BOOL _GetDevicememHistoryData(IMG_PID uiPID, IMG_DEV_VIRTADDR sFaultDevVAddr,
+                                                       DEVICEMEM_HISTORY_QUERY_OUT asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_COUNT],
+                                                       IMG_UINT32 ui32PageSizeBytes)
+{
+       DEVICEMEM_HISTORY_QUERY_IN sQueryIn;
+       IMG_BOOL bAnyHits = IMG_FALSE;
+
+       /* if the page fault originated in the firmware then the allocation may
+        * appear to belong to any PID, because FW allocations are attributed
+        * to the client process creating the allocation, so instruct the
+        * devicemem_history query to search all available PIDs
+        */
+       if (uiPID == RGXMEM_SERVER_PID_FIRMWARE)
+       {
+               sQueryIn.uiPID = DEVICEMEM_HISTORY_PID_ANY;
+       }
+       else
+       {
+               sQueryIn.uiPID = uiPID;
+       }
+
+       /* Query the DevicememHistory for all allocations in the previous page... */
+       sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) - ui32PageSizeBytes;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING],
+                                 ui32PageSizeBytes, IMG_TRUE))
+       {
+               bAnyHits = IMG_TRUE;
+       }
+
+       /* Query the DevicememHistory for any record at the exact address... */
+       sQueryIn.sDevVAddr = sFaultDevVAddr;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED],
+                                 ui32PageSizeBytes, IMG_FALSE))
+       {
+               bAnyHits = IMG_TRUE;
+       }
+       else
+       {
+               /* If not matched then try matching any record in the faulting page... */
+               if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED],
+                                         ui32PageSizeBytes, IMG_TRUE))
+               {
+                       bAnyHits = IMG_TRUE;
+               }
+       }
+
+       /* Query the DevicememHistory for all allocations in the next page... */
+       sQueryIn.sDevVAddr.uiAddr = (sFaultDevVAddr.uiAddr & ~(IMG_UINT64)(ui32PageSizeBytes - 1)) + ui32PageSizeBytes;
+       if (DevicememHistoryQuery(&sQueryIn, &asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_NEXT],
+                                 ui32PageSizeBytes, IMG_TRUE))
+       {
+               bAnyHits = IMG_TRUE;
+       }
+
+       return bAnyHits;
+}
+
+/* stored data about one page fault */
+typedef struct _FAULT_INFO_
+{
+       /* the process info of the memory context that page faulted */
+       RGXMEM_PROCESS_INFO sProcessInfo;
+       IMG_DEV_VIRTADDR sFaultDevVAddr;
+       MMU_FAULT_DATA   sMMUFaultData;
+       DEVICEMEM_HISTORY_QUERY_OUT asQueryOut[DEVICEMEM_HISTORY_QUERY_INDEX_COUNT];
+       /* the CR timer value at the time of the fault, recorded by the FW.
+        * used to differentiate different page faults
+        */
+       IMG_UINT64 ui64CRTimer;
+       /* time when this FAULT_INFO entry was added. used for timing
+        * reference against the map/unmap information
+        */
+       IMG_UINT64 ui64When;
+       IMG_UINT32 ui32FaultInfoFlags;
+} FAULT_INFO;
+
+/* history list of page faults.
+ * Keeps the first `n` page faults and the last `n` page faults, like the FW
+ * HWR log
+ */
+typedef struct _FAULT_INFO_LOG_
+{
+       IMG_UINT32 ui32Head;
+       /* the number of faults in this log need not correspond exactly to
+        * the HWINFO number of the FW, as the FW HWINFO log may contain
+        * non-page fault HWRs
+        */
+       FAULT_INFO asFaults[RGXFWIF_HWINFO_MAX];
+} FAULT_INFO_LOG;
+
+#define FAULT_INFO_PROC_INFO   (0x1U)
+#define FAULT_INFO_DEVMEM_HIST (0x2U)
+
+static FAULT_INFO_LOG gsFaultInfoLog = { 0 };
+
+static void _FillAppForFWFaults(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                       FAULT_INFO *psInfo,
+                                                       RGXMEM_PROCESS_INFO *psProcInfo)
+{
+       IMG_UINT32 i, j;
+
+       for (i = 0; i < DEVICEMEM_HISTORY_QUERY_INDEX_COUNT; i++)
+       {
+               for (j = 0; j < DEVICEMEM_HISTORY_QUERY_OUT_MAX_RESULTS; j++)
+               {
+                       IMG_BOOL bFound;
+
+                       RGXMEM_PROCESS_INFO *psProcInfo = &psInfo->asQueryOut[i].sResults[j].sProcessInfo;
+                       bFound = RGXPCPIDToProcessInfo(psDevInfo,
+                                                               psProcInfo->uiPID,
+                                                               psProcInfo);
+                       if (!bFound)
+                       {
+                               OSStringLCopy(psProcInfo->szProcessName,
+                                                               "(unknown)",
+                                                               sizeof(psProcInfo->szProcessName));
+                       }
+               }
+       }
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _PrintFaultInfo
+
+ @Description
+
+ Print all the details of a page fault from a FAULT_INFO structure
+
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Input psInfo               - The page fault occurrence to print
+
+ @Return   void
+
+******************************************************************************/
+static void _PrintFaultInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       FAULT_INFO *psInfo,
+                                       const IMG_CHAR* pszIndent)
+{
+       IMG_UINT32 i;
+       IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+
+       ConvertOSTimestampToSAndNS(psInfo->ui64When, &ui64Seconds, &ui64Nanoseconds);
+
+       if (BITMASK_HAS(psInfo->ui32FaultInfoFlags, FAULT_INFO_PROC_INFO))
+       {
+               IMG_PID uiPID = (psInfo->sProcessInfo.uiPID == RGXMEM_SERVER_PID_FIRMWARE || psInfo->sProcessInfo.uiPID == RGXMEM_SERVER_PID_PM) ?
+                                                       0 : psInfo->sProcessInfo.uiPID;
+
+               PVR_DUMPDEBUG_LOG("%sDevice memory history for page fault address " IMG_DEV_VIRTADDR_FMTSPEC
+                                                       ", CRTimer: 0x%016" IMG_UINT64_FMTSPECX
+                                                       ", PID: %u (%s, unregistered: %u) OS time: "
+                                                       "%" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC,
+                                       pszIndent,
+                                       psInfo->sFaultDevVAddr.uiAddr,
+                                       psInfo->ui64CRTimer,
+                                       uiPID,
+                                       psInfo->sProcessInfo.szProcessName,
+                                       psInfo->sProcessInfo.bUnregistered,
+                                       ui64Seconds,
+                                       ui64Nanoseconds);
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("%sCould not find PID for device memory history on PC of the fault", pszIndent);
+       }
+
+       if (BITMASK_HAS(psInfo->ui32FaultInfoFlags, FAULT_INFO_DEVMEM_HIST))
+       {
+               for (i = DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING; i < DEVICEMEM_HISTORY_QUERY_INDEX_COUNT; i++)
+               {
+                       const IMG_CHAR *pszWhich = NULL;
+
+                       switch (i)
+                       {
+                               case DEVICEMEM_HISTORY_QUERY_INDEX_PRECEDING:
+                                       pszWhich = "Preceding page";
+                                       break;
+                               case DEVICEMEM_HISTORY_QUERY_INDEX_FAULTED:
+                                       pszWhich = "Faulted page";
+                                       break;
+                               case DEVICEMEM_HISTORY_QUERY_INDEX_NEXT:
+                                       pszWhich = "Next page";
+                                       break;
+                       }
+
+                       PVR_DUMPDEBUG_LOG("%s  %s:", pszIndent, pszWhich);
+                       _PrintDevicememHistoryQueryOut(pfnDumpDebugPrintf, pvDumpDebugFile,
+                                                               &psInfo->sProcessInfo,
+                                                               &psInfo->asQueryOut[i],
+                                                               pszIndent);
+               }
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("%s  No matching Devmem History for fault address", pszIndent);
+       }
+}
+
+static void _RecordFaultInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                       FAULT_INFO *psInfo,
+                                       IMG_DEV_VIRTADDR sFaultDevVAddr,
+                                       IMG_DEV_PHYADDR sPCDevPAddr,
+                                       IMG_UINT64 ui64CRTimer,
+                                       IMG_UINT32 ui32PageSizeBytes)
+{
+       IMG_BOOL bFound = IMG_FALSE, bIsPMFault = IMG_FALSE;
+       RGXMEM_PROCESS_INFO sProcessInfo;
+
+       psInfo->ui32FaultInfoFlags = 0;
+       psInfo->sFaultDevVAddr = sFaultDevVAddr;
+       psInfo->ui64CRTimer = ui64CRTimer;
+       psInfo->ui64When = OSClockns64();
+
+       if (GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED)
+       {
+               /* Check if this is PM fault */
+               if (psInfo->sMMUFaultData.eType == MMU_FAULT_TYPE_PM)
+               {
+                       bIsPMFault = IMG_TRUE;
+                       bFound = IMG_TRUE;
+                       sProcessInfo.uiPID = RGXMEM_SERVER_PID_PM;
+                       OSStringLCopy(sProcessInfo.szProcessName, "PM", sizeof(sProcessInfo.szProcessName));
+                       sProcessInfo.szProcessName[sizeof(sProcessInfo.szProcessName) - 1] = '\0';
+                       sProcessInfo.bUnregistered = IMG_FALSE;
+               }
+               else
+               {
+                       /* look up the process details for the faulting page catalogue */
+                       bFound = RGXPCAddrToProcessInfo(psDevInfo, sPCDevPAddr, &sProcessInfo);
+               }
+
+               if (bFound)
+               {
+                       IMG_BOOL bHits;
+
+                       psInfo->ui32FaultInfoFlags = FAULT_INFO_PROC_INFO;
+                       psInfo->sProcessInfo = sProcessInfo;
+
+                       if (bIsPMFault)
+                       {
+                               bHits = IMG_TRUE;
+                       }
+                       else
+                       {
+                               /* get any DevicememHistory data for the faulting address */
+                               bHits = _GetDevicememHistoryData(sProcessInfo.uiPID,
+                                                                sFaultDevVAddr,
+                                                                psInfo->asQueryOut,
+                                                                ui32PageSizeBytes);
+
+                               if (bHits)
+                               {
+                                       psInfo->ui32FaultInfoFlags |= FAULT_INFO_DEVMEM_HIST;
+
+                                       /* if the page fault was caused by the firmware then get information about
+                                        * which client application created the related allocations.
+                                        *
+                                        * Fill in the process info data for each query result.
+                                        */
+
+                                       if (sProcessInfo.uiPID == RGXMEM_SERVER_PID_FIRMWARE)
+                                       {
+                                               _FillAppForFWFaults(psDevInfo, psInfo, &sProcessInfo);
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _DumpFaultAddressHostView
+
+ @Description
+
+ Dump FW HWR fault status in human readable form.
+
+ @Input ui32Index            - Index of global Fault info
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Return   void
+
+******************************************************************************/
+static void _DumpFaultAddressHostView(MMU_FAULT_DATA *psFaultData,
+                                       DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       const IMG_CHAR* pszIndent)
+{
+       MMU_LEVEL eTopLevel;
+       const IMG_CHAR szPageLevel[][4] = {"", "PTE", "PDE", "PCE" };
+       const IMG_CHAR szPageError[][3] = {"", "PT",  "PD",  "PC"  };
+
+       eTopLevel = psFaultData->eTopLevel;
+
+       if (psFaultData->eType == MMU_FAULT_TYPE_UNKNOWN)
+       {
+               PVR_DUMPDEBUG_LOG("%sNo live host MMU data available", pszIndent);
+               return;
+       }
+       else if (psFaultData->eType == MMU_FAULT_TYPE_PM)
+       {
+               PVR_DUMPDEBUG_LOG("%sPM faulted at PC address = 0x%016" IMG_UINT64_FMTSPECx, pszIndent, psFaultData->sLevelData[MMU_LEVEL_0].ui64Address);
+       }
+       else
+       {
+               MMU_LEVEL eCurrLevel;
+               PVR_ASSERT(eTopLevel < MMU_LEVEL_LAST);
+
+               for (eCurrLevel = eTopLevel; eCurrLevel > MMU_LEVEL_0; eCurrLevel--)
+               {
+                       MMU_LEVEL_DATA *psMMULevelData = &psFaultData->sLevelData[eCurrLevel];
+                       if (psMMULevelData->ui64Address)
+                       {
+                               if (psMMULevelData->uiBytesPerEntry == 4)
+                               {
+                                       PVR_DUMPDEBUG_LOG("%s%s for index %d = 0x%08x and is %s",
+                                                               pszIndent,
+                                                               szPageLevel[eCurrLevel],
+                                                               psMMULevelData->ui32Index,
+                                                               (IMG_UINT) psMMULevelData->ui64Address,
+                                                               psMMULevelData->psDebugStr);
+                               }
+                               else
+                               {
+                                       PVR_DUMPDEBUG_LOG("%s%s for index %d = 0x%016" IMG_UINT64_FMTSPECx " and is %s",
+                                                               pszIndent,
+                                                               szPageLevel[eCurrLevel],
+                                                               psMMULevelData->ui32Index,
+                                                               psMMULevelData->ui64Address,
+                                                               psMMULevelData->psDebugStr);
+                               }
+                       }
+                       else
+                       {
+                               PVR_DUMPDEBUG_LOG("%s%s index (%d) out of bounds (%d)",
+                                                       pszIndent,
+                                                       szPageError[eCurrLevel],
+                                                       psMMULevelData->ui32Index,
+                                                       psMMULevelData->ui32NumOfEntries);
+                               break;
+                       }
+               }
+       }
+
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _RGXDumpRGXMMUFaultStatus
+
+ @Description
+
+ Dump MMU Fault status in human readable form.
+
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Input psDevInfo            - RGX device info
+ @Input ui64MMUStatus        - MMU Status register value
+ @Input pszMetaOrCore        - string representing call is for META or MMU core
+ @Return   void
+
+******************************************************************************/
+static void _RGXDumpRGXMMUFaultStatus(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       PVRSRV_RGXDEV_INFO *psDevInfo,
+                                       const IMG_UINT64 aui64MMUStatus[],
+                                       const IMG_PCHAR pszMetaOrCore,
+                                       const IMG_CHAR *pszIndent)
+{
+       if (aui64MMUStatus[0] == 0x0)
+       {
+               PVR_DUMPDEBUG_LOG("%sMMU (%s) - OK", pszIndent, pszMetaOrCore);
+       }
+       else
+       {
+               IMG_UINT32 ui32PC        = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_CONTEXT_CLRMSK) >>
+                                          RGX_CR_MMU_FAULT_STATUS1_CONTEXT_SHIFT;
+               IMG_UINT64 ui64Addr      = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_ADDRESS_CLRMSK) >>
+                                          RGX_CR_MMU_FAULT_STATUS1_ADDRESS_SHIFT) <<  4; /* align shift */
+               IMG_UINT32 ui32Requester = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_REQ_ID_CLRMSK) >>
+                                          RGX_CR_MMU_FAULT_STATUS1_REQ_ID_SHIFT;
+               IMG_UINT32 ui32MMULevel  = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_LEVEL_CLRMSK) >>
+                                          RGX_CR_MMU_FAULT_STATUS1_LEVEL_SHIFT;
+               IMG_BOOL bRead           = (aui64MMUStatus[0] & RGX_CR_MMU_FAULT_STATUS1_RNW_EN) != 0;
+               IMG_BOOL bFault          = (aui64MMUStatus[0] & RGX_CR_MMU_FAULT_STATUS1_FAULT_EN) != 0;
+               IMG_BOOL bROFault        = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_TYPE_CLRMSK) >>
+                                           RGX_CR_MMU_FAULT_STATUS1_TYPE_SHIFT) == 0x2;
+               IMG_BOOL bProtFault      = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_TYPE_CLRMSK) >>
+                                           RGX_CR_MMU_FAULT_STATUS1_TYPE_SHIFT) == 0x3;
+               IMG_UINT32 ui32BIFModule;
+               IMG_BOOL bWriteBack, bFBMFault;
+               IMG_CHAR aszScratch[RGX_DEBUG_STR_SIZE];
+               IMG_CHAR *pszTagID = NULL;
+               IMG_CHAR *pszTagSB = NULL;
+               const IMG_PCHAR pszMetaOrRiscv = RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ? "META" : "RISCV";
+
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, ALBIORIX_TOP_INFRASTRUCTURE))
+               {
+                       ui32BIFModule = (aui64MMUStatus[1] & ~RGX_CR_MMU_FAULT_STATUS2__ALBTOP__BIF_ID_CLRMSK) >>
+                                                                               RGX_CR_MMU_FAULT_STATUS2__ALBTOP__BIF_ID_SHIFT;
+                       bWriteBack    = (aui64MMUStatus[1] & RGX_CR_MMU_FAULT_STATUS2__ALBTOP__WRITEBACK_EN) != 0;
+                       bFBMFault     = (aui64MMUStatus[1] & RGX_CR_MMU_FAULT_STATUS2__ALBTOP__FBM_FAULT_EN) != 0;
+               }
+               else
+               {
+                       ui32BIFModule = (aui64MMUStatus[1] & ~RGX_CR_MMU_FAULT_STATUS2_BIF_ID_CLRMSK) >>
+                                                                               RGX_CR_MMU_FAULT_STATUS2_BIF_ID_SHIFT;
+                       bWriteBack    = (aui64MMUStatus[1] & RGX_CR_MMU_FAULT_STATUS2_WRITEBACK_EN) != 0;
+                       bFBMFault     = (aui64MMUStatus[1] & RGX_CR_MMU_FAULT_STATUS2_FBM_FAULT_EN) != 0;
+               }
+
+               if (strcmp(pszMetaOrCore, "Core") != 0)
+               {
+                       ui32PC          = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_SHIFT;
+                       ui64Addr        = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_SHIFT) <<  4; /* align shift */
+                       ui32Requester = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_SHIFT;
+                       ui32MMULevel  = (aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_LEVEL_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_LEVEL_SHIFT;
+                       bRead           = (aui64MMUStatus[0] & RGX_CR_MMU_FAULT_STATUS_META_RNW_EN) != 0;
+                       bFault      = (aui64MMUStatus[0] & RGX_CR_MMU_FAULT_STATUS_META_FAULT_EN) != 0;
+                       bROFault    = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT) == 0x2;
+                       bProtFault  = ((aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK) >>
+                                                               RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT) == 0x3;
+               }
+               else
+               {
+                       _RGXDecodeMMUReqTags(psDevInfo, ui32Requester, ui32BIFModule, bRead, bWriteBack, bFBMFault, &pszTagID, &pszTagSB, aszScratch, RGX_DEBUG_STR_SIZE);
+               }
+
+               PVR_DUMPDEBUG_LOG("%sMMU (%s) - FAULT:", pszIndent, pszMetaOrCore);
+               PVR_DUMPDEBUG_LOG("%s  * MMU status (0x%016" IMG_UINT64_FMTSPECX " | 0x%08" IMG_UINT64_FMTSPECX "): PC = %d, %s 0x%010" IMG_UINT64_FMTSPECX ", %s(%s)%s%s%s%s.",
+                                                 pszIndent,
+                                                 aui64MMUStatus[0],
+                                                 aui64MMUStatus[1],
+                                                 ui32PC,
+                                                 (bRead)?"Reading from":"Writing to",
+                                                 ui64Addr,
+                                                 (pszTagID)? pszTagID : pszMetaOrRiscv,
+                                                 (pszTagSB)? pszTagSB : "-",
+                                                 (bFault)?", Fault":"",
+                                                 (bROFault)?", Read Only fault":"",
+                                                 (bProtFault)?", PM/FW core protection fault":"",
+                                                 _RGXDecodeMMULevel(ui32MMULevel));
+
+       }
+}
+
+static_assert((RGX_CR_MMU_FAULT_STATUS1_CONTEXT_CLRMSK == RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_CLRMSK),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_CONTEXT_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_CONTEXT_SHIFT),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_ADDRESS_CLRMSK == RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_CLRMSK),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_ADDRESS_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_ADDRESS_SHIFT),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_REQ_ID_CLRMSK == RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_CLRMSK),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_REQ_ID_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_REQ_ID_SHIFT),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_LEVEL_CLRMSK == RGX_CR_MMU_FAULT_STATUS_META_LEVEL_CLRMSK),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_LEVEL_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_LEVEL_SHIFT),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_RNW_EN == RGX_CR_MMU_FAULT_STATUS_META_RNW_EN),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_FAULT_EN == RGX_CR_MMU_FAULT_STATUS_META_FAULT_EN),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_TYPE_CLRMSK == RGX_CR_MMU_FAULT_STATUS_META_TYPE_CLRMSK),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+static_assert((RGX_CR_MMU_FAULT_STATUS1_TYPE_SHIFT == RGX_CR_MMU_FAULT_STATUS_META_TYPE_SHIFT),
+                         "RGX_CR_MMU_FAULT_STATUS_META mismatch!");
+
+
+static const IMG_FLAGS2DESC asCswOpts2Description[] =
+{
+       {RGXFWIF_INICFG_CTXSWITCH_PROFILE_FAST, " Fast CSW profile;"},
+       {RGXFWIF_INICFG_CTXSWITCH_PROFILE_MEDIUM, " Medium CSW profile;"},
+       {RGXFWIF_INICFG_CTXSWITCH_PROFILE_SLOW, " Slow CSW profile;"},
+       {RGXFWIF_INICFG_CTXSWITCH_PROFILE_NODELAY, " No Delay CSW profile;"},
+       {RGXFWIF_INICFG_CTXSWITCH_MODE_RAND, " Random Csw enabled;"},
+       {RGXFWIF_INICFG_CTXSWITCH_SRESET_EN, " SoftReset;"},
+};
+
+static const IMG_FLAGS2DESC asMisc2Description[] =
+{
+       {RGXFWIF_INICFG_POW_RASCALDUST, " Power Rascal/Dust;"},
+       {RGXFWIF_INICFG_HWPERF_EN, " HwPerf EN;"},
+       {RGXFWIF_INICFG_FBCDC_V3_1_EN, " FBCDCv3.1;"},
+       {RGXFWIF_INICFG_CHECK_MLIST_EN, " Check MList;"},
+       {RGXFWIF_INICFG_DISABLE_CLKGATING_EN, " ClockGating Off;"},
+       {RGXFWIF_INICFG_REGCONFIG_EN, " Register Config;"},
+       {RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY, " Assert on OOM;"},
+       {RGXFWIF_INICFG_HWP_DISABLE_FILTER, " HWP Filter Off;"},
+       {RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN, " CDM Random kill;"},
+       {RGXFWIF_INICFG_DISABLE_DM_OVERLAP, " DM Overlap Off;"},
+       {RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER, " Assert on HWR;"},
+       {RGXFWIF_INICFG_FABRIC_COHERENCY_ENABLED, " Coherent fabric on;"},
+       {RGXFWIF_INICFG_VALIDATE_IRQ, " Validate IRQ;"},
+       {RGXFWIF_INICFG_DISABLE_PDP_EN, " PDUMP Panic off;"},
+       {RGXFWIF_INICFG_SPU_POWER_STATE_MASK_CHANGE_EN, " SPU Pow mask change on;"},
+       {RGXFWIF_INICFG_WORKEST, " Workload Estim;"},
+       {RGXFWIF_INICFG_PDVFS, " PDVFS;"},
+       {RGXFWIF_INICFG_CDM_ARBITRATION_TASK_DEMAND, " CDM task demand arbitration;"},
+       {RGXFWIF_INICFG_CDM_ARBITRATION_ROUND_ROBIN, " CDM round-robin arbitration;"},
+       {RGXFWIF_INICFG_ISPSCHEDMODE_VER1_IPP, " ISP v1 scheduling;"},
+       {RGXFWIF_INICFG_ISPSCHEDMODE_VER2_ISP, " ISP v2 scheduling;"},
+       {RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER, " Validate SOC&USC timers;"}
+};
+
+static const IMG_FLAGS2DESC asFwOsCfg2Description[] =
+{
+       {RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN, " TDM;"},
+       {RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN, " GEOM;"},
+       {RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN, " 3D;"},
+       {RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN, " CDM;"},
+       {RGXFWIF_INICFG_OS_CTXSWITCH_RDM_EN, " RDM;"},
+       {RGXFWIF_INICFG_OS_LOW_PRIO_CS_TDM, " LowPrio TDM;"},
+       {RGXFWIF_INICFG_OS_LOW_PRIO_CS_GEOM, " LowPrio GEOM;"},
+       {RGXFWIF_INICFG_OS_LOW_PRIO_CS_3D, " LowPrio 3D;"},
+       {RGXFWIF_INICFG_OS_LOW_PRIO_CS_CDM, " LowPrio CDM;"},
+       {RGXFWIF_INICFG_OS_LOW_PRIO_CS_RDM, " LowPrio RDM;"},
+};
+
+static const IMG_FLAGS2DESC asHwrState2Description[] =
+{
+       {RGXFWIF_HWR_HARDWARE_OK, " HWR OK;"},
+       {RGXFWIF_HWR_RESET_IN_PROGRESS, " Reset ongoing;"},
+       {RGXFWIF_HWR_GENERAL_LOCKUP, " General lockup;"},
+       {RGXFWIF_HWR_DM_RUNNING_OK, " DM running ok;"},
+       {RGXFWIF_HWR_DM_STALLING, " DM stalling;"},
+       {RGXFWIF_HWR_FW_FAULT, " FW Fault;"},
+       {RGXFWIF_HWR_RESTART_REQUESTED, " Restart requested;"},
+};
+
+static const IMG_FLAGS2DESC asDmState2Description[] =
+{
+       {RGXFWIF_DM_STATE_READY_FOR_HWR, " ready for hwr;"},
+       {RGXFWIF_DM_STATE_NEEDS_SKIP, " needs skip;"},
+       {RGXFWIF_DM_STATE_NEEDS_PR_CLEANUP, " needs PR cleanup;"},
+       {RGXFWIF_DM_STATE_NEEDS_TRACE_CLEAR, " needs trace clear;"},
+       {RGXFWIF_DM_STATE_GUILTY_LOCKUP, " guilty lockup;"},
+       {RGXFWIF_DM_STATE_INNOCENT_LOCKUP, " innocent lockup;"},
+       {RGXFWIF_DM_STATE_GUILTY_OVERRUNING, " guilty overrunning;"},
+       {RGXFWIF_DM_STATE_INNOCENT_OVERRUNING, " innocent overrunning;"},
+       {RGXFWIF_DM_STATE_GPU_ECC_HWR, " GPU ECC hwr;"},
+};
+
+static const IMG_FLAGS2DESC asHWErrorState[] =
+{
+       {RGX_HW_ERR_NA, "N/A"},
+       {RGX_HW_ERR_PRIMID_FAILURE_DURING_DMKILL, "Primitive ID failure during DM kill."},
+};
+
+#if !defined(NO_HARDWARE)
+static inline IMG_CHAR const *_GetRISCVException(IMG_UINT32 ui32Mcause)
+{
+       switch (ui32Mcause)
+       {
+#define X(value, fatal, description) \
+               case value: \
+                       if (fatal) \
+                               return description; \
+                       return NULL;
+
+               RGXRISCVFW_MCAUSE_TABLE
+#undef X
+
+               default:
+                       PVR_DPF((PVR_DBG_WARNING, "Invalid RISC-V FW mcause value 0x%08x", ui32Mcause));
+                       return NULL;
+       }
+}
+#endif // !defined(NO_HARDWARE)
+
+/*
+       Appends flags strings to a null-terminated string buffer - each flag
+       description string starts with a space.
+*/
+static void _Flags2Description(IMG_CHAR *psDesc,
+                               IMG_UINT32 ui32DescSize,
+                               const IMG_FLAGS2DESC *psConvTable,
+                               IMG_UINT32 ui32TableSize,
+                               IMG_UINT32 ui32Flags)
+{
+       IMG_UINT32 ui32Idx;
+
+       for (ui32Idx = 0; ui32Idx < ui32TableSize; ui32Idx++)
+       {
+               if ((ui32Flags & psConvTable[ui32Idx].uiFlag) == psConvTable[ui32Idx].uiFlag)
+               {
+                       OSStringLCat(psDesc, psConvTable[ui32Idx].pszLabel, ui32DescSize);
+               }
+       }
+}
+
+/*
+ *  Translate ID code to descriptive string.
+ *  Returns on the first match.
+ */
+static void _ID2Description(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, const IMG_FLAGS2DESC *psConvTable, IMG_UINT32 ui32TableSize, IMG_UINT32 ui32ID)
+{
+       IMG_UINT32 ui32Idx;
+
+       for (ui32Idx = 0; ui32Idx < ui32TableSize; ui32Idx++)
+       {
+               if (ui32ID == psConvTable[ui32Idx].uiFlag)
+               {
+                       OSStringLCopy(psDesc, psConvTable[ui32Idx].pszLabel, ui32DescSize);
+                       return;
+               }
+       }
+}
+
+/*
+       Writes flags strings to an uninitialised buffer.
+*/
+static void _GetFwSysFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, IMG_UINT32 ui32RawFlags)
+{
+       const IMG_CHAR szCswLabel[] = "Ctx switch options:";
+       size_t uLabelLen = sizeof(szCswLabel) - 1;
+       const size_t uiBytesPerDesc = (ui32DescSize - uLabelLen) / 2U - 1U;
+
+       OSStringLCopy(psDesc, szCswLabel, ui32DescSize);
+
+       _Flags2Description(psDesc, uiBytesPerDesc + uLabelLen, asCswOpts2Description, ARRAY_SIZE(asCswOpts2Description), ui32RawFlags);
+       _Flags2Description(psDesc, ui32DescSize, asMisc2Description, ARRAY_SIZE(asMisc2Description), ui32RawFlags);
+}
+
+static void _GetFwOsFlagsDescription(IMG_CHAR *psDesc, IMG_UINT32 ui32DescSize, IMG_UINT32 ui32RawFlags)
+{
+       const IMG_CHAR szCswLabel[] = "Ctx switch:";
+       size_t uLabelLen = sizeof(szCswLabel) - 1;
+       const size_t uiBytesPerDesc = (ui32DescSize - uLabelLen) / 2U - 1U;
+
+       OSStringLCopy(psDesc, szCswLabel, ui32DescSize);
+
+       _Flags2Description(psDesc, uiBytesPerDesc + uLabelLen, asFwOsCfg2Description, ARRAY_SIZE(asFwOsCfg2Description), ui32RawFlags);
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function     _RGXDumpFWAssert
+
+ @Description
+
+ Dump FW assert strings when a thread asserts.
+
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Input psRGXFWIfTraceBufCtl - RGX FW trace buffer
+
+ @Return   void
+
+******************************************************************************/
+static void _RGXDumpFWAssert(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       const RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl)
+{
+       const IMG_CHAR *pszTraceAssertPath;
+       const IMG_CHAR *pszTraceAssertInfo;
+       IMG_INT32 ui32TraceAssertLine;
+       IMG_UINT32 i;
+
+       for (i = 0; i < RGXFW_THREAD_NUM; i++)
+       {
+               pszTraceAssertPath = psRGXFWIfTraceBufCtl->sTraceBuf[i].sAssertBuf.szPath;
+               pszTraceAssertInfo = psRGXFWIfTraceBufCtl->sTraceBuf[i].sAssertBuf.szInfo;
+               ui32TraceAssertLine = psRGXFWIfTraceBufCtl->sTraceBuf[i].sAssertBuf.ui32LineNum;
+
+               /* print non-null assert strings */
+               if (*pszTraceAssertInfo)
+               {
+                       PVR_DUMPDEBUG_LOG("FW-T%d Assert: %s (%s:%d)",
+                                         i, pszTraceAssertInfo, pszTraceAssertPath, ui32TraceAssertLine);
+               }
+       }
+}
+
+/*!
+*******************************************************************************
+
+ @Function     _RGXDumpFWFaults
+
+ @Description
+
+ Dump FW assert strings when a thread asserts.
+
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Input psFwSysData       - RGX FW shared system data
+
+ @Return   void
+
+******************************************************************************/
+static void _RGXDumpFWFaults(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                             void *pvDumpDebugFile,
+                             const RGXFWIF_SYSDATA *psFwSysData)
+{
+       if (psFwSysData->ui32FWFaults > 0)
+       {
+               IMG_UINT32      ui32StartFault = psFwSysData->ui32FWFaults - RGXFWIF_FWFAULTINFO_MAX;
+               IMG_UINT32      ui32EndFault   = psFwSysData->ui32FWFaults - 1;
+               IMG_UINT32  ui32Index;
+
+               if (psFwSysData->ui32FWFaults < RGXFWIF_FWFAULTINFO_MAX)
+               {
+                       ui32StartFault = 0;
+               }
+
+               for (ui32Index = ui32StartFault; ui32Index <= ui32EndFault; ui32Index++)
+               {
+                       const RGX_FWFAULTINFO *psFaultInfo = &psFwSysData->sFaultInfo[ui32Index % RGXFWIF_FWFAULTINFO_MAX];
+                       IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+
+                       /* Split OS timestamp in seconds and nanoseconds */
+                       ConvertOSTimestampToSAndNS(psFaultInfo->ui64OSTimer, &ui64Seconds, &ui64Nanoseconds);
+
+                       PVR_DUMPDEBUG_LOG("FW Fault %d: %s (%s:%d)",
+                                         ui32Index+1, psFaultInfo->sFaultBuf.szInfo,
+                                         psFaultInfo->sFaultBuf.szPath,
+                                         psFaultInfo->sFaultBuf.ui32LineNum);
+                       PVR_DUMPDEBUG_LOG("            Data = 0x%08x, CRTimer = 0x%012"IMG_UINT64_FMTSPECX", OSTimer = %" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC,
+                                         psFaultInfo->ui32Data,
+                                         psFaultInfo->ui64CRTimer,
+                                         ui64Seconds, ui64Nanoseconds);
+               }
+       }
+}
+
+static void _RGXDumpFWPoll(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       const RGXFWIF_SYSDATA *psFwSysData)
+{
+       IMG_UINT32 i;
+       for (i = 0; i < RGXFW_THREAD_NUM; i++)
+       {
+               if (psFwSysData->aui32CrPollAddr[i])
+               {
+                       PVR_DUMPDEBUG_LOG("T%u polling %s (reg:0x%08X mask:0x%08X)",
+                                         i,
+                                         ((psFwSysData->aui32CrPollAddr[i] & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+                                         psFwSysData->aui32CrPollAddr[i] & ~RGXFW_POLL_TYPE_SET,
+                                         psFwSysData->aui32CrPollMask[i]);
+               }
+       }
+
+}
+
+static void _RGXDumpFWHWRInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                                         void *pvDumpDebugFile,
+                                                         const RGXFWIF_SYSDATA *psFwSysData,
+                                                         const RGXFWIF_HWRINFOBUF *psHWRInfoBuf,
+                                                         PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_BOOL          bAnyLocked = IMG_FALSE;
+       IMG_UINT32        dm, i;
+       IMG_UINT32        ui32LineSize;
+       IMG_CHAR          *pszLine, *pszTemp;
+       const IMG_CHAR    *apszDmNames[RGXFWIF_DM_MAX] = {"GP", "TDM", "GEOM", "3D", "CDM", "RAY", "GEOM2", "GEOM3", "GEOM4"};
+       const IMG_CHAR    szMsgHeader[] = "Number of HWR: ";
+       const IMG_CHAR    szMsgFalse[] = "FALSE(";
+       IMG_CHAR          *pszLockupType = "";
+       const IMG_UINT32  ui32MsgHeaderCharCount = ARRAY_SIZE(szMsgHeader) - 1; /* size includes the null */
+       const IMG_UINT32  ui32MsgFalseCharCount = ARRAY_SIZE(szMsgFalse) - 1;
+       IMG_UINT32        ui32HWRRecoveryFlags;
+       IMG_UINT32        ui32ReadIndex;
+
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+       {
+               if (psHWRInfoBuf->aui32HwrDmLockedUpCount[dm] ||
+                   psHWRInfoBuf->aui32HwrDmOverranCount[dm])
+               {
+                       bAnyLocked = IMG_TRUE;
+                       break;
+               }
+       }
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST) && !bAnyLocked && (psFwSysData->ui32HWRStateFlags & RGXFWIF_HWR_HARDWARE_OK))
+       {
+               /* No HWR situation, print nothing */
+               return;
+       }
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               IMG_BOOL bAnyHWROccured = IMG_FALSE;
+
+               for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+               {
+                       if (psHWRInfoBuf->aui32HwrDmRecoveredCount[dm] != 0 ||
+                               psHWRInfoBuf->aui32HwrDmLockedUpCount[dm] != 0 ||
+                               psHWRInfoBuf->aui32HwrDmOverranCount[dm] !=0)
+                               {
+                                       bAnyHWROccured = IMG_TRUE;
+                                       break;
+                               }
+               }
+
+               if (!bAnyHWROccured)
+               {
+                       return;
+               }
+       }
+
+       ui32LineSize = sizeof(IMG_CHAR) * (
+                       ui32MsgHeaderCharCount +
+                       (psDevInfo->sDevFeatureCfg.ui32MAXDMCount*(     4/*DM name + left parenthesis*/ +
+                               10/*UINT32 max num of digits*/ +
+                               1/*slash*/ +
+                               10/*UINT32 max num of digits*/ +
+                               3/*right parenthesis + comma + space*/)) +
+                       ui32MsgFalseCharCount + 1 + (psDevInfo->sDevFeatureCfg.ui32MAXDMCount*6) + 1
+                               /* 'FALSE(' + ')' + (UINT16 max num + comma) per DM + \0 */
+                       );
+
+       pszLine = OSAllocMem(ui32LineSize);
+       if (pszLine == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: Out of mem allocating line string (size: %d)",
+                       __func__,
+                       ui32LineSize));
+               return;
+       }
+
+       OSStringLCopy(pszLine, szMsgHeader, ui32LineSize);
+       pszTemp = pszLine + ui32MsgHeaderCharCount;
+
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+       {
+               pszTemp += OSSNPrintf(pszTemp,
+                               4 + 10 + 1 + 10 + 1 + 10 + 1 + 1 + 1 + 1
+                               /* (name + left parenthesis) + UINT32 + slash + UINT32 + plus + UINT32 + right parenthesis + comma + space + \0 */,
+                               "%s(%u/%u+%u), ",
+                               apszDmNames[dm],
+                               psHWRInfoBuf->aui32HwrDmRecoveredCount[dm],
+                               psHWRInfoBuf->aui32HwrDmLockedUpCount[dm],
+                               psHWRInfoBuf->aui32HwrDmOverranCount[dm]);
+       }
+
+       OSStringLCat(pszLine, szMsgFalse, ui32LineSize);
+       pszTemp += ui32MsgFalseCharCount;
+
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+       {
+               pszTemp += OSSNPrintf(pszTemp,
+                               10 + 1 + 1 /* UINT32 max num + comma + \0 */,
+                               (dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount-1 ? "%u," : "%u)"),
+                               psHWRInfoBuf->aui32HwrDmFalseDetectCount[dm]);
+       }
+
+       PVR_DUMPDEBUG_LOG("%s", pszLine);
+
+       OSFreeMem(pszLine);
+
+       /* Print out per HWR info */
+       for (dm = 0; dm < psDevInfo->sDevFeatureCfg.ui32MAXDMCount; dm++)
+       {
+               if (dm == RGXFWIF_DM_GP)
+               {
+                       PVR_DUMPDEBUG_LOG("DM %d (GP)", dm);
+               }
+               else
+               {
+                       if (!PVRSRV_VZ_MODE_IS(GUEST))
+                       {
+                               IMG_UINT32 ui32HWRRecoveryFlags = psFwSysData->aui32HWRRecoveryFlags[dm];
+                               IMG_CHAR sPerDmHwrDescription[RGX_DEBUG_STR_SIZE];
+                               sPerDmHwrDescription[0] = '\0';
+
+                               if (ui32HWRRecoveryFlags == RGXFWIF_DM_STATE_WORKING)
+                               {
+                                       OSStringLCopy(sPerDmHwrDescription, " working;", RGX_DEBUG_STR_SIZE);
+                               }
+                               else
+                               {
+                                       _Flags2Description(sPerDmHwrDescription, RGX_DEBUG_STR_SIZE,
+                                               asDmState2Description, ARRAY_SIZE(asDmState2Description),
+                                               ui32HWRRecoveryFlags);
+                               }
+                               PVR_DUMPDEBUG_LOG("DM %d (HWRflags 0x%08x:%s)", dm, ui32HWRRecoveryFlags, sPerDmHwrDescription);
+                       }
+                       else
+                       {
+                               PVR_DUMPDEBUG_LOG("DM %d", dm);
+                       }
+               }
+
+               ui32ReadIndex = 0;
+               for (i = 0 ; i < RGXFWIF_HWINFO_MAX ; i++)
+               {
+                       IMG_BOOL bPMFault = IMG_FALSE;
+                       IMG_UINT32 ui32PC;
+                       IMG_UINT32 ui32PageSize = 0;
+                       IMG_DEV_PHYADDR sPCDevPAddr = { 0 };
+                       const RGX_HWRINFO *psHWRInfo = &psHWRInfoBuf->sHWRInfo[ui32ReadIndex];
+
+                       if ((psHWRInfo->eDM == dm) && (psHWRInfo->ui32HWRNumber != 0))
+                       {
+                               IMG_CHAR aui8RecoveryNum[10+10+1];
+                               IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+                               IMG_BOOL bPageFault = IMG_FALSE;
+                               IMG_DEV_VIRTADDR sFaultDevVAddr;
+
+                               /* Split OS timestamp in seconds and nanoseconds */
+                               ConvertOSTimestampToSAndNS(psHWRInfo->ui64OSTimer, &ui64Seconds, &ui64Nanoseconds);
+
+                               ui32HWRRecoveryFlags = psHWRInfo->ui32HWRRecoveryFlags;
+                               if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GUILTY_LOCKUP) { pszLockupType = ", Guilty Lockup"; }
+                               else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_INNOCENT_LOCKUP) { pszLockupType = ", Innocent Lockup"; }
+                               else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GUILTY_OVERRUNING) { pszLockupType = ", Guilty Overrun"; }
+                               else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_INNOCENT_OVERRUNING) { pszLockupType = ", Innocent Overrun"; }
+                               else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_HARD_CONTEXT_SWITCH) { pszLockupType = ", Hard Context Switch"; }
+                               else if (ui32HWRRecoveryFlags & RGXFWIF_DM_STATE_GPU_ECC_HWR) { pszLockupType = ", GPU ECC HWR"; }
+
+                               OSSNPrintf(aui8RecoveryNum, sizeof(aui8RecoveryNum), "Recovery %d:", psHWRInfo->ui32HWRNumber);
+                               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_MULTICORE_SUPPORT))
+                               {
+                                       PVR_DUMPDEBUG_LOG("  %s Core = %u, PID = %u, frame = %d, HWRTData = 0x%08X, EventStatus = 0x%08X%s",
+                                                  aui8RecoveryNum,
+                                                  psHWRInfo->ui32CoreID,
+                                                  psHWRInfo->ui32PID,
+                                                  psHWRInfo->ui32FrameNum,
+                                                  psHWRInfo->ui32ActiveHWRTData,
+                                                  psHWRInfo->ui32EventStatus,
+                                                  pszLockupType);
+                               }
+                               else
+                               {
+                                       PVR_DUMPDEBUG_LOG("  %s PID = %u, frame = %d, HWRTData = 0x%08X, EventStatus = 0x%08X%s",
+                                                  aui8RecoveryNum,
+                                                  psHWRInfo->ui32PID,
+                                                  psHWRInfo->ui32FrameNum,
+                                                  psHWRInfo->ui32ActiveHWRTData,
+                                                  psHWRInfo->ui32EventStatus,
+                                                  pszLockupType);
+                               }
+
+                               if (psHWRInfo->eHWErrorCode != RGX_HW_ERR_NA)
+                               {
+                                       IMG_CHAR sHWDebugInfo[RGX_DEBUG_STR_SIZE] = "";
+
+                                       _ID2Description(sHWDebugInfo, RGX_DEBUG_STR_SIZE, asHWErrorState, ARRAY_SIZE(asHWErrorState),
+                                               psHWRInfo->eHWErrorCode);
+                                       PVR_DUMPDEBUG_LOG("  HW error code = 0x%X: %s",
+                                                                         psHWRInfo->eHWErrorCode, sHWDebugInfo);
+                               }
+
+                               pszTemp = &aui8RecoveryNum[0];
+                               while (*pszTemp != '\0')
+                               {
+                                       *pszTemp++ = ' ';
+                               }
+
+                               /* There's currently no time correlation for the Guest OSes on the Firmware so there's no point printing OS Timestamps on Guests */
+                               if (!PVRSRV_VZ_MODE_IS(GUEST))
+                               {
+                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECX", OSTimer = %" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC ", CyclesElapsed = %" IMG_INT64_FMTSPECd,
+                                                                          aui8RecoveryNum,
+                                                                          psHWRInfo->ui64CRTimer,
+                                                                          ui64Seconds,
+                                                                          ui64Nanoseconds,
+                                                                          (psHWRInfo->ui64CRTimer-psHWRInfo->ui64CRTimeOfKick)*256);
+                               }
+                               else
+                               {
+                                       PVR_DUMPDEBUG_LOG("  %s CRTimer = 0x%012"IMG_UINT64_FMTSPECX", CyclesElapsed = %" IMG_INT64_FMTSPECd,
+                                                                          aui8RecoveryNum,
+                                                                          psHWRInfo->ui64CRTimer,
+                                                                          (psHWRInfo->ui64CRTimer-psHWRInfo->ui64CRTimeOfKick)*256);
+                               }
+
+                               if (psHWRInfo->ui64CRTimeHWResetFinish != 0)
+                               {
+                                       if (psHWRInfo->ui64CRTimeFreelistReady != 0)
+                                       {
+                                               /* If ui64CRTimeFreelistReady is less than ui64CRTimeHWResetFinish it means APM kicked in and the time is not valid. */
+                                               if (psHWRInfo->ui64CRTimeHWResetFinish < psHWRInfo->ui64CRTimeFreelistReady)
+                                               {
+                                                       PVR_DUMPDEBUG_LOG("  %s PreResetTimeInCycles = %" IMG_INT64_FMTSPECd ", HWResetTimeInCycles = %" IMG_INT64_FMTSPECd ", FreelistReconTimeInCycles = %" IMG_INT64_FMTSPECd ", TotalRecoveryTimeInCycles = %" IMG_INT64_FMTSPECd,
+                                                                                          aui8RecoveryNum,
+                                                                                          (psHWRInfo->ui64CRTimeHWResetStart-psHWRInfo->ui64CRTimer)*256,
+                                                                                          (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimeHWResetStart)*256,
+                                                                                          (psHWRInfo->ui64CRTimeFreelistReady-psHWRInfo->ui64CRTimeHWResetFinish)*256,
+                                                                                          (psHWRInfo->ui64CRTimeFreelistReady-psHWRInfo->ui64CRTimer)*256);
+                                               }
+                                               else
+                                               {
+                                                       PVR_DUMPDEBUG_LOG("  %s PreResetTimeInCycles = %" IMG_INT64_FMTSPECd ", HWResetTimeInCycles = %" IMG_INT64_FMTSPECd ", FreelistReconTimeInCycles = <not_timed>, TotalResetTimeInCycles = %" IMG_INT64_FMTSPECd,
+                                                                                          aui8RecoveryNum,
+                                                                                          (psHWRInfo->ui64CRTimeHWResetStart-psHWRInfo->ui64CRTimer)*256,
+                                                                                          (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimeHWResetStart)*256,
+                                                                                          (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimer)*256);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               PVR_DUMPDEBUG_LOG("  %s PreResetTimeInCycles = %" IMG_INT64_FMTSPECd ", HWResetTimeInCycles = %" IMG_INT64_FMTSPECd ", TotalResetTimeInCycles = %" IMG_INT64_FMTSPECd,
+                                                                                  aui8RecoveryNum,
+                                                                                  (psHWRInfo->ui64CRTimeHWResetStart-psHWRInfo->ui64CRTimer)*256,
+                                                                                  (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimeHWResetStart)*256,
+                                                                                  (psHWRInfo->ui64CRTimeHWResetFinish-psHWRInfo->ui64CRTimer)*256);
+                                       }
+                               }
+
+                               switch (psHWRInfo->eHWRType)
+                               {
+                                       case RGX_HWRTYPE_ECCFAULT:
+                                       {
+                                               PVR_DUMPDEBUG_LOG("    ECC fault GPU=0x%08x", psHWRInfo->uHWRData.sECCInfo.ui32FaultGPU);
+                                       }
+                                       break;
+
+                                       case RGX_HWRTYPE_MMUFAULT:
+                                       {
+                                               _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
+                                                                               &psHWRInfo->uHWRData.sMMUInfo.aui64MMUStatus[0],
+                                                                               "Core",
+                                                                               DD_NORMAL_INDENT);
+
+                                               bPageFault = IMG_TRUE;
+                                               sFaultDevVAddr.uiAddr =   psHWRInfo->uHWRData.sMMUInfo.aui64MMUStatus[0];
+                                               sFaultDevVAddr.uiAddr &=  ~RGX_CR_MMU_FAULT_STATUS1_ADDRESS_CLRMSK;
+                                               sFaultDevVAddr.uiAddr >>= RGX_CR_MMU_FAULT_STATUS1_ADDRESS_SHIFT;
+                                               sFaultDevVAddr.uiAddr <<= 4; /* align shift */
+                                               ui32PC  = (psHWRInfo->uHWRData.sMMUInfo.aui64MMUStatus[0] & ~RGX_CR_MMU_FAULT_STATUS1_CONTEXT_CLRMSK) >>
+                                                                                                  RGX_CR_MMU_FAULT_STATUS1_CONTEXT_SHIFT;
+#if defined(SUPPORT_TRUSTED_DEVICE)
+                                               ui32PC = ui32PC - 1;
+#endif
+                                               bPMFault = (ui32PC <= 8);
+                                               sPCDevPAddr.uiAddr = psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress;
+
+                                       }
+                                       break;
+
+                                       case RGX_HWRTYPE_MMUMETAFAULT:
+                                       {
+                                               const IMG_PCHAR pszMetaOrRiscv = RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ? "Meta" : "RiscV";
+
+                                               _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo,
+                                                                                       &psHWRInfo->uHWRData.sMMUInfo.aui64MMUStatus[0],
+                                                                                       pszMetaOrRiscv,
+                                                                                       DD_NORMAL_INDENT);
+
+                                               bPageFault = IMG_TRUE;
+                                               sFaultDevVAddr.uiAddr =   psHWRInfo->uHWRData.sMMUInfo.aui64MMUStatus[0];
+                                               sFaultDevVAddr.uiAddr &=  ~RGX_CR_MMU_FAULT_STATUS1_ADDRESS_CLRMSK;
+                                               sFaultDevVAddr.uiAddr >>= RGX_CR_MMU_FAULT_STATUS1_ADDRESS_SHIFT;
+                                               sFaultDevVAddr.uiAddr <<= 4; /* align shift */
+                                               sPCDevPAddr.uiAddr = psHWRInfo->uHWRData.sMMUInfo.ui64PCAddress;
+                                       }
+                                       break;
+
+                                       case RGX_HWRTYPE_POLLFAILURE:
+                                       {
+                                               PVR_DUMPDEBUG_LOG("    T%u polling %s (reg:0x%08X mask:0x%08X last:0x%08X)",
+                                                                                 psHWRInfo->uHWRData.sPollInfo.ui32ThreadNum,
+                                                                                 ((psHWRInfo->uHWRData.sPollInfo.ui32CrPollAddr & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+                                                                                 psHWRInfo->uHWRData.sPollInfo.ui32CrPollAddr & ~RGXFW_POLL_TYPE_SET,
+                                                                                 psHWRInfo->uHWRData.sPollInfo.ui32CrPollMask,
+                                                                                 psHWRInfo->uHWRData.sPollInfo.ui32CrPollLastValue);
+                                       }
+                                       break;
+
+                                       case RGX_HWRTYPE_OVERRUN:
+                                       case RGX_HWRTYPE_UNKNOWNFAILURE:
+                                       {
+                                               /* Nothing to dump */
+                                       }
+                                       break;
+
+                                       default:
+                                       {
+                                               PVR_DUMPDEBUG_LOG("    Unknown HWR Info type: 0x%x", psHWRInfo->eHWRType);
+                                       }
+                                       break;
+                               }
+
+                               if (bPageFault)
+                               {
+
+                                       FAULT_INFO *psInfo;
+
+                                       OSLockAcquire(psDevInfo->hDebugFaultInfoLock);
+
+                                       /* Find the matching Fault Info for this HWRInfo */
+                                       psInfo = &gsFaultInfoLog.asFaults[ui32ReadIndex];
+
+                                       /* if they do not match, we need to update the psInfo */
+                                       if ((psInfo->ui64CRTimer != psHWRInfo->ui64CRTimer) ||
+                                               (psInfo->sFaultDevVAddr.uiAddr != sFaultDevVAddr.uiAddr))
+                                       {
+                                               MMU_FAULT_DATA *psFaultData = &psInfo->sMMUFaultData;
+
+                                               psFaultData->eType = MMU_FAULT_TYPE_UNKNOWN;
+
+                                               if (bPMFault)
+                                               {
+                                                       /* PM fault and we dump PC details only */
+                                                       psFaultData->eTopLevel = MMU_LEVEL_0;
+                                                       psFaultData->eType     = MMU_FAULT_TYPE_PM;
+                                                       psFaultData->sLevelData[MMU_LEVEL_0].ui64Address = sPCDevPAddr.uiAddr;
+                                               }
+                                               else
+                                               {
+                                                       RGXCheckFaultAddress(psDevInfo, &sFaultDevVAddr, &sPCDevPAddr, psFaultData);
+                                               }
+
+                                               _RecordFaultInfo(psDevInfo, psInfo,
+                                                                       sFaultDevVAddr, sPCDevPAddr, psHWRInfo->ui64CRTimer,
+                                                                       _PageSizeHWToBytes(ui32PageSize));
+
+                                       }
+
+                                       _DumpFaultAddressHostView(&psInfo->sMMUFaultData, pfnDumpDebugPrintf, pvDumpDebugFile, DD_NORMAL_INDENT);
+
+                                       if (GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED)
+                                       {
+                                               _PrintFaultInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psInfo, DD_NORMAL_INDENT);
+                                       }
+
+                                       OSLockRelease(psDevInfo->hDebugFaultInfoLock);
+                               }
+
+                       }
+
+                       if (ui32ReadIndex == RGXFWIF_HWINFO_MAX_FIRST - 1)
+                               ui32ReadIndex = psHWRInfoBuf->ui32WriteIndex;
+                       else
+                               ui32ReadIndex = (ui32ReadIndex + 1) - (ui32ReadIndex / RGXFWIF_HWINFO_LAST_INDEX) * RGXFWIF_HWINFO_MAX_LAST;
+               }
+       }
+}
+
+#if !defined(NO_HARDWARE)
+
+/*!
+*******************************************************************************
+
+ @Function     _CheckForPendingPage
+
+ @Description
+
+ Check if the MMU indicates it is blocked on a pending page
+ MMU4 does not support pending pages, so return false.
+
+ @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)
+{
+       /* MMU4 doesn't support pending pages */
+       return (RGX_GET_FEATURE_VALUE(psDevInfo, MMU_VERSION) < 4) &&
+                  (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_ENTRY) & RGX_CR_MMU_ENTRY_PENDING_EN);
+}
+
+/*!
+*******************************************************************************
+
+ @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
+
+ @Return   void
+
+******************************************************************************/
+static void _GetPendingPageInfo(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_DEV_VIRTADDR *psDevVAddr,
+                                                               IMG_UINT32 *pui32CatBase)
+{
+       IMG_UINT64 ui64BIFMMUEntryStatus;
+
+       ui64BIFMMUEntryStatus = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_ENTRY_STATUS);
+
+       psDevVAddr->uiAddr = (ui64BIFMMUEntryStatus & ~RGX_CR_MMU_ENTRY_STATUS_ADDRESS_CLRMSK);
+
+       *pui32CatBase = (ui64BIFMMUEntryStatus & ~RGX_CR_MMU_ENTRY_STATUS_CONTEXT_ID_CLRMSK) >>
+                                                               RGX_CR_MMU_ENTRY_STATUS_CONTEXT_ID_SHIFT;
+}
+
+#endif
+
+void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       PVRSRV_RGXDEV_INFO *psDevInfo,
+                                       IMG_BOOL bRGXPoweredON)
+{
+       IMG_CHAR *pszState, *pszReason;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       const RGXFWIF_TRACEBUF *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       IMG_UINT32 ui32OSid;
+       const RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+       /* space for the current clock speed and 3 previous */
+       RGXFWIF_TIME_CORR asTimeCorrs[4];
+       IMG_UINT32 ui32NumClockSpeedChanges;
+
+#if defined(NO_HARDWARE)
+       PVR_UNREFERENCED_PARAMETER(bRGXPoweredON);
+#else
+       if ((bRGXPoweredON) && !PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               IMG_UINT64      aui64RegValMMUStatus[2];
+               const IMG_PCHAR pszMetaOrRiscv = RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ? "Meta" : "RiscV";
+
+               aui64RegValMMUStatus[0] = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS1);
+               aui64RegValMMUStatus[1] = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS2);
+               _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, &aui64RegValMMUStatus[0], "Core", DD_SUMMARY_INDENT);
+
+               aui64RegValMMUStatus[0] = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_FAULT_STATUS_META);
+               _RGXDumpRGXMMUFaultStatus(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, &aui64RegValMMUStatus[0], pszMetaOrRiscv, DD_SUMMARY_INDENT);
+
+               if (_CheckForPendingPage(psDevInfo))
+               {
+                       IMG_UINT32 ui32CatBase;
+                       IMG_DEV_VIRTADDR sDevVAddr;
+
+                       PVR_DUMPDEBUG_LOG("MMU Pending page: Yes");
+
+                       _GetPendingPageInfo(psDevInfo, &sDevVAddr, &ui32CatBase);
+
+                       if (ui32CatBase <= MAX_RESERVED_FW_MMU_CONTEXT)
+                       {
+                               PVR_DUMPDEBUG_LOG("Cannot check address on PM cat base %u", ui32CatBase);
+                       }
+                       else
+                       {
+                               IMG_UINT64 ui64CBaseMapping;
+                               IMG_DEV_PHYADDR sPCDevPAddr;
+                               MMU_FAULT_DATA sFaultData;
+                               IMG_BOOL bIsValid;
+
+                               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, ui32CatBase);
+
+                               ui64CBaseMapping = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_MMU_CBASE_MAPPING);
+                               sPCDevPAddr.uiAddr = (((ui64CBaseMapping & ~RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_CLRMSK)
+                                                                                       >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
+                                                                                       << RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT);
+                               bIsValid = !(ui64CBaseMapping & RGX_CR_MMU_CBASE_MAPPING_INVALID_EN);
+
+                               PVR_DUMPDEBUG_LOG("Checking device virtual address " IMG_DEV_VIRTADDR_FMTSPEC
+                                                       " on cat base %u. PC Addr = 0x%llX is %s",
+                                                               (unsigned long long) sDevVAddr.uiAddr,
+                                                               ui32CatBase,
+                                                               (unsigned long long) sPCDevPAddr.uiAddr,
+                                                               bIsValid ? "valid":"invalid");
+                               RGXCheckFaultAddress(psDevInfo, &sDevVAddr, &sPCDevPAddr, &sFaultData);
+                               _DumpFaultAddressHostView(&sFaultData, pfnDumpDebugPrintf, pvDumpDebugFile, DD_SUMMARY_INDENT);
+                       }
+               }
+       }
+#endif /* NO_HARDWARE */
+
+       /* Firmware state */
+       switch (OSAtomicRead(&psDevInfo->psDeviceNode->eHealthStatus))
+       {
+               case PVRSRV_DEVICE_HEALTH_STATUS_OK:  pszState = "OK";  break;
+               case PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING:  pszState = "NOT RESPONDING";  break;
+               case PVRSRV_DEVICE_HEALTH_STATUS_DEAD:  pszState = "DEAD";  break;
+               case PVRSRV_DEVICE_HEALTH_STATUS_FAULT:  pszState = "FAULT";  break;
+               case PVRSRV_DEVICE_HEALTH_STATUS_UNDEFINED:  pszState = "UNDEFINED";  break;
+               default:  pszState = "UNKNOWN";  break;
+       }
+
+       switch (OSAtomicRead(&psDevInfo->psDeviceNode->eHealthReason))
+       {
+               case PVRSRV_DEVICE_HEALTH_REASON_NONE:  pszReason = "";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_ASSERTED:  pszReason = " - Asserted";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING:  pszReason = " - Poll failing";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS:  pszReason = " - Global Event Object timeouts rising";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_CORRUPT:  pszReason = " - KCCB offset invalid";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED:  pszReason = " - KCCB stalled";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_IDLING:  pszReason = " - Idling";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_RESTARTING:  pszReason = " - Restarting";  break;
+               case PVRSRV_DEVICE_HEALTH_REASON_MISSING_INTERRUPTS:  pszReason = " - Missing interrupts";  break;
+               default:  pszReason = " - Unknown reason";  break;
+       }
+
+#if !defined(NO_HARDWARE)
+       /* Determine the type virtualisation support used */
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       if (!PVRSRV_VZ_MODE_IS(NATIVE))
+       {
+#if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS)
+#if defined(SUPPORT_AUTOVZ)
+#if defined(SUPPORT_AUTOVZ_HW_REGS)
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation type: AutoVz with HW register support");
+#else
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation type: AutoVz with shared memory");
+#endif /* defined(SUPPORT_AUTOVZ_HW_REGS) */
+#else
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation type: Hypervisor-assisted with static Fw heap allocation");
+#endif /* defined(SUPPORT_AUTOVZ) */
+#else
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation type: Hypervisor-assisted with dynamic Fw heap allocation");
+#endif /* defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) */
+       }
+#endif /* (RGX_NUM_OS_SUPPORTED > 1) */
+
+#if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) || (defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1))
+       if (!PVRSRV_VZ_MODE_IS(NATIVE))
+       {
+               RGXFWIF_CONNECTION_FW_STATE eFwState = KM_GET_FW_CONNECTION(psDevInfo);
+               RGXFWIF_CONNECTION_OS_STATE eOsState = KM_GET_OS_CONNECTION(psDevInfo);
+
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation firmware connection state: %s (Fw=%s; OS=%s)",
+                                                 ((eFwState == RGXFW_CONNECTION_FW_ACTIVE) && (eOsState == RGXFW_CONNECTION_OS_ACTIVE)) ? ("UP") : ("DOWN"),
+                                                 (eFwState < RGXFW_CONNECTION_FW_STATE_COUNT) ? (apszFwOsStateName[eFwState]) : ("invalid"),
+                                                 (eOsState < RGXFW_CONNECTION_OS_STATE_COUNT) ? (apszFwOsStateName[eOsState]) : ("invalid"));
+
+       }
+#endif
+
+#if defined(SUPPORT_AUTOVZ) && defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       if (!PVRSRV_VZ_MODE_IS(NATIVE))
+       {
+               IMG_UINT32 ui32FwAliveTS = KM_GET_FW_ALIVE_TOKEN(psDevInfo);
+               IMG_UINT32 ui32OsAliveTS = KM_GET_OS_ALIVE_TOKEN(psDevInfo);
+
+               PVR_DUMPDEBUG_LOG("RGX Virtualisation watchdog timestamps (in GPU timer ticks): Fw=%u; OS=%u; diff(FW, OS) = %u",
+                                                 ui32FwAliveTS, ui32OsAliveTS, ui32FwAliveTS - ui32OsAliveTS);
+       }
+#endif
+#endif /* !defined(NO_HARDWARE) */
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               IMG_CHAR sHwrStateDescription[RGX_DEBUG_STR_SIZE];
+               IMG_BOOL bOsIsolationEnabled = IMG_FALSE;
+
+               if (psFwSysData == NULL)
+               {
+                       /* can't dump any more information */
+                       PVR_DUMPDEBUG_LOG("RGX FW State: %s%s", pszState, pszReason);
+                       return;
+               }
+
+               sHwrStateDescription[0] = '\0';
+
+               _Flags2Description(sHwrStateDescription, RGX_DEBUG_STR_SIZE,
+                       asHwrState2Description, ARRAY_SIZE(asHwrState2Description),
+                       psFwSysData->ui32HWRStateFlags);
+               PVR_DUMPDEBUG_LOG("RGX FW State: %s%s (HWRState 0x%08x:%s)", pszState, pszReason, psFwSysData->ui32HWRStateFlags, sHwrStateDescription);
+               PVR_DUMPDEBUG_LOG("RGX FW Power State: %s (APM %s: %d ok, %d denied, %d non-idle, %d retry, %d other, %d total. Latency: %u ms)",
+                         pszPowStateName[psFwSysData->ePowState],
+                         (psDevInfo->pvAPMISRData)?"enabled":"disabled",
+                         psDevInfo->ui32ActivePMReqOk - psDevInfo->ui32ActivePMReqNonIdle,
+                         psDevInfo->ui32ActivePMReqDenied,
+                         psDevInfo->ui32ActivePMReqNonIdle,
+                         psDevInfo->ui32ActivePMReqRetry,
+                         psDevInfo->ui32ActivePMReqTotal -
+                                                 psDevInfo->ui32ActivePMReqOk -
+                                                 psDevInfo->ui32ActivePMReqDenied -
+                                                 psDevInfo->ui32ActivePMReqRetry -
+                                                 psDevInfo->ui32ActivePMReqNonIdle,
+                         psDevInfo->ui32ActivePMReqTotal,
+                         psRuntimeCfg->ui32ActivePMLatencyms);
+
+               ui32NumClockSpeedChanges = (IMG_UINT32) OSAtomicRead(&psDevInfo->psDeviceNode->iNumClockSpeedChanges);
+               RGXGetTimeCorrData(psDevInfo->psDeviceNode, asTimeCorrs, ARRAY_SIZE(asTimeCorrs));
+
+               PVR_DUMPDEBUG_LOG("RGX DVFS: %u frequency changes. "
+                                 "Current frequency: %u.%03u MHz (sampled at %" IMG_UINT64_FMTSPEC " ns). "
+                                 "FW frequency: %u.%03u MHz.",
+                                 ui32NumClockSpeedChanges,
+                                 asTimeCorrs[0].ui32CoreClockSpeed / 1000000,
+                                 (asTimeCorrs[0].ui32CoreClockSpeed / 1000) % 1000,
+                                 asTimeCorrs[0].ui64OSTimeStamp,
+                                 psRuntimeCfg->ui32CoreClockSpeed / 1000000,
+                                 (psRuntimeCfg->ui32CoreClockSpeed / 1000) % 1000);
+               if (ui32NumClockSpeedChanges > 0)
+               {
+                       PVR_DUMPDEBUG_LOG("          Previous frequencies: %u.%03u, %u.%03u, %u.%03u MHz (Sampled at "
+                                                       "%" IMG_UINT64_FMTSPEC ", %" IMG_UINT64_FMTSPEC ", %" IMG_UINT64_FMTSPEC ")",
+                                                                                               asTimeCorrs[1].ui32CoreClockSpeed / 1000000,
+                                                                                               (asTimeCorrs[1].ui32CoreClockSpeed / 1000) % 1000,
+                                                                                               asTimeCorrs[2].ui32CoreClockSpeed / 1000000,
+                                                                                               (asTimeCorrs[2].ui32CoreClockSpeed / 1000) % 1000,
+                                                                                               asTimeCorrs[3].ui32CoreClockSpeed / 1000000,
+                                                                                               (asTimeCorrs[3].ui32CoreClockSpeed / 1000) % 1000,
+                                                                                               asTimeCorrs[1].ui64OSTimeStamp,
+                                                                                               asTimeCorrs[2].ui64OSTimeStamp,
+                                                                                               asTimeCorrs[3].ui64OSTimeStamp);
+               }
+
+               for (ui32OSid = 0; ui32OSid < RGX_NUM_OS_SUPPORTED; ui32OSid++)
+               {
+                       RGXFWIF_OS_RUNTIME_FLAGS sFwRunFlags = psFwSysData->asOsRuntimeFlagsMirror[ui32OSid];
+
+                       IMG_BOOL bMTSEnabled = (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_VIRTUALISATION)) ?
+                                                                       IMG_TRUE : ((OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_SCHEDULE_ENABLE) & BIT(ui32OSid)) != 0);
+
+                       PVR_DUMPDEBUG_LOG("RGX FW OS %u - State: %s; Freelists: %s%s; Priority: %d;%s %s", ui32OSid,
+                                                         apszFwOsStateName[sFwRunFlags.bfOsState],
+                                                         (sFwRunFlags.bfFLOk) ? "Ok" : "Not Ok",
+                                                         (sFwRunFlags.bfFLGrowPending) ? "; Grow Request Pending" : "",
+                                                         psDevInfo->psRGXFWIfRuntimeCfg->aui32OSidPriority[ui32OSid],
+                                                         (sFwRunFlags.bfIsolatedOS) ? " Isolated;" : "",
+                                                         (bMTSEnabled) ? "MTS on;" : "MTS off;"
+                                                        );
+
+                       bOsIsolationEnabled |= sFwRunFlags.bfIsolatedOS;
+               }
+
+#if defined(PVR_ENABLE_PHR)
+               {
+                       IMG_CHAR sPHRConfigDescription[RGX_DEBUG_STR_SIZE];
+
+                       sPHRConfigDescription[0] = '\0';
+                       _Flags2Description(sPHRConfigDescription, RGX_DEBUG_STR_SIZE,
+                                          asPHRConfig2Description, ARRAY_SIZE(asPHRConfig2Description),
+                                          BIT_ULL(psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode));
+
+                       PVR_DUMPDEBUG_LOG("RGX PHR configuration: (%d) %s", psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode, sPHRConfigDescription);
+               }
+#endif
+
+               if (bOsIsolationEnabled)
+               {
+                       PVR_DUMPDEBUG_LOG("RGX Hard Context Switch deadline: %u ms", psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS);
+               }
+
+               _RGXDumpFWAssert(pfnDumpDebugPrintf, pvDumpDebugFile, psRGXFWIfTraceBufCtl);
+               _RGXDumpFWFaults(pfnDumpDebugPrintf, pvDumpDebugFile, psFwSysData);
+               _RGXDumpFWPoll(pfnDumpDebugPrintf, pvDumpDebugFile, psFwSysData);
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("RGX FW State: Unavailable under Guest Mode of operation");
+               PVR_DUMPDEBUG_LOG("RGX FW Power State: Unavailable under Guest Mode of operation");
+       }
+
+       _RGXDumpFWHWRInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psFwSysData, psDevInfo->psRGXFWIfHWRInfoBufCtl, psDevInfo);
+
+#if defined(SUPPORT_RGXFW_STATS_FRAMEWORK)
+       /* Dump all non-zero values in lines of 8... */
+       {
+               IMG_CHAR    pszLine[(9*RGXFWIF_STATS_FRAMEWORK_LINESIZE)+1];
+               const IMG_UINT32 *pui32FWStatsBuf = psFwSysData->aui32FWStatsBuf;
+               IMG_UINT32  ui32Index1, ui32Index2;
+
+               PVR_DUMPDEBUG_LOG("STATS[START]: RGXFWIF_STATS_FRAMEWORK_MAX=%d", RGXFWIF_STATS_FRAMEWORK_MAX);
+               for (ui32Index1 = 0;  ui32Index1 < RGXFWIF_STATS_FRAMEWORK_MAX;  ui32Index1 += RGXFWIF_STATS_FRAMEWORK_LINESIZE)
+               {
+                       IMG_UINT32  ui32OrOfValues = 0;
+                       IMG_CHAR    *pszBuf = pszLine;
+
+                       /* Print all values in this line and skip if all zero... */
+                       for (ui32Index2 = 0;  ui32Index2 < RGXFWIF_STATS_FRAMEWORK_LINESIZE;  ui32Index2++)
+                       {
+                               ui32OrOfValues |= pui32FWStatsBuf[ui32Index1+ui32Index2];
+                               OSSNPrintf(pszBuf, 9 + 1, " %08x", pui32FWStatsBuf[ui32Index1+ui32Index2]);
+                               pszBuf += 9; /* write over the '\0' */
+                       }
+
+                       if (ui32OrOfValues != 0)
+                       {
+                               PVR_DUMPDEBUG_LOG("STATS[%08x]:%s", ui32Index1, pszLine);
+                       }
+               }
+               PVR_DUMPDEBUG_LOG("STATS[END]");
+       }
+#endif
+}
+
+#if !defined(NO_HARDWARE)
+static void _RGXDumpMetaSPExtraDebugInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile,
+                                               PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+/* List of extra META Slave Port debug registers */
+/* Order in these two initialisers must match */
+#define RGX_META_SP_EXTRA_DEBUG \
+                       X(RGX_CR_META_SP_MSLVCTRL0) \
+                       X(RGX_CR_META_SP_MSLVCTRL1) \
+                       X(RGX_CR_META_SP_MSLVDATAX) \
+                       X(RGX_CR_META_SP_MSLVIRQSTATUS) \
+                       X(RGX_CR_META_SP_MSLVIRQENABLE) \
+                       X(RGX_CR_META_SP_MSLVIRQLEVEL)
+
+#define RGX_META_SP_EXTRA_DEBUG__UNPACKED_ACCESSES \
+                       X(RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES) \
+                       X(RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES) \
+                       X(RGX_CR_META_SP_MSLVDATAX__META_REGISTER_UNPACKED_ACCESSES) \
+                       X(RGX_CR_META_SP_MSLVIRQSTATUS__META_REGISTER_UNPACKED_ACCESSES) \
+                       X(RGX_CR_META_SP_MSLVIRQENABLE__META_REGISTER_UNPACKED_ACCESSES) \
+                       X(RGX_CR_META_SP_MSLVIRQLEVEL__META_REGISTER_UNPACKED_ACCESSES)
+
+       IMG_UINT32 ui32Idx, ui32RegIdx;
+       IMG_UINT32 ui32RegVal;
+       IMG_UINT32 ui32RegAddr;
+
+       const IMG_UINT32* pui32DebugRegAddr;
+       const IMG_UINT32 aui32DebugRegAddr[] = {
+#define X(A) A,
+               RGX_META_SP_EXTRA_DEBUG
+#undef X
+               };
+       const IMG_UINT32 aui32DebugRegAddrUA[] = {
+#define X(A) A,
+               RGX_META_SP_EXTRA_DEBUG__UNPACKED_ACCESSES
+#undef X
+               };
+
+       const IMG_CHAR* apszDebugRegName[] = {
+#define X(A) #A,
+       RGX_META_SP_EXTRA_DEBUG
+#undef X
+       };
+
+       const IMG_UINT32 aui32Debug2RegAddr[] = {0xA28, 0x0A30, 0x0A38};
+
+       PVR_DUMPDEBUG_LOG("META Slave Port extra debug:");
+
+       /* array of register offset values depends on feature. But don't augment names in apszDebugRegName */
+       PVR_ASSERT(sizeof(aui32DebugRegAddrUA) == sizeof(aui32DebugRegAddr));
+       pui32DebugRegAddr = RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES) ?
+                                                       aui32DebugRegAddrUA : aui32DebugRegAddr;
+
+       /* dump first set of Slave Port debug registers */
+       for (ui32Idx = 0; ui32Idx < sizeof(aui32DebugRegAddr)/sizeof(IMG_UINT32); ui32Idx++)
+       {
+               const IMG_CHAR* pszRegName = apszDebugRegName[ui32Idx];
+
+               ui32RegAddr = pui32DebugRegAddr[ui32Idx];
+               ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32RegAddr);
+               PVR_DUMPDEBUG_LOG("  * %s: 0x%8.8X", pszRegName, ui32RegVal);
+       }
+
+       /* dump second set of Slave Port debug registers */
+       for (ui32Idx = 0; ui32Idx < 4; ui32Idx++)
+       {
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, 0xA20, ui32Idx);
+               ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM, 0xA20);
+               PVR_DUMPDEBUG_LOG("  * 0xA20[%d]: 0x%8.8X", ui32Idx, ui32RegVal);
+
+       }
+
+       for (ui32RegIdx = 0; ui32RegIdx < sizeof(aui32Debug2RegAddr)/sizeof(IMG_UINT32); ui32RegIdx++)
+       {
+               ui32RegAddr = aui32Debug2RegAddr[ui32RegIdx];
+               for (ui32Idx = 0; ui32Idx < 2; ui32Idx++)
+               {
+                       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32RegAddr, ui32Idx);
+                       ui32RegVal = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32RegAddr);
+                       PVR_DUMPDEBUG_LOG("  * 0x%X[%d]: 0x%8.8X", ui32RegAddr, ui32Idx, ui32RegVal);
+               }
+       }
+
+}
+#endif /* !defined(NO_HARDWARE) */
+
+/*
+ *  Array of all the Firmware Trace log IDs used to convert the trace data.
+ */
+typedef struct _TRACEBUF_LOG_ {
+       RGXFW_LOG_SFids eSFId;
+       const IMG_CHAR  *pszName;
+       const IMG_CHAR  *pszFmt;
+       IMG_UINT32              ui32ArgNum;
+} TRACEBUF_LOG;
+
+static const TRACEBUF_LOG aLogDefinitions[] =
+{
+#define X(a, b, c, d, e) {RGXFW_LOG_CREATESFID(a,b,e), #c, d, e},
+       RGXFW_LOG_SFIDLIST
+#undef X
+};
+
+#define NARGS_MASK ~(0xF<<16)
+static IMG_BOOL _FirmwareTraceIntegrityCheck(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                               void *pvDumpDebugFile)
+{
+       const TRACEBUF_LOG *psLogDef = &aLogDefinitions[0];
+       IMG_BOOL bIntegrityOk = IMG_TRUE;
+
+       /*
+        * For every log ID, check the format string and number of arguments is valid.
+        */
+       while (psLogDef->eSFId != RGXFW_SF_LAST)
+       {
+               const TRACEBUF_LOG *psLogDef2;
+               const IMG_CHAR *pszString;
+               IMG_UINT32 ui32Count;
+
+               /*
+                * Check the number of arguments matches the number of '%' in the string and
+                * check that no string uses %s which is not supported as it requires a
+                * pointer to memory that is not going to be valid.
+                */
+               pszString = psLogDef->pszFmt;
+               ui32Count = 0;
+
+               while (*pszString != '\0')
+               {
+                       if (*pszString++ == '%')
+                       {
+                               ui32Count++;
+                               if (*pszString == 's')
+                               {
+                                       bIntegrityOk = IMG_FALSE;
+                                       PVR_DUMPDEBUG_LOG("Integrity Check FAIL: %s has an unsupported type not recognized (fmt: %%%c). Please fix.",
+                                                                         psLogDef->pszName, *pszString);
+                               }
+                               else if (*pszString == '%')
+                               {
+                                       /* Double % is a printable % sign and not a format string... */
+                                       ui32Count--;
+                               }
+                       }
+               }
+
+               if (ui32Count != psLogDef->ui32ArgNum)
+               {
+                       bIntegrityOk = IMG_FALSE;
+                       PVR_DUMPDEBUG_LOG("Integrity Check FAIL: %s has %d arguments but only %d are specified. Please fix.",
+                                         psLogDef->pszName, ui32Count, psLogDef->ui32ArgNum);
+               }
+
+               /* RGXDumpFirmwareTrace() has a hardcoded limit of supporting up to 20 arguments... */
+               if (ui32Count > 20)
+               {
+                       bIntegrityOk = IMG_FALSE;
+                       PVR_DUMPDEBUG_LOG("Integrity Check FAIL: %s has %d arguments but a maximum of 20 are supported. Please fix.",
+                                         psLogDef->pszName, ui32Count);
+               }
+
+               /* Check the id number is unique (don't take into account the number of arguments) */
+               ui32Count = 0;
+               psLogDef2 = &aLogDefinitions[0];
+
+               while (psLogDef2->eSFId != RGXFW_SF_LAST)
+               {
+                       if ((psLogDef->eSFId & NARGS_MASK) == (psLogDef2->eSFId & NARGS_MASK))
+                       {
+                               ui32Count++;
+                       }
+                       psLogDef2++;
+               }
+
+               if (ui32Count != 1)
+               {
+                       bIntegrityOk = IMG_FALSE;
+                       PVR_DUMPDEBUG_LOG("Integrity Check FAIL: %s id %x is not unique, there are %d more. Please fix.",
+                                         psLogDef->pszName, psLogDef->eSFId, ui32Count - 1);
+               }
+
+               /* Move to the next log ID... */
+               psLogDef++;
+       }
+
+       return bIntegrityOk;
+}
+
+typedef struct {
+       IMG_UINT16     ui16Mask;
+       const IMG_CHAR *pszStr;
+} RGXFWT_DEBUG_INFO_MSKSTR; /* pair of bit mask and debug info message string */
+
+
+/*!
+*******************************************************************************
+
+ @Function     RGXPrepareExtraDebugInfo
+
+ @Description
+
+ Prepares debug info string by decoding ui16DebugInfo value passed
+
+ @Input pszBuffer       - pointer to debug info string buffer
+
+ @Return   void
+
+******************************************************************************/
+static void RGXPrepareExtraDebugInfo(IMG_CHAR *pszBuffer, IMG_UINT32 ui32BufferSize, IMG_UINT16 ui16DebugInfo)
+{
+       const RGXFWT_DEBUG_INFO_MSKSTR aDebugInfoMskStr[] =
+       {
+#define X(a, b) {a, b},
+               RGXFWT_DEBUG_INFO_MSKSTRLIST
+#undef X
+       };
+
+       IMG_UINT32 ui32NumFields = sizeof(aDebugInfoMskStr)/sizeof(RGXFWT_DEBUG_INFO_MSKSTR);
+       IMG_UINT32 i;
+       IMG_BOOL   bHasExtraDebugInfo = IMG_FALSE;
+
+       /* Add prepend string */
+       OSStringLCopy(pszBuffer, RGXFWT_DEBUG_INFO_STR_PREPEND, ui32BufferSize);
+
+       /* Add debug info strings */
+       for (i = 0; i < ui32NumFields; i++)
+       {
+               if (ui16DebugInfo & aDebugInfoMskStr[i].ui16Mask)
+               {
+                       if (bHasExtraDebugInfo)
+                       {
+                               OSStringLCat(pszBuffer, ", ", ui32BufferSize); /* Add comma separator */
+                       }
+                       OSStringLCat(pszBuffer, aDebugInfoMskStr[i].pszStr, ui32BufferSize);
+                       bHasExtraDebugInfo = IMG_TRUE;
+               }
+       }
+
+       /* Add append string */
+       OSStringLCat(pszBuffer, RGXFWT_DEBUG_INFO_STR_APPEND, ui32BufferSize);
+}
+
+void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                               void *pvDumpDebugFile,
+                               PVRSRV_RGXDEV_INFO  *psDevInfo)
+{
+       RGXFWIF_TRACEBUF  *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       static IMG_BOOL   bIntegrityCheckPassed = IMG_FALSE;
+
+       /* Check that the firmware trace is correctly defined... */
+       if (!bIntegrityCheckPassed)
+       {
+               bIntegrityCheckPassed = _FirmwareTraceIntegrityCheck(pfnDumpDebugPrintf, pvDumpDebugFile);
+               if (!bIntegrityCheckPassed)
+               {
+                       return;
+               }
+       }
+
+       /* Dump FW trace information... */
+       if (psRGXFWIfTraceBufCtl != NULL)
+       {
+               IMG_UINT32  tid;
+               IMG_UINT32  ui32TraceBufSizeInDWords = psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords;
+
+               /* Print the log type settings... */
+               if (psRGXFWIfTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_GROUP_MASK)
+               {
+                       PVR_DUMPDEBUG_LOG("Debug log type: %s ( " RGXFWIF_LOG_ENABLED_GROUPS_LIST_PFSPEC ")",
+                                                         ((psRGXFWIfTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_TRACE)?("trace"):("tbi")),
+                                                         RGXFWIF_LOG_ENABLED_GROUPS_LIST(psRGXFWIfTraceBufCtl->ui32LogType)
+                                                         );
+               }
+               else
+               {
+                       PVR_DUMPDEBUG_LOG("Debug log type: none");
+               }
+
+               /* Print the decoded log for each thread... */
+               for (tid = 0;  tid < RGXFW_THREAD_NUM;  tid++)
+               {
+                       volatile IMG_UINT32  *pui32FWWrapCount = &(psRGXFWIfTraceBufCtl->sTraceBuf[tid].sAssertBuf.ui32LineNum);
+                       volatile IMG_UINT32  *pui32FWTracePtr  = &(psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer);
+                       IMG_UINT32           *pui32TraceBuf    = psRGXFWIfTraceBufCtl->sTraceBuf[tid].pui32TraceBuffer;
+                       IMG_UINT32           ui32HostWrapCount = *pui32FWWrapCount;
+                       IMG_UINT32           ui32HostTracePtr  = *pui32FWTracePtr;
+                       IMG_UINT32           ui32Count         = 0;
+
+                       if (pui32TraceBuf == NULL)
+                       {
+                               /* trace buffer not yet allocated */
+                               continue;
+                       }
+
+                       while (ui32Count < ui32TraceBufSizeInDWords)
+                       {
+                               IMG_UINT32  ui32Data, ui32DataToId;
+
+                               /* Find the first valid log ID, skipping whitespace... */
+                               do
+                               {
+                                       ui32Data     = pui32TraceBuf[ui32HostTracePtr];
+                                       ui32DataToId = idToStringID(ui32Data, SFs);
+
+                                       /* If an unrecognized id is found it may be inconsistent data or a firmware trace error. */
+                                       if (ui32DataToId == RGXFW_SF_LAST  &&  RGXFW_LOG_VALIDID(ui32Data))
+                                       {
+                                               PVR_DUMPDEBUG_LOG("WARNING: Unrecognized id (%x). From here on the trace might be wrong!", ui32Data);
+                                       }
+
+                                       /* Update the trace pointer... */
+                                       ui32HostTracePtr++;
+                                       if (ui32HostTracePtr >= ui32TraceBufSizeInDWords)
+                                       {
+                                               ui32HostTracePtr = 0;
+                                               ui32HostWrapCount++;
+                                       }
+                                       ui32Count++;
+                               } while ((RGXFW_SF_LAST == ui32DataToId)  &&
+                                        ui32Count < ui32TraceBufSizeInDWords);
+
+                               if (ui32Count < ui32TraceBufSizeInDWords)
+                               {
+                                       IMG_CHAR   szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN] = "%" IMG_UINT64_FMTSPEC ":T%u-%s> ";
+                                       IMG_CHAR   szDebugInfoBuffer[RGXFWT_DEBUG_INFO_STR_MAXLEN] = "";
+                                       IMG_UINT64 ui64Timestamp;
+                                       IMG_UINT16 ui16DebugInfo;
+
+                                       /* If we hit the ASSERT message then this is the end of the log... */
+                                       if (ui32Data == RGXFW_SF_MAIN_ASSERT_FAILED)
+                                       {
+                                               PVR_DUMPDEBUG_LOG("ASSERTION %s failed at %s:%u",
+                                                                                 psRGXFWIfTraceBufCtl->sTraceBuf[tid].sAssertBuf.szInfo,
+                                                                                 psRGXFWIfTraceBufCtl->sTraceBuf[tid].sAssertBuf.szPath,
+                                                                                 psRGXFWIfTraceBufCtl->sTraceBuf[tid].sAssertBuf.ui32LineNum);
+                                               break;
+                                       }
+
+                                       ui64Timestamp = (IMG_UINT64)(pui32TraceBuf[(ui32HostTracePtr + 0) % ui32TraceBufSizeInDWords]) << 32 |
+                                                       (IMG_UINT64)(pui32TraceBuf[(ui32HostTracePtr + 1) % ui32TraceBufSizeInDWords]);
+
+                                       ui16DebugInfo = (IMG_UINT16) ((ui64Timestamp & ~RGXFWT_TIMESTAMP_DEBUG_INFO_CLRMSK) >> RGXFWT_TIMESTAMP_DEBUG_INFO_SHIFT);
+                                       ui64Timestamp = (ui64Timestamp & ~RGXFWT_TIMESTAMP_TIME_CLRMSK) >> RGXFWT_TIMESTAMP_TIME_SHIFT;
+
+                                       /*
+                                        * Print the trace string and provide up to 20 arguments which
+                                        * printf function will be able to use. We have already checked
+                                        * that no string uses more than this.
+                                        */
+                                       OSStringLCat(szBuffer, SFs[ui32DataToId].psName, PVR_MAX_DEBUG_MESSAGE_LEN);
+
+                                       /* Check and append any extra debug info available */
+                                       if (ui16DebugInfo)
+                                       {
+                                               /* Prepare debug info string */
+                                               RGXPrepareExtraDebugInfo(szDebugInfoBuffer, RGXFWT_DEBUG_INFO_STR_MAXLEN, ui16DebugInfo);
+
+                                               /* Append debug info string */
+                                               OSStringLCat(szBuffer, szDebugInfoBuffer, PVR_MAX_DEBUG_MESSAGE_LEN);
+                                       }
+
+                                       PVR_DUMPDEBUG_LOG(szBuffer, ui64Timestamp, tid, groups[RGXFW_SF_GID(ui32Data)],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  2) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  3) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  4) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  5) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  6) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  7) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  8) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr +  9) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 10) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 11) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 12) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 13) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 14) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 15) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 16) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 17) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 18) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 19) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 20) % ui32TraceBufSizeInDWords],
+                                                                         pui32TraceBuf[(ui32HostTracePtr + 21) % ui32TraceBufSizeInDWords]);
+
+                                       /* Update the trace pointer... */
+                                       ui32HostTracePtr = ui32HostTracePtr + 2 + RGXFW_SF_PARAMNUM(ui32Data);
+                                       if (ui32HostTracePtr >= ui32TraceBufSizeInDWords)
+                                       {
+                                               ui32HostTracePtr = ui32HostTracePtr % ui32TraceBufSizeInDWords;
+                                               ui32HostWrapCount++;
+                                       }
+                                       ui32Count = (ui32Count + 2 + RGXFW_SF_PARAMNUM(ui32Data));
+
+                                       /* Has the FW trace buffer overtaken the host pointer during the last line printed??? */
+                                       if ((*pui32FWWrapCount > ui32HostWrapCount) ||
+                                           ((*pui32FWWrapCount == ui32HostWrapCount) && (*pui32FWTracePtr > ui32HostTracePtr)))
+                                       {
+                                               /* Move forward to the oldest entry again... */
+                                               PVR_DUMPDEBUG_LOG(". . .");
+                                               ui32HostWrapCount = *pui32FWWrapCount;
+                                               ui32HostTracePtr  = *pui32FWTracePtr;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+#if defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+void RGXDumpPowerMonitoring(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                               void *pvDumpDebugFile,
+                               PVRSRV_RGXDEV_INFO  *psDevInfo)
+{
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+       /* Print the power monitoring counters... */
+       if (psFwSysData != NULL)
+       {
+               const IMG_UINT32 *pui32TraceBuf = psFwSysData->sPowerMonBuf.pui32TraceBuffer;
+               IMG_UINT32 ui32TracePtr = 0; //psFwSysData->sPowerMonBuf.ui32TracePointer;
+               IMG_UINT32 ui32PowerMonBufSizeInDWords = psFwSysData->ui32PowerMonBufSizeInDWords;
+               IMG_UINT32 ui32Count = 0;
+               IMG_UINT64 ui64Timestamp;
+
+               if (pui32TraceBuf == NULL)
+               {
+                       /* power monitoring buffer not yet allocated */
+                       return;
+               }
+
+               if (pui32TraceBuf[ui32TracePtr] != RGX_CR_TIMER)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "Power monitoring data not available."));
+                       return;
+               }
+               ui64Timestamp = (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr + 1) % ui32PowerMonBufSizeInDWords]) << 32 |
+                                               (IMG_UINT64)(pui32TraceBuf[(ui32TracePtr + 2) % ui32PowerMonBufSizeInDWords]);
+
+               /* Update the trace pointer... */
+               ui32TracePtr = (ui32TracePtr + 3) % ui32PowerMonBufSizeInDWords;
+               ui32Count    = (ui32Count    + 3);
+
+               PVR_DPF((PVR_DBG_WARNING, "Dumping power monitoring buffer: CPUVAddr = %p, pointer = 0x%x, size = 0x%x",
+                                pui32TraceBuf,
+                                ui32TracePtr,
+                                ui32PowerMonBufSizeInDWords));
+
+               while (ui32Count < ui32PowerMonBufSizeInDWords)
+               {
+                       /* power monitoring data is (register, value) dword pairs */
+                       PVR_DUMPDEBUG_LOG("%" IMG_UINT64_FMTSPEC ":POWMON  0x%08x 0x%08x  0x%08x 0x%08x",
+                                                         ui64Timestamp,
+                                                         pui32TraceBuf[(ui32TracePtr + 0) % ui32PowerMonBufSizeInDWords],
+                                                         pui32TraceBuf[(ui32TracePtr + 1) % ui32PowerMonBufSizeInDWords],
+                                                         pui32TraceBuf[(ui32TracePtr + 2) % ui32PowerMonBufSizeInDWords],
+                                                         pui32TraceBuf[(ui32TracePtr + 3) % ui32PowerMonBufSizeInDWords]);
+
+                       if (pui32TraceBuf[(ui32TracePtr + 0) % ui32PowerMonBufSizeInDWords] == RGXFWIF_TIMEDIFF_ID ||
+                               pui32TraceBuf[(ui32TracePtr + 2) % ui32PowerMonBufSizeInDWords] == RGXFWIF_TIMEDIFF_ID)
+                       {
+                               /* end of buffer */
+                               break;
+                       }
+
+                       /* Update the trace pointer... */
+                       ui32TracePtr = (ui32TracePtr + 4) % ui32PowerMonBufSizeInDWords;
+                       ui32Count    = (ui32Count    + 4);
+               }
+       }
+}
+#endif
+
+static const IMG_CHAR *_RGXGetDebugDevStateString(PVRSRV_DEVICE_STATE eDevState)
+{
+       switch (eDevState)
+       {
+               case PVRSRV_DEVICE_STATE_INIT:
+                       return "Initialising";
+               case PVRSRV_DEVICE_STATE_ACTIVE:
+                       return "Active";
+               case PVRSRV_DEVICE_STATE_DEINIT:
+                       return "De-initialising";
+               case PVRSRV_DEVICE_STATE_BAD:
+                       return "Bad";
+               case PVRSRV_DEVICE_STATE_UNDEFINED:
+                       PVR_ASSERT(!"Device has undefined state");
+                       __fallthrough;
+               default:
+                       return "Unknown";
+       }
+}
+
+static const IMG_CHAR* _RGXGetDebugDevPowerStateString(PVRSRV_DEV_POWER_STATE ePowerState)
+{
+       switch (ePowerState)
+       {
+               case PVRSRV_DEV_POWER_STATE_DEFAULT: return "DEFAULT";
+               case PVRSRV_DEV_POWER_STATE_OFF: return "OFF";
+               case PVRSRV_DEV_POWER_STATE_ON: return "ON";
+               default: return "UNKNOWN";
+       }
+}
+
+/* Helper macros to emit data */
+#define REG32_FMTSPEC   "%-30s: 0x%08X"
+#define REG64_FMTSPEC   "%-30s: 0x%016" IMG_UINT64_FMTSPECX
+#define DDLOG32(R)      PVR_DUMPDEBUG_LOG(REG32_FMTSPEC, #R, OSReadHWReg32(pvRegsBaseKM, RGX_CR_##R));
+#define DDLOG64(R)      PVR_DUMPDEBUG_LOG(REG64_FMTSPEC, #R, OSReadHWReg64(pvRegsBaseKM, RGX_CR_##R));
+#define DDLOG32_DPX(R)  PVR_DUMPDEBUG_LOG(REG32_FMTSPEC, #R, OSReadHWReg32(pvRegsBaseKM, DPX_CR_##R));
+#define DDLOG64_DPX(R)  PVR_DUMPDEBUG_LOG(REG64_FMTSPEC, #R, OSReadHWReg64(pvRegsBaseKM, DPX_CR_##R));
+#define DDLOGVAL32(S,V) PVR_DUMPDEBUG_LOG(REG32_FMTSPEC, S, V);
+#define DDLOG32UNPACKED(R)      PVR_DUMPDEBUG_LOG(REG32_FMTSPEC, #R, OSReadHWReg32(pvRegsBaseKM, RGX_CR_##R##__META_REGISTER_UNPACKED_ACCESSES));
+
+#if !defined(NO_HARDWARE)
+static PVRSRV_ERROR RGXDumpRISCVState(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                                                         void *pvDumpDebugFile,
+                                                                         PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+       RGXRISCVFW_STATE sRiscvState;
+       const IMG_CHAR *pszException;
+       PVRSRV_ERROR eError;
+
+       /* Limit dump to what is currently being used */
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG4);
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG5);
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG6);
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG12);
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG13);
+       DDLOG64(FWCORE_ADDR_REMAP_CONFIG14);
+
+       PVR_DUMPDEBUG_LOG("---- [ RISC-V internal state ] ----");
+
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+       if (RGXRiscvIsHalted(psDevInfo))
+       {
+               /* Avoid resuming the RISC-V FW as most operations
+                * on the debug module require a halted core */
+               PVR_DUMPDEBUG_LOG("(skipping as RISC-V found halted)");
+               return PVRSRV_OK;
+       }
+#endif
+
+       eError = RGXRiscvHalt(psDevInfo);
+       PVR_GOTO_IF_ERROR(eError, _RISCVDMError);
+
+#define X(name, address)                                                                                               \
+       eError = RGXRiscvReadReg(psDevInfo, address, &sRiscvState.name);        \
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXRiscvReadReg", _RISCVDMError);        \
+       DDLOGVAL32(#name, sRiscvState.name);
+
+       RGXRISCVFW_DEBUG_DUMP_REGISTERS
+#undef X
+
+       eError = RGXRiscvResume(psDevInfo);
+       PVR_GOTO_IF_ERROR(eError, _RISCVDMError);
+
+       pszException = _GetRISCVException(sRiscvState.mcause);
+       if (pszException != NULL)
+       {
+               PVR_DUMPDEBUG_LOG("RISC-V FW hit an exception: %s", pszException);
+
+               eError = _ValidateFWImage(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DUMPDEBUG_LOG("Failed to validate any FW code corruption");
+               }
+       }
+
+       return PVRSRV_OK;
+
+_RISCVDMError:
+       PVR_DPF((PVR_DBG_ERROR, "Failed to communicate with the Debug Module"));
+
+       return eError;
+}
+#endif
+
+PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                                                void *pvDumpDebugFile,
+                                                                PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if !defined(NO_HARDWARE)
+       IMG_UINT32   ui32Meta = RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ? RGX_GET_FEATURE_VALUE(psDevInfo, META) : 0;
+       IMG_UINT32   ui32RegVal;
+       PVRSRV_ERROR eError;
+       IMG_BOOL     bFirmwarePerf;
+#endif
+       IMG_BOOL     bMulticore = RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_MULTICORE_SUPPORT);
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+
+#if !defined(NO_HARDWARE)
+       /* Check if firmware perf was set at Init time */
+       bFirmwarePerf = (psDevInfo->psRGXFWIfSysInit->eFirmwarePerf != FW_PERF_CONF_NONE);
+#endif
+
+       DDLOG64(CORE_ID);
+
+       if (bMulticore)
+       {
+               DDLOG64(MULTICORE);
+               DDLOG32(MULTICORE_SYSTEM);
+               DDLOG32(MULTICORE_DOMAIN);
+       }
+       DDLOG32(EVENT_STATUS);
+       DDLOG64(TIMER);
+       DDLOG64(CLK_CTRL0);
+       DDLOG64(CLK_STATUS0);
+       DDLOG64(CLK_CTRL1);
+       DDLOG64(CLK_STATUS1);
+       DDLOG64(MMU_FAULT_STATUS1);
+       DDLOG64(MMU_FAULT_STATUS2);
+       DDLOG64(MMU_FAULT_STATUS_PM);
+       DDLOG64(MMU_FAULT_STATUS_META);
+       DDLOG64(SLC_STATUS1);
+       DDLOG64(SLC_STATUS2);
+       DDLOG64(SLC_STATUS_DEBUG);
+       DDLOG64(MMU_STATUS);
+       DDLOG32(BIF_PFS);
+       DDLOG32(BIF_TEXAS0_PFS);
+       DDLOG32(BIF_TEXAS1_PFS);
+       DDLOG32(BIF_OUTSTANDING_READ);
+       DDLOG32(BIF_TEXAS0_OUTSTANDING_READ);
+       DDLOG32(BIF_TEXAS1_OUTSTANDING_READ);
+       DDLOG32(FBCDC_IDLE);
+       DDLOG32(FBCDC_STATUS);
+       DDLOG32(SPU_ENABLE);
+
+       DDLOG64(CONTEXT_MAPPING0);
+       DDLOG64(CONTEXT_MAPPING2);
+       DDLOG64(CONTEXT_MAPPING3);
+       DDLOG64(CONTEXT_MAPPING4);
+
+       if (bMulticore)
+       {
+#if !defined(RGX_CR_MULTICORE_AXI)
+#define RGX_CR_MULTICORE_AXI                              (0x2508U)
+#define RGX_CR_MULTICORE_AXI_ERROR                        (0x2510U)
+#endif
+               DDLOG32(MULTICORE_AXI);
+               DDLOG32(MULTICORE_AXI_ERROR);
+               DDLOG32(MULTICORE_TDM_CTRL_COMMON);
+               DDLOG32(MULTICORE_FRAGMENT_CTRL_COMMON);
+               DDLOG32(MULTICORE_COMPUTE_CTRL_COMMON);
+       }
+
+       DDLOG32(PERF_PHASE_2D);
+       DDLOG32(PERF_CYCLE_2D_TOTAL);
+       DDLOG32(PERF_PHASE_GEOM);
+       DDLOG32(PERF_CYCLE_GEOM_TOTAL);
+       DDLOG32(PERF_PHASE_FRAG);
+       DDLOG32(PERF_CYCLE_FRAG_TOTAL);
+       DDLOG32(PERF_CYCLE_GEOM_OR_FRAG_TOTAL);
+       DDLOG32(PERF_CYCLE_GEOM_AND_FRAG_TOTAL);
+       DDLOG32(PERF_PHASE_COMP);
+       DDLOG32(PERF_CYCLE_COMP_TOTAL);
+       DDLOG32(PM_PARTIAL_RENDER_ENABLE);
+
+       DDLOG32(ISP_RENDER);
+       DDLOG32(ISP_CTL);
+
+       DDLOG32(MTS_INTCTX);
+       DDLOG32(MTS_BGCTX);
+       DDLOG32(MTS_BGCTX_COUNTED_SCHEDULE);
+       DDLOG32(MTS_SCHEDULE);
+       DDLOG32(MTS_GPU_INT_STATUS);
+
+       DDLOG32(CDM_CONTEXT_STORE_STATUS);
+       DDLOG64(CDM_CONTEXT_PDS0);
+       DDLOG64(CDM_CONTEXT_PDS1);
+       DDLOG64(CDM_TERMINATE_PDS);
+       DDLOG64(CDM_TERMINATE_PDS1);
+       DDLOG64(CDM_CONTEXT_LOAD_PDS0);
+       DDLOG64(CDM_CONTEXT_LOAD_PDS1);
+
+       DDLOG32(JONES_IDLE);
+       DDLOG32(SLC_IDLE);
+       DDLOG32(SLC_FAULT_STOP_STATUS);
+
+       DDLOG64(SCRATCH0);
+       DDLOG64(SCRATCH1);
+       DDLOG64(SCRATCH2);
+       DDLOG64(SCRATCH3);
+       DDLOG64(SCRATCH4);
+       DDLOG64(SCRATCH5);
+       DDLOG64(SCRATCH6);
+       DDLOG64(SCRATCH7);
+       DDLOG64(SCRATCH8);
+       DDLOG64(SCRATCH9);
+       DDLOG64(SCRATCH10);
+       DDLOG64(SCRATCH11);
+       DDLOG64(SCRATCH12);
+       DDLOG64(SCRATCH13);
+       DDLOG64(SCRATCH14);
+       DDLOG64(SCRATCH15);
+       DDLOG32(IRQ_OS0_EVENT_STATUS);
+
+#if !defined(NO_HARDWARE)
+       if (ui32Meta)
+       {
+               IMG_BOOL bIsT0Enabled = IMG_FALSE, bIsFWFaulted = IMG_FALSE;
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+               {
+                       DDLOG32UNPACKED(META_SP_MSLVIRQSTATUS);
+               }
+               else
+               {
+                       DDLOG32(META_SP_MSLVIRQSTATUS);
+               }
+
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+               DDLOGVAL32("T0 TXENABLE", ui32RegVal);
+               if (ui32RegVal & META_CR_TXENABLE_ENABLE_BIT)
+               {
+                       bIsT0Enabled = IMG_TRUE;
+               }
+
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0STATUS_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+               DDLOGVAL32("T0 TXSTATUS", ui32RegVal);
+
+               /* check for FW fault */
+               if (((ui32RegVal >> 20) & 0x3) == 0x2)
+               {
+                       bIsFWFaulted = IMG_TRUE;
+               }
+
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0DEFR_OFFSET, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+               DDLOGVAL32("T0 TXDEFR", ui32RegVal);
+
+               eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR0_PC, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+               DDLOGVAL32("T0 PC", ui32RegVal);
+
+               eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR0_PCX, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+               DDLOGVAL32("T0 PCX", ui32RegVal);
+
+               eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR0_SP, &ui32RegVal);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+               DDLOGVAL32("T0 SP", ui32RegVal);
+
+               if ((ui32Meta == MTP218) || (ui32Meta == MTP219))
+               {
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1ENABLE_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+                       DDLOGVAL32("T1 TXENABLE", ui32RegVal);
+
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1STATUS_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+                       DDLOGVAL32("T1 TXSTATUS", ui32RegVal);
+
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T1DEFR_OFFSET, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+                       DDLOGVAL32("T1 TXDEFR", ui32RegVal);
+
+                       eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR1_PC, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+                       DDLOGVAL32("T1 PC", ui32RegVal);
+
+                       eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR1_PCX, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+                       DDLOGVAL32("T1 PCX", ui32RegVal);
+
+                       eError = RGXReadMetaCoreReg(psDevInfo, META_CR_THR1_SP, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadMetaCoreReg", _METASPError);
+                       DDLOGVAL32("T1 SP", ui32RegVal);
+               }
+
+               if (bFirmwarePerf)
+               {
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_PERF_COUNT0, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+                       DDLOGVAL32("META_CR_PERF_COUNT0", ui32RegVal);
+
+                       eError = RGXReadFWModuleAddr(psDevInfo, META_CR_PERF_COUNT1, &ui32RegVal);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXReadFWModuleAddr", _METASPError);
+                       DDLOGVAL32("META_CR_PERF_COUNT1", ui32RegVal);
+               }
+
+               if (bIsT0Enabled & bIsFWFaulted)
+               {
+                       eError = _ValidateFWImage(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DUMPDEBUG_LOG("Failed to validate any FW code corruption");
+                       }
+               }
+               else if (bIsFWFaulted)
+               {
+                       PVR_DUMPDEBUG_LOG("Skipping FW code memory corruption checking as META is disabled");
+               }
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               eError = RGXDumpRISCVState(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+               PVR_RETURN_IF_ERROR(eError);
+       }
+#endif
+
+       return PVRSRV_OK;
+
+#if !defined(NO_HARDWARE)
+_METASPError:
+       PVR_DUMPDEBUG_LOG("Dump Slave Port debug information");
+       _RGXDumpMetaSPExtraDebugInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+
+       return eError;
+#endif
+}
+
+#undef REG32_FMTSPEC
+#undef REG64_FMTSPEC
+#undef DDLOG32
+#undef DDLOG64
+#undef DDLOG32_DPX
+#undef DDLOG64_DPX
+#undef DDLOGVAL32
+#undef DDLOG32UNPACKED
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDebugRequestProcess
+
+ @Description
+
+ This function will print out the debug for the specified level of verbosity
+
+ @Input pfnDumpDebugPrintf  - Optional replacement print function
+ @Input pvDumpDebugFile     - Optional file identifier to be passed to the
+                              'printf' function if required
+ @Input psDevInfo           - RGX device info
+ @Input ui32VerbLevel       - Verbosity level
+
+ @Return   void
+
+******************************************************************************/
+static
+void RGXDebugRequestProcess(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                               void *pvDumpDebugFile,
+                               PVRSRV_RGXDEV_INFO *psDevInfo,
+                               IMG_UINT32 ui32VerbLevel)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       PVRSRV_DEV_POWER_STATE  ePowerState;
+       IMG_BOOL                bRGXPoweredON;
+       IMG_UINT8               ui8FwOsCount;
+       RGXFWIF_TRACEBUF        *psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       const RGXFWIF_OSDATA    *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
+       IMG_BOOL                bPwrLockAlreadyHeld;
+
+       bPwrLockAlreadyHeld = PVRSRVPwrLockIsLockedByMe(psDeviceNode);
+       if (!bPwrLockAlreadyHeld)
+       {
+               /* Only acquire the power-lock if not already held by the calling context */
+               eError = PVRSRVPowerLock(psDeviceNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire lock (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       return;
+               }
+       }
+
+       ui8FwOsCount = psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.sInitOptions.ui8OsCountSupport;
+
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Error retrieving RGX power state. No debug info dumped.",
+                               __func__));
+               goto Exit;
+       }
+
+       if ((PVRSRV_VZ_MODE_IS(NATIVE) && (ui8FwOsCount > 1)) ||
+               (PVRSRV_VZ_MODE_IS(HOST) && (ui8FwOsCount != RGX_NUM_OS_SUPPORTED)))
+       {
+               PVR_DUMPDEBUG_LOG("Mismatch between the number of Operating Systems supported by KM driver (%d) and FW (%d)",
+                                                 (PVRSRV_VZ_MODE_IS(NATIVE)) ? (1) : (RGX_NUM_OS_SUPPORTED), ui8FwOsCount);
+       }
+
+       PVR_DUMPDEBUG_LOG("------[ RGX Device ID:%d Start ]------", psDevInfo->psDeviceNode->sDevId.ui32InternalID);
+
+       bRGXPoweredON = (ePowerState == PVRSRV_DEV_POWER_STATE_ON);
+
+       PVR_DUMPDEBUG_LOG("------[ RGX Info ]------");
+       PVR_DUMPDEBUG_LOG("Device Node (Info): %p (%p)", psDevInfo->psDeviceNode, psDevInfo);
+       PVR_DUMPDEBUG_LOG("RGX BVNC: %d.%d.%d.%d (%s)", psDevInfo->sDevFeatureCfg.ui32B,
+                                                                                          psDevInfo->sDevFeatureCfg.ui32V,
+                                                                                          psDevInfo->sDevFeatureCfg.ui32N,
+                                                                                          psDevInfo->sDevFeatureCfg.ui32C,
+                                                                                          PVR_ARCH_NAME);
+       PVR_DUMPDEBUG_LOG("RGX Device State: %s", _RGXGetDebugDevStateString(psDeviceNode->eDevState));
+       PVR_DUMPDEBUG_LOG("RGX Power State: %s", _RGXGetDebugDevPowerStateString(ePowerState));
+       if (psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated)
+       {
+               PVR_DUMP_FIRMWARE_INFO(psDevInfo->psRGXFWIfOsInit->sRGXCompChecks);
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("FW info: UNINITIALIZED");
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, TILE_REGION_PROTECTION))
+       {
+#if defined(SUPPORT_TRP)
+               PVR_DUMPDEBUG_LOG("TRP: HW support - Yes; SW enabled");
+#else
+               PVR_DUMPDEBUG_LOG("TRP: HW support - Yes; SW disabled");
+#endif
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("TRP: HW support - No");
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, WORKGROUP_PROTECTION))
+       {
+#if defined(SUPPORT_WGP)
+               PVR_DUMPDEBUG_LOG("WGP: HW support - Yes; SW enabled");
+#else
+               PVR_DUMPDEBUG_LOG("WGP: HW support - Yes; SW disabled");
+#endif
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG("WGP: HW support - No");
+       }
+
+       RGXDumpRGXDebugSummary(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, bRGXPoweredON);
+
+       /* Dump out the kernel CCB. */
+       {
+               const RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
+
+               if (psKCCBCtl != NULL)
+               {
+                       PVR_DUMPDEBUG_LOG("RGX Kernel CCB WO:0x%X RO:0x%X",
+                                                         psKCCBCtl->ui32WriteOffset,
+                                                         psKCCBCtl->ui32ReadOffset);
+               }
+       }
+
+       /* Dump out the firmware CCB. */
+       {
+               const RGXFWIF_CCB_CTL *psFCCBCtl = psDevInfo->psFirmwareCCBCtl;
+
+               if (psFCCBCtl != NULL)
+               {
+                       PVR_DUMPDEBUG_LOG("RGX Firmware CCB WO:0x%X RO:0x%X",
+                                                          psFCCBCtl->ui32WriteOffset,
+                                                          psFCCBCtl->ui32ReadOffset);
+               }
+       }
+
+       if (psFwOsData != NULL)
+       {
+               IMG_UINT32 ui32TID;
+
+               /* Dump the KCCB commands executed */
+               PVR_DUMPDEBUG_LOG("RGX Kernel CCB commands executed = %d",
+                                                 psFwOsData->ui32KCCBCmdsExecuted);
+
+#if defined(PVRSRV_STALLED_CCB_ACTION)
+               /* Dump the number of times we have performed a forced UFO update,
+                * and (if non-zero) the timestamp of the most recent occurrence/
+                */
+               PVR_DUMPDEBUG_LOG("RGX SLR: Forced UFO updates requested = %d",
+                                                 psFwOsData->ui32ForcedUpdatesRequested);
+               if (psFwOsData->ui32ForcedUpdatesRequested > 0)
+               {
+                       IMG_UINT8 ui8Idx;
+                       IMG_UINT64 ui64Seconds, ui64Nanoseconds;
+
+                       if (psFwOsData->ui64LastForcedUpdateTime > 0ULL)
+                       {
+                               ConvertOSTimestampToSAndNS(psFwOsData->ui64LastForcedUpdateTime, &ui64Seconds, &ui64Nanoseconds);
+                               PVR_DUMPDEBUG_LOG("RGX SLR: (most recent forced update was around %" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC ")",
+                                                                 ui64Seconds, ui64Nanoseconds);
+                       }
+                       else
+                       {
+                               PVR_DUMPDEBUG_LOG("RGX SLR: (unable to force update as fence contained no sync checkpoints)");
+                       }
+                       /* Dump SLR log */
+                       if (psFwOsData->sSLRLogFirst.aszCCBName[0])
+                       {
+                               ConvertOSTimestampToSAndNS(psFwOsData->sSLRLogFirst.ui64Timestamp, &ui64Seconds, &ui64Nanoseconds);
+                               PVR_DUMPDEBUG_LOG("RGX SLR:{%" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC
+                                                                 "} Fence found on context 0x%x '%s' has %d UFOs",
+                                                                 ui64Seconds, ui64Nanoseconds,
+                                                                 psFwOsData->sSLRLogFirst.ui32FWCtxAddr,
+                                                                 psFwOsData->sSLRLogFirst.aszCCBName,
+                                                                 psFwOsData->sSLRLogFirst.ui32NumUFOs);
+                       }
+                       for (ui8Idx=0; ui8Idx<PVR_SLR_LOG_ENTRIES;ui8Idx++)
+                       {
+                               if (psFwOsData->sSLRLog[ui8Idx].aszCCBName[0])
+                               {
+                                       ConvertOSTimestampToSAndNS(psFwOsData->sSLRLog[ui8Idx].ui64Timestamp, &ui64Seconds, &ui64Nanoseconds);
+                                       PVR_DUMPDEBUG_LOG("RGX SLR:[%" IMG_UINT64_FMTSPEC ".%09" IMG_UINT64_FMTSPEC
+                                                                         "] Fence found on context 0x%x '%s' has %d UFOs",
+                                                                         ui64Seconds, ui64Nanoseconds,
+                                                                         psFwOsData->sSLRLog[ui8Idx].ui32FWCtxAddr,
+                                                                         psFwOsData->sSLRLog[ui8Idx].aszCCBName,
+                                                                         psFwOsData->sSLRLog[ui8Idx].ui32NumUFOs);
+                               }
+                       }
+               }
+#else
+               PVR_DUMPDEBUG_LOG("RGX SLR: Disabled");
+#endif
+
+               /* Dump the error counts */
+               PVR_DUMPDEBUG_LOG("RGX Errors: WGP:%d, TRP:%d",
+                                                 psDevInfo->sErrorCounts.ui32WGPErrorCount,
+                                                 psDevInfo->sErrorCounts.ui32TRPErrorCount);
+
+               for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+               {
+                       /* Dump the IRQ info for threads */
+                       PVR_DUMPDEBUG_LOG("RGX FW thread %u: FW IRQ count = %u, Last sampled IRQ count in LISR = %u",
+                                                         ui32TID,
+                                                         psFwOsData->aui32InterruptCount[ui32TID],
+                                                         psDevInfo->aui32SampleIRQCount[ui32TID]);
+               }
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Dump out the Workload estimation CCB. */
+       {
+               const RGXFWIF_CCB_CTL *psWorkEstCCBCtl = psDevInfo->psWorkEstFirmwareCCBCtl;
+
+               if (psWorkEstCCBCtl != NULL)
+               {
+                       PVR_DUMPDEBUG_LOG("RGX WorkEst CCB WO:0x%X RO:0x%X",
+                                                         psWorkEstCCBCtl->ui32WriteOffset,
+                                                         psWorkEstCCBCtl->ui32ReadOffset);
+               }
+       }
+#endif
+
+       /* Dump the FW Sys config flags on the Host */
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+               IMG_CHAR sFwSysFlagsDescription[MAX_FW_DESCRIPTION_LENGTH];
+
+               if (!psFwSysData)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Fw Sys Data is not mapped into CPU space", __func__));
+                       goto Exit;
+               }
+
+               _GetFwSysFlagsDescription(sFwSysFlagsDescription, MAX_FW_DESCRIPTION_LENGTH, psFwSysData->ui32ConfigFlags);
+               PVR_DUMPDEBUG_LOG("FW System config flags = 0x%08X (%s)", psFwSysData->ui32ConfigFlags, sFwSysFlagsDescription);
+       }
+
+       /* Dump the FW OS config flags */
+       {
+               IMG_CHAR sFwOsFlagsDescription[MAX_FW_DESCRIPTION_LENGTH];
+
+               if (!psFwOsData)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Fw Os Data is not mapped into CPU space", __func__));
+                       goto Exit;
+               }
+
+               _GetFwOsFlagsDescription(sFwOsFlagsDescription, MAX_FW_DESCRIPTION_LENGTH, psFwOsData->ui32FwOsConfigFlags);
+               PVR_DUMPDEBUG_LOG("FW OS config flags = 0x%08X (%s)", psFwOsData->ui32FwOsConfigFlags, sFwOsFlagsDescription);
+       }
+
+       if ((bRGXPoweredON) && !PVRSRV_VZ_MODE_IS(GUEST))
+       {
+
+               PVR_DUMPDEBUG_LOG("------[ RGX registers ]------");
+               PVR_DUMPDEBUG_LOG("RGX Register Base Address (Linear):   0x%p", psDevInfo->pvRegsBaseKM);
+               PVR_DUMPDEBUG_LOG("RGX Register Base Address (Physical): 0x%08lX", (unsigned long)psDevInfo->sRegsPhysBase.uiAddr);
+
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+               {
+                       /* Forcing bit 6 of MslvCtrl1 to 0 to avoid internal reg read going through the core */
+                       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+                       {
+                               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES, 0x0);
+                       }
+                       else
+                       {
+                               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL1, 0x0);
+                       }
+               }
+
+               eError = RGXDumpRGXRegisters(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: RGXDumpRGXRegisters failed (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
+                       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+                       {
+                               PVR_DUMPDEBUG_LOG("Dump Slave Port debug information");
+                               _RGXDumpMetaSPExtraDebugInfo(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo);
+                       }
+#endif
+               }
+       }
+       else
+       {
+               PVR_DUMPDEBUG_LOG(" (!) %s. No registers dumped", PVRSRV_VZ_MODE_IS(GUEST) ? "Guest Mode of operation" : "RGX power is down");
+       }
+
+       PVR_DUMPDEBUG_LOG("------[ RGX FW Trace Info ]------");
+
+       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_MEDIUM))
+       {
+               IMG_INT tid;
+               /* Dump FW trace information */
+               if (psRGXFWIfTraceBufCtl != NULL)
+               {
+                       for (tid = 0 ; tid < RGXFW_THREAD_NUM ; tid++)
+                       {
+                               IMG_UINT32      i;
+                               IMG_BOOL        bPrevLineWasZero = IMG_FALSE;
+                               IMG_BOOL        bLineIsAllZeros = IMG_FALSE;
+                               IMG_UINT32      ui32CountLines = 0;
+                               IMG_UINT32      *pui32TraceBuffer;
+                               IMG_CHAR        *pszLine;
+
+                               if (psRGXFWIfTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_GROUP_MASK)
+                               {
+                                       PVR_DUMPDEBUG_LOG("Debug log type: %s ( " RGXFWIF_LOG_ENABLED_GROUPS_LIST_PFSPEC ")",
+                                                                         ((psRGXFWIfTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_TRACE)?("trace"):("tbi")),
+                                                                         RGXFWIF_LOG_ENABLED_GROUPS_LIST(psRGXFWIfTraceBufCtl->ui32LogType)
+                                                                         );
+                               }
+                               else
+                               {
+                                       PVR_DUMPDEBUG_LOG("Debug log type: none");
+                               }
+
+                               pui32TraceBuffer = psRGXFWIfTraceBufCtl->sTraceBuf[tid].pui32TraceBuffer;
+
+                               /* Skip if trace buffer is not allocated */
+                               if (pui32TraceBuffer == NULL)
+                               {
+                                       PVR_DUMPDEBUG_LOG("RGX FW thread %d: Trace buffer not yet allocated",tid);
+                                       continue;
+                               }
+
+/* Max number of DWords to be printed per line, in debug dump output */
+#define PVR_DD_FW_TRACEBUF_LINESIZE 30U
+                               /* each element in the line is 8 characters plus a space.  The '+ 1' is because of the final trailing '\0'. */
+                               pszLine = OSAllocMem(9 * PVR_DD_FW_TRACEBUF_LINESIZE + 1);
+                               if (pszLine == NULL)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                       "%s: Out of mem allocating line string (size: %d)",
+                                                       __func__,
+                                                       9 * PVR_DD_FW_TRACEBUF_LINESIZE + 1));
+                                       goto Exit;
+                               }
+
+                               PVR_DUMPDEBUG_LOG("------[ RGX FW thread %d trace START ]------", tid);
+                               PVR_DUMPDEBUG_LOG("FWT[traceptr]: %X", psRGXFWIfTraceBufCtl->sTraceBuf[tid].ui32TracePointer);
+                               PVR_DUMPDEBUG_LOG("FWT[tracebufsize]: %X", psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords);
+
+                               for (i = 0; i < psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords; i += PVR_DD_FW_TRACEBUF_LINESIZE)
+                               {
+                                       IMG_UINT32 k = 0;
+                                       IMG_UINT32 ui32Line = 0x0;
+                                       IMG_UINT32 ui32LineOffset = i*sizeof(IMG_UINT32);
+                                       IMG_CHAR   *pszBuf = pszLine;
+
+                                       for (k = 0; k < PVR_DD_FW_TRACEBUF_LINESIZE; k++)
+                                       {
+                                               if ((i + k) >= psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords)
+                                               {
+                                                       /* Stop reading when the index goes beyond trace buffer size. This condition is
+                                                        * hit during printing the last line in DD when ui32TraceBufSizeInDWords is not
+                                                        * a multiple of PVR_DD_FW_TRACEBUF_LINESIZE */
+                                                       break;
+                                               }
+
+                                               ui32Line |= pui32TraceBuffer[i + k];
+
+                                               /* prepare the line to print it. The '+1' is because of the trailing '\0' added */
+                                               OSSNPrintf(pszBuf, 9 + 1, " %08x", pui32TraceBuffer[i + k]);
+                                               pszBuf += 9; /* write over the '\0' */
+                                       }
+
+                                       bLineIsAllZeros = (ui32Line == 0x0);
+
+                                       if (bLineIsAllZeros)
+                                       {
+                                               if (bPrevLineWasZero)
+                                               {
+                                                       ui32CountLines++;
+                                               }
+                                               else
+                                               {
+                                                       bPrevLineWasZero = IMG_TRUE;
+                                                       ui32CountLines = 1;
+                                                       PVR_DUMPDEBUG_LOG("FWT[%08x]: 00000000 ... 00000000", ui32LineOffset);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (bPrevLineWasZero  &&  ui32CountLines > 1)
+                                               {
+                                                       PVR_DUMPDEBUG_LOG("FWT[...]: %d lines were all zero", ui32CountLines);
+                                               }
+                                               bPrevLineWasZero = IMG_FALSE;
+
+                                               PVR_DUMPDEBUG_LOG("FWT[%08x]:%s", ui32LineOffset, pszLine);
+                                       }
+
+                               }
+                               if (bPrevLineWasZero)
+                               {
+                                       PVR_DUMPDEBUG_LOG("FWT[END]: %d lines were all zero", ui32CountLines);
+                               }
+
+                               PVR_DUMPDEBUG_LOG("------[ RGX FW thread %d trace END ]------", tid);
+
+                               OSFreeMem(pszLine);
+                       }
+               }
+
+               {
+                       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_HIGH))
+                       {
+                               PVR_DUMPDEBUG_LOG("------[ Full CCB Status ]------");
+                       }
+                       else
+                       {
+                               PVR_DUMPDEBUG_LOG("------[ Stalled FWCtxs ]------");
+                       }
+
+                       DumpRenderCtxtsInfo(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+                       DumpComputeCtxtsInfo(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+
+                       DumpTDMTransferCtxtsInfo(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+
+                       DumpKickSyncCtxtsInfo(psDevInfo, pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+               }
+       }
+
+       PVR_DUMPDEBUG_LOG("------[ RGX Device ID:%d End ]------", psDevInfo->psDeviceNode->sDevId.ui32InternalID);
+
+Exit:
+       if (!bPwrLockAlreadyHeld)
+       {
+               PVRSRVPowerUnlock(psDeviceNode);
+       }
+}
+
+/*!
+ ******************************************************************************
+
+ @Function     RGXDebugRequestNotify
+
+ @Description Dump the debug data for RGX
+
+ ******************************************************************************/
+static void RGXDebugRequestNotify(PVRSRV_DBGREQ_HANDLE hDbgRequestHandle,
+               IMG_UINT32 ui32VerbLevel,
+               DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+               void *pvDumpDebugFile)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = hDbgRequestHandle;
+
+       /* Only action the request if we've fully init'ed */
+       if (psDevInfo->bDevInit2Done)
+       {
+               RGXDebugRequestProcess(pfnDumpDebugPrintf, pvDumpDebugFile, psDevInfo, ui32VerbLevel);
+       }
+}
+
+PVRSRV_ERROR RGXDebugInit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       return PVRSRVRegisterDeviceDbgRequestNotify(&psDevInfo->hDbgReqNotify,
+                                                       psDevInfo->psDeviceNode,
+                                                       RGXDebugRequestNotify,
+                                                       DEBUG_REQUEST_RGX,
+                                                       psDevInfo);
+}
+
+PVRSRV_ERROR RGXDebugDeinit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       if (psDevInfo->hDbgReqNotify)
+       {
+               return PVRSRVUnregisterDeviceDbgRequestNotify(psDevInfo->hDbgReqNotify);
+       }
+
+       /* No notifier registered */
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (rgxdebug.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdebug.h
new file mode 100644 (file)
index 0000000..d253d89
--- /dev/null
@@ -0,0 +1,191 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX debug header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX debugging functions
+@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(RGXDEBUG_H)
+#define RGXDEBUG_H
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "device.h"
+#include "pvr_notifier.h"
+#include "pvrsrv.h"
+#include "rgxdevice.h"
+
+/**
+ * Debug utility macro for printing FW IRQ count and Last sampled IRQ count in
+ * LISR for each RGX FW thread.
+ * Macro takes pointer to PVRSRV_RGXDEV_INFO as input.
+ */
+#define RGXDEBUG_PRINT_IRQ_COUNT(psRgxDevInfo) \
+       do \
+       { \
+               IMG_UINT32 ui32TID; \
+               for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++) \
+               { \
+                       PVR_DPF((DBGPRIV_VERBOSE, \
+                                       "RGX FW thread %u: FW IRQ count = %u, Last sampled IRQ count in LISR = %u)", \
+                                       ui32TID, \
+                                       (psRgxDevInfo)->psRGXFWIfFwOsData->aui32InterruptCount[ui32TID], \
+                                       (psRgxDevInfo)->aui32SampleIRQCount[ui32TID])); \
+               } \
+       } while (0)
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDumpRGXRegisters
+
+ @Description
+
+ Dumps an extensive list of RGX registers required for debugging
+
+ @Input pfnDumpDebugPrintf  - Optional replacement print function
+ @Input pvDumpDebugFile     - Optional file identifier to be passed to the
+                              'printf' function if required
+ @Input psDevInfo           - RGX device info
+
+ @Return PVRSRV_ERROR         PVRSRV_OK on success, error code otherwise
+
+******************************************************************************/
+PVRSRV_ERROR RGXDumpRGXRegisters(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                                                void *pvDumpDebugFile,
+                                                                PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDumpFirmwareTrace
+
+ @Description Dumps the decoded version of the firmware trace buffer.
+
+ Dump useful debugging info
+
+ @Input pfnDumpDebugPrintf  - Optional replacement print function
+ @Input pvDumpDebugFile     - Optional file identifier to be passed to the
+                              'printf' function if required
+ @Input psDevInfo           - RGX device info
+
+ @Return   void
+
+******************************************************************************/
+void RGXDumpFirmwareTrace(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                               void *pvDumpDebugFile,
+                               PVRSRV_RGXDEV_INFO  *psDevInfo);
+
+#if defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+void RGXDumpPowerMonitoring(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                               void *pvDumpDebugFile,
+                               PVRSRV_RGXDEV_INFO  *psDevInfo);
+#endif
+
+#if defined(SUPPORT_FW_VIEW_EXTRA_DEBUG)
+/*!
+*******************************************************************************
+
+ @Function     ValidateFWOnLoad
+
+ @Description  Compare the Firmware image as seen from the CPU point of view
+               against the same memory area as seen from the firmware point
+               of view after first power up.
+
+ @Input        psDevInfo - Device Info
+
+ @Return       PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR ValidateFWOnLoad(PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDumpRGXDebugSummary
+
+ @Description
+
+ Dump a summary in human readable form with the RGX state
+
+ @Input pfnDumpDebugPrintf   - The debug printf function
+ @Input pvDumpDebugFile      - Optional file identifier to be passed to the
+                               'printf' function if required
+ @Input psDevInfo           - RGX device info
+ @Input bRGXPoweredON        - IMG_TRUE if RGX device is on
+
+ @Return   void
+
+******************************************************************************/
+void RGXDumpRGXDebugSummary(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                                       void *pvDumpDebugFile,
+                                       PVRSRV_RGXDEV_INFO *psDevInfo,
+                                       IMG_BOOL bRGXPoweredON);
+
+/*!
+*******************************************************************************
+
+ @Function RGXDebugInit
+
+ @Description
+
+ Setup debug requests, calls into PVRSRVRegisterDeviceDbgRequestNotify
+
+ @Input          psDevInfo            RGX device info
+ @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
+
+******************************************************************************/
+PVRSRV_ERROR RGXDebugInit(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function RGXDebugDeinit
+
+ @Description
+
+ Remove debug requests, calls into PVRSRVUnregisterDeviceDbgRequestNotify
+
+ @Output         phNotify             Points to debug notifier handle
+ @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
+
+******************************************************************************/
+PVRSRV_ERROR RGXDebugDeinit(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+#endif /* RGXDEBUG_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdevice.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxdevice.h
new file mode 100644 (file)
index 0000000..90c8540
--- /dev/null
@@ -0,0 +1,832 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX device node header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX device node
+@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(RGXDEVICE_H)
+#define RGXDEVICE_H
+
+#include "img_types.h"
+#include "img_defs.h"
+#include "pvrsrv_device_types.h"
+#include "mmu_common.h"
+#include "rgx_fwif_km.h"
+#include "cache_ops.h"
+#include "device.h"
+#include "osfunc.h"
+#include "rgxlayer_impl.h"
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "hash.h"
+#endif
+typedef struct _RGX_SERVER_COMMON_CONTEXT_ RGX_SERVER_COMMON_CONTEXT;
+
+typedef struct {
+       DEVMEM_MEMDESC          *psFWFrameworkMemDesc;
+} RGX_COMMON_CONTEXT_INFO;
+
+
+/*!
+ ******************************************************************************
+ * Device state flags
+ *****************************************************************************/
+#define RGXKM_DEVICE_STATE_ZERO_FREELIST                          (0x1)  /*!< Zeroing the physical pages of reconstructed free lists */
+#define RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN                  (0x2)  /*!< Used to disable the Devices Watchdog logging */
+#define RGXKM_DEVICE_STATE_GPU_UNITS_POWER_CHANGE_EN              (0x4)  /*!< Used for validation to inject SPU power state mask change every DM kick */
+#define RGXKM_DEVICE_STATE_CCB_GROW_EN                            (0x8)  /*!< Used to indicate CCB grow is permitted */
+#define RGXKM_DEVICE_STATE_ENABLE_SPU_UNITS_POWER_MASK_CHANGE_EN  (0x10) /*!< Used for validation to enable SPU power state mask change */
+#define RGXKM_DEVICE_STATE_MASK                                   (0x1F)
+
+/*!
+ ******************************************************************************
+ * GPU DVFS Table
+ *****************************************************************************/
+
+#define RGX_GPU_DVFS_TABLE_SIZE                      32
+#define RGX_GPU_DVFS_FIRST_CALIBRATION_TIME_US       25000     /* Time required to calibrate a clock frequency the first time */
+#define RGX_GPU_DVFS_TRANSITION_CALIBRATION_TIME_US  150000    /* Time required for a recalibration after a DVFS transition */
+#define RGX_GPU_DVFS_PERIODIC_CALIBRATION_TIME_US    10000000  /* Time before the next periodic calibration and correlation */
+
+
+/*!
+ ******************************************************************************
+ * Global flags for driver validation
+ *****************************************************************************/
+#define RGX_VAL_LS_EN                             (0x1U)  /*!< Enable dual lockstep firmware */
+#define RGX_VAL_FBDC_SIG_CHECK_NOERR_EN           (0x2U)  /*!< Enable FBDC signature check. Signatures must match */
+#define RGX_VAL_FBDC_SIG_CHECK_ERR_EN             (0x4U)  /*!< Enable FBDC signature check. Signatures must not match */
+#define RGX_VAL_GPUSTATEPIN_EN                    (0x8U)  /*!< Enable GPU state pin check */
+#define RGX_VAL_KZ_SIG_CHECK_NOERR_EN            (0x10U)  /*!< Enable KZ signature check. Signatures must match */
+#define RGX_VAL_KZ_SIG_CHECK_ERR_EN              (0x20U)  /*!< Enable KZ signature check. Signatures must not match */
+#define RGX_VAL_SIG_CHECK_ERR_EN                 (RGX_VAL_FBDC_SIG_CHECK_ERR_EN)
+
+typedef struct _GPU_FREQ_TRACKING_DATA_
+{
+       /* Core clock speed estimated by the driver */
+       IMG_UINT32 ui32EstCoreClockSpeed;
+
+       /* Amount of successful calculations of the estimated core clock speed */
+       IMG_UINT32 ui32CalibrationCount;
+} GPU_FREQ_TRACKING_DATA;
+
+#if defined(PVRSRV_TIMER_CORRELATION_HISTORY)
+#define RGX_GPU_FREQ_TRACKING_SIZE 16
+
+typedef struct
+{
+       IMG_UINT64 ui64BeginCRTimestamp;
+       IMG_UINT64 ui64BeginOSTimestamp;
+
+       IMG_UINT64 ui64EndCRTimestamp;
+       IMG_UINT64 ui64EndOSTimestamp;
+
+       IMG_UINT32 ui32EstCoreClockSpeed;
+       IMG_UINT32 ui32CoreClockSpeed;
+} GPU_FREQ_TRACKING_HISTORY;
+#endif
+
+typedef struct _RGX_GPU_DVFS_TABLE_
+{
+       /* Beginning of current calibration period (in us) */
+       IMG_UINT64 ui64CalibrationCRTimestamp;
+       IMG_UINT64 ui64CalibrationOSTimestamp;
+
+       /* Calculated calibration period (in us) */
+       IMG_UINT64 ui64CalibrationCRTimediff;
+       IMG_UINT64 ui64CalibrationOSTimediff;
+
+       /* Current calibration period (in us) */
+       IMG_UINT32 ui32CalibrationPeriod;
+
+       /* System layer frequency table and frequency tracking data */
+       IMG_UINT32 ui32FreqIndex;
+       IMG_UINT32 aui32GPUFrequency[RGX_GPU_DVFS_TABLE_SIZE];
+       GPU_FREQ_TRACKING_DATA asTrackingData[RGX_GPU_DVFS_TABLE_SIZE];
+
+#if defined(PVRSRV_TIMER_CORRELATION_HISTORY)
+       IMG_UINT32 ui32HistoryIndex;
+       GPU_FREQ_TRACKING_HISTORY asTrackingHistory[RGX_GPU_FREQ_TRACKING_SIZE];
+#endif
+} RGX_GPU_DVFS_TABLE;
+
+
+/*!
+ ******************************************************************************
+ * GPU utilisation statistics
+ *****************************************************************************/
+
+typedef struct _RGXFWIF_GPU_UTIL_STATS_
+{
+       IMG_BOOL   bValid;                /* If TRUE, statistics are valid.
+                                            FALSE if the driver couldn't get reliable stats. */
+       IMG_UINT64 ui64GpuStatActive;     /* GPU active statistic */
+       IMG_UINT64 ui64GpuStatBlocked;    /* GPU blocked statistic */
+       IMG_UINT64 ui64GpuStatIdle;       /* GPU idle statistic */
+       IMG_UINT64 ui64GpuStatCumulative; /* Sum of active/blocked/idle stats */
+       IMG_UINT64 ui64TimeStamp;         /* Timestamp of the most recent sample of the GPU stats */
+} RGXFWIF_GPU_UTIL_STATS;
+
+
+typedef struct _RGX_REG_CONFIG_
+{
+       IMG_BOOL               bEnabled;
+       RGXFWIF_REG_CFG_TYPE   eRegCfgTypeToPush;
+       IMG_UINT32             ui32NumRegRecords;
+       POS_LOCK               hLock;
+} RGX_REG_CONFIG;
+
+typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
+
+#if defined(SUPPORT_VALIDATION)
+/**
+ * Structure containing information for calculating next SPU power domain state.
+ */
+typedef struct _RGX_POWER_DOMAIN_STATE_
+{
+       /**
+        * Total number of power units in the core.
+        */
+       IMG_UINT32 ui32PowUnitsCount;
+       /**
+        * Current power domain state
+        */
+       IMG_UINT32 ui32CurrentState;
+       /**
+        * Stores last transition that happened for each power domain state.
+        */
+       IMG_UINT32 *paui32LastTransition;
+} RGX_POWER_DOMAIN_STATE;
+#endif
+
+typedef struct _PVRSRV_DEVICE_FEATURE_CONFIG_
+{
+       IMG_UINT64 ui64ErnsBrns;
+       IMG_UINT64 ui64Features;
+       IMG_UINT32 ui32B;
+       IMG_UINT32 ui32V;
+       IMG_UINT32 ui32N;
+       IMG_UINT32 ui32C;
+       IMG_UINT32 ui32FeaturesValues[RGX_FEATURE_WITH_VALUES_MAX_IDX];
+       IMG_UINT32 ui32MAXDMCount;
+       IMG_UINT32 ui32MAXPowUnitCount;
+       IMG_UINT32 ui32MAXRACCount;
+       IMG_UINT32 ui32SLCSizeInBytes;
+       IMG_PCHAR  pszBVNCString;
+}PVRSRV_DEVICE_FEATURE_CONFIG;
+
+/* This is used to get the value of a specific feature.
+ * Note that it will assert if the feature is disabled or value is invalid. */
+#define RGX_GET_FEATURE_VALUE(psDevInfo, Feature) \
+                       ( psDevInfo->sDevFeatureCfg.ui32FeaturesValues[RGX_FEATURE_##Feature##_IDX] )
+
+/* This is used to check if the feature value (e.g. with an integer value) is available for the currently running BVNC or not */
+#define RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, Feature) \
+                       ( psDevInfo->sDevFeatureCfg.ui32FeaturesValues[RGX_FEATURE_##Feature##_IDX] < RGX_FEATURE_VALUE_DISABLED )
+
+/* This is used to check if the Boolean feature (e.g. WITHOUT an integer value) is available for the currently running BVNC or not */
+#define RGX_IS_FEATURE_SUPPORTED(psDevInfo, Feature) \
+                       BITMASK_HAS(psDevInfo->sDevFeatureCfg.ui64Features, RGX_FEATURE_##Feature##_BIT_MASK)
+
+/* This is used to check if the ERN is available for the currently running BVNC or not */
+#define RGX_IS_ERN_SUPPORTED(psDevInfo, ERN) \
+                       BITMASK_HAS(psDevInfo->sDevFeatureCfg.ui64ErnsBrns, HW_ERN_##ERN##_BIT_MASK)
+
+/* This is used to check if the BRN is available for the currently running BVNC or not */
+#define RGX_IS_BRN_SUPPORTED(psDevInfo, BRN) \
+                       BITMASK_HAS(psDevInfo->sDevFeatureCfg.ui64ErnsBrns, FIX_HW_BRN_##BRN##_BIT_MASK)
+
+/* there is a corresponding define in rgxapi.h */
+#define RGX_MAX_TIMER_QUERIES 16U
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+/*!
+ * The host maintains a 512-deep cache of submitted workloads per device,
+ * i.e. a global look-up table for TA, 3D and compute (depending on the RGX
+ * hardware support present)
+ */
+
+/*
+ * For the workload estimation return data array, the max amount of commands the
+ * MTS can have is 255, therefore 512 (LOG2 = 9) is large enough to account for
+ * all corner cases
+ */
+#define RETURN_DATA_ARRAY_SIZE_LOG2 (9)
+#define RETURN_DATA_ARRAY_SIZE      ((1U) << RETURN_DATA_ARRAY_SIZE_LOG2)
+#define RETURN_DATA_ARRAY_WRAP_MASK (RETURN_DATA_ARRAY_SIZE - 1)
+
+#define WORKLOAD_HASH_SIZE_LOG2                6
+#define WORKLOAD_HASH_SIZE                     ((1U) << WORKLOAD_HASH_SIZE_LOG2)
+#define WORKLOAD_HASH_WRAP_MASK                (WORKLOAD_HASH_SIZE - 1)
+
+/*!
+ * Workload characteristics for supported data masters.
+ * All characteristics must match for the workload estimate to be used/updated.
+ */
+typedef union _RGX_WORKLOAD_
+{
+       struct
+       {
+               IMG_UINT32                              ui32RenderTargetSize;
+               IMG_UINT32                              ui32NumberOfDrawCalls;
+               IMG_UINT32                              ui32NumberOfIndices;
+               IMG_UINT32                              ui32NumberOfMRTs;
+       } sTA3D;
+
+       struct
+       {
+               IMG_UINT32                              ui32NumberOfWorkgroups;
+               IMG_UINT32                              ui32NumberOfWorkitems;
+       } sCompute;
+
+       struct
+       {
+               IMG_UINT32                              ui32Characteristic1;
+               IMG_UINT32                              ui32Characteristic2;
+       } sTransfer;
+} RGX_WORKLOAD;
+
+/*!
+ * Host data used to match the return data (actual cycles count) to the
+ * submitted command packet.
+ * The hash table is a per-DM circular buffer containing a key based on the
+ * workload characteristics. On job completion, the oldest workload data
+ * is evicted if the CB is full and the driver matches the characteristics
+ * to the matching data.
+ *
+ * o If the driver finds a match the existing cycle estimate is averaged with
+ *   the actual cycles used.
+ * o Otherwise a new hash entry is created with the actual cycles for this
+ *   workload.
+ *
+ * Subsequently if a match is found during command submission, the estimate
+ * is passed to the scheduler, e.g. adjust the GPU frequency if PDVFS is enabled.
+ */
+typedef struct _WORKLOAD_MATCHING_DATA_
+{
+       POS_LOCK                                psHashLock;
+       HASH_TABLE                              *psHashTable;           /*! existing workload cycle estimates for this DM */
+       RGX_WORKLOAD                    asHashKeys[WORKLOAD_HASH_SIZE];
+       IMG_UINT64                              aui64HashData[WORKLOAD_HASH_SIZE];
+       IMG_UINT32                              ui32HashArrayWO;        /*! track the most recent workload estimates */
+} WORKLOAD_MATCHING_DATA;
+
+/*!
+ * A generic container for the workload matching data for GPU contexts:
+ * rendering (TA, 3D), compute, etc.
+ */
+typedef struct _WORKEST_HOST_DATA_
+{
+       union
+       {
+               struct
+               {
+                       WORKLOAD_MATCHING_DATA  sDataTA;        /*!< matching data for TA commands */
+                       WORKLOAD_MATCHING_DATA  sData3D;        /*!< matching data for 3D commands */
+               } sTA3D;
+
+               struct
+               {
+                       WORKLOAD_MATCHING_DATA  sDataCDM;       /*!< matching data for CDM commands */
+               } sCompute;
+
+               struct
+               {
+                       WORKLOAD_MATCHING_DATA  sDataTDM;       /*!< matching data for TDM-TQ commands */
+               } sTransfer;
+       } uWorkloadMatchingData;
+
+       /*
+        * This is a per-context property, hence the TA and 3D share the same
+        * per render context counter.
+        */
+       IMG_UINT32                              ui32WorkEstCCBReceived; /*!< Used to ensure all submitted work
+                                                                                                                estimation commands are received
+                                                                                                                by the host before clean up. */
+} WORKEST_HOST_DATA;
+
+/*!
+ * Entries in the list of submitted workloads, used when the completed command
+ * returns data to the host.
+ *
+ * - the matching data is needed as it holds the hash data
+ * - the host data is needed for completion updates, ensuring memory is not
+ *   freed while workload estimates are in-flight.
+ * - the workload characteristic is used in the hash table look-up.
+ */
+typedef struct _WORKEST_RETURN_DATA_
+{
+       WORKEST_HOST_DATA               *psWorkEstHostData;
+       WORKLOAD_MATCHING_DATA  *psWorkloadMatchingData;
+       RGX_WORKLOAD                    sWorkloadCharacteristics;
+} WORKEST_RETURN_DATA;
+#endif
+
+
+#define RGX_MAX_NUM_MMU_PAGE_SIZE_RANGES    4
+
+
+/*!
+ ******************************************************************************
+ * RGX Device error counts
+ *****************************************************************************/
+typedef struct _PVRSRV_RGXDEV_ERROR_COUNTS_
+{
+       IMG_UINT32 ui32WGPErrorCount;           /*!< count of the number of WGP checksum errors */
+       IMG_UINT32 ui32TRPErrorCount;           /*!< count of the number of TRP checksum errors */
+} PVRSRV_RGXDEV_ERROR_COUNTS;
+
+/*!
+ ******************************************************************************
+ * RGX Device info
+ *****************************************************************************/
+typedef struct _PVRSRV_RGXDEV_INFO_
+{
+       PVRSRV_DEVICE_NODE              *psDeviceNode;
+
+       PVRSRV_DEVICE_FEATURE_CONFIG    sDevFeatureCfg;
+
+       IMG_BOOL                                bDevInit2Done;
+
+       IMG_BOOL                                bFirmwareInitialised;
+       IMG_BOOL                                bPDPEnabled;
+
+       IMG_HANDLE                              hDbgReqNotify;
+
+       /* Kernel mode linear address of device registers */
+       void __iomem                    *pvRegsBaseKM;
+
+       IMG_HANDLE                              hRegMapping;
+
+       /* System physical address of device registers */
+       IMG_CPU_PHYADDR                 sRegsPhysBase;
+       /* Register region size in bytes */
+       IMG_UINT32                              ui32RegSize;
+
+       PVRSRV_STUB_PBDESC              *psStubPBDescListKM;
+
+       /* Firmware memory context info */
+       DEVMEM_CONTEXT                  *psKernelDevmemCtx;
+       DEVMEM_HEAP                             *psFirmwareMainHeap;
+       DEVMEM_HEAP                             *psFirmwareConfigHeap;
+       MMU_CONTEXT                             *psKernelMMUCtx;
+
+       void                                    *pvDeviceMemoryHeap;
+
+       /* Kernel CCB */
+       DEVMEM_MEMDESC                  *psKernelCCBCtlMemDesc;      /*!< memdesc for Kernel CCB control */
+       RGXFWIF_CCB_CTL                 *psKernelCCBCtl;             /*!< kernel mapping for Kernel CCB control */
+       DEVMEM_MEMDESC                  *psKernelCCBMemDesc;         /*!< memdesc for Kernel CCB */
+       IMG_UINT8                               *psKernelCCB;                /*!< kernel mapping for Kernel CCB */
+       DEVMEM_MEMDESC                  *psKernelCCBRtnSlotsMemDesc; /*!< Return slot array for Kernel CCB commands */
+       IMG_UINT32                              *pui32KernelCCBRtnSlots;     /*!< kernel mapping for return slot array */
+
+       /* Firmware CCB */
+       DEVMEM_MEMDESC                  *psFirmwareCCBCtlMemDesc;   /*!< memdesc for Firmware CCB control */
+       RGXFWIF_CCB_CTL                 *psFirmwareCCBCtl;          /*!< kernel mapping for Firmware CCB control */
+       DEVMEM_MEMDESC                  *psFirmwareCCBMemDesc;      /*!< memdesc for Firmware CCB */
+       IMG_UINT8                               *psFirmwareCCB;             /*!< kernel mapping for Firmware CCB */
+
+       /* Workload Estimation Firmware CCB */
+       DEVMEM_MEMDESC                  *psWorkEstFirmwareCCBCtlMemDesc;   /*!< memdesc for Workload Estimation Firmware CCB control */
+       RGXFWIF_CCB_CTL                 *psWorkEstFirmwareCCBCtl;          /*!< kernel mapping for Workload Estimation Firmware CCB control */
+       DEVMEM_MEMDESC                  *psWorkEstFirmwareCCBMemDesc;      /*!< memdesc for Workload Estimation Firmware CCB */
+       IMG_UINT8                               *psWorkEstFirmwareCCB;             /*!< kernel mapping for Workload Estimation Firmware CCB */
+
+       PVRSRV_MEMALLOCFLAGS_T  uiFWPoisonOnFreeFlag;           /*!< Flag for poisoning FW allocations when freed */
+
+       IMG_BOOL                                bIgnoreHWReportedBVNC;                  /*!< Ignore BVNC reported by HW */
+
+       /*
+               if we don't preallocate the pagetables we must
+               insert newly allocated page tables dynamically
+       */
+       void                                    *pvMMUContextList;
+
+       IMG_UINT32                              ui32ClkGateStatusReg;
+       IMG_UINT32                              ui32ClkGateStatusMask;
+
+       DEVMEM_MEMDESC                  *psRGXFWCodeMemDesc;
+       IMG_DEV_VIRTADDR                sFWCodeDevVAddrBase;
+       IMG_UINT32                      ui32FWCodeSizeInBytes;
+       DEVMEM_MEMDESC                  *psRGXFWDataMemDesc;
+       IMG_DEV_VIRTADDR                sFWDataDevVAddrBase;
+
+       DEVMEM_MEMDESC                  *psRGXFWCorememCodeMemDesc;
+       IMG_DEV_VIRTADDR                sFWCorememCodeDevVAddrBase;
+       RGXFWIF_DEV_VIRTADDR            sFWCorememCodeFWAddr;
+       IMG_UINT32                      ui32FWCorememCodeSizeInBytes;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfCorememDataStoreMemDesc;
+       IMG_DEV_VIRTADDR                sFWCorememDataStoreDevVAddrBase;
+       RGXFWIF_DEV_VIRTADDR            sFWCorememDataStoreFWAddr;
+
+       DEVMEM_MEMDESC                  *psRGXFWAlignChecksMemDesc;
+
+#if defined(PDUMP)
+       DEVMEM_MEMDESC                  *psRGXFWSigTAChecksMemDesc;
+       IMG_UINT32                              ui32SigTAChecksSize;
+
+       DEVMEM_MEMDESC                  *psRGXFWSig3DChecksMemDesc;
+       IMG_UINT32                              ui32Sig3DChecksSize;
+
+       DEVMEM_MEMDESC                  *psRGXFWSigCDMChecksMemDesc;
+       IMG_UINT32                              ui32SigCDMChecksSize;
+
+       DEVMEM_MEMDESC                  *psRGXFWSigTDMChecksMemDesc;
+       IMG_UINT32                              ui32SigTDMChecksSize;
+
+       DEVMEM_MEMDESC                  *psRGXFWSigRDMChecksMemDesc;
+       IMG_UINT32                              ui32SigRDMChecksSize;
+
+
+#if defined(SUPPORT_VALIDATION)
+       DEVMEM_MEMDESC                  *psRGXFWValidationSigMemDesc;
+       IMG_UINT32                              ui32ValidationSigSize;
+#endif
+
+       IMG_BOOL                                bDumpedKCCBCtlAlready;
+
+       POS_SPINLOCK                    hSyncCheckpointSignalSpinLock;                                          /*!< Guards data shared between an atomic & sleepable-context */
+#endif
+
+       POS_LOCK                                hRGXFWIfBufInitLock;                                                            /*!< trace buffer lock for initialisation phase */
+
+       DEVMEM_MEMDESC                  *psRGXFWIfTraceBufCtlMemDesc;                                           /*!< memdesc of trace buffer control structure */
+       DEVMEM_MEMDESC                  *psRGXFWIfTraceBufferMemDesc[RGXFW_THREAD_NUM];         /*!< memdesc of actual FW trace (log) buffer(s) */
+       DEVMEM_MEMDESC                  *psRGXFWIfPowMonBufferMemDesc;                                          /*!< memdesc of FW power monitoring data */
+       RGXFWIF_TRACEBUF                *psRGXFWIfTraceBufCtl;                                                          /*!< structure containing trace control data and actual trace buffer */
+
+       DEVMEM_MEMDESC                  *psRGXFWIfFwSysDataMemDesc;                                                     /*!< memdesc of the firmware-shared system data structure */
+       RGXFWIF_SYSDATA                 *psRGXFWIfFwSysData;                                                            /*!< structure containing trace control data and actual trace buffer */
+
+       DEVMEM_MEMDESC                  *psRGXFWIfFwOsDataMemDesc;                                                      /*!< memdesc of the firmware-shared os structure */
+       RGXFWIF_OSDATA                  *psRGXFWIfFwOsData;                                                                     /*!< structure containing trace control data and actual trace buffer */
+
+#if defined(SUPPORT_TBI_INTERFACE)
+       DEVMEM_MEMDESC                  *psRGXFWIfTBIBufferMemDesc;                                                     /*!< memdesc of actual FW TBI buffer */
+       RGXFWIF_DEV_VIRTADDR    sRGXFWIfTBIBuffer;                                                                      /*!< TBI buffer data */
+       IMG_UINT32                              ui32FWIfTBIBufferSize;
+#endif
+
+       DEVMEM_MEMDESC                  *psRGXFWIfHWRInfoBufCtlMemDesc;
+       RGXFWIF_HWRINFOBUF              *psRGXFWIfHWRInfoBufCtl;
+       IMG_UINT32                              ui32ClockSource;
+       IMG_UINT32                              ui32LastClockSource;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfGpuUtilFWCbCtlMemDesc;
+       RGXFWIF_GPU_UTIL_FWCB   *psRGXFWIfGpuUtilFWCb;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfHWPerfBufMemDesc;
+       IMG_BYTE                                *psRGXFWIfHWPerfBuf;
+       IMG_UINT32                              ui32RGXFWIfHWPerfBufSize; /* in bytes */
+
+       DEVMEM_MEMDESC                  *psRGXFWIfRegCfgMemDesc;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfHWPerfCountersMemDesc;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfConnectionCtlMemDesc;
+       RGXFWIF_CONNECTION_CTL  *psRGXFWIfConnectionCtl;
+
+       DEVMEM_MEMDESC                  *psRGXFWHeapGuardPageReserveMemDesc;
+       DEVMEM_MEMDESC                  *psRGXFWIfSysInitMemDesc;
+       RGXFWIF_SYSINIT                 *psRGXFWIfSysInit;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfOsInitMemDesc;
+       RGXFWIF_OSINIT                  *psRGXFWIfOsInit;
+
+       DEVMEM_MEMDESC                  *psRGXFWIfRuntimeCfgMemDesc;
+       RGXFWIF_RUNTIME_CFG             *psRGXFWIfRuntimeCfg;
+
+       /* Additional guest firmware memory context info */
+       DEVMEM_HEAP                             *psGuestFirmwareRawHeap[RGX_NUM_OS_SUPPORTED];
+       DEVMEM_MEMDESC                  *psGuestFirmwareRawMemDesc[RGX_NUM_OS_SUPPORTED];
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Array to store data needed for workload estimation when a workload
+          has finished and its cycle time is returned to the host.      */
+       WORKEST_RETURN_DATA     asReturnData[RETURN_DATA_ARRAY_SIZE];
+       IMG_UINT32              ui32ReturnDataWO;
+       POS_LOCK                hWorkEstLock;
+#endif
+
+#if defined(SUPPORT_PDVFS)
+       /**
+        * Host memdesc and pointer to memory containing core clock rate in Hz.
+        * Firmware (PDVFS) updates the memory on changing the core clock rate over
+        * GPIO.
+        * Note: Shared memory needs atomic access from Host driver and firmware,
+        * hence size should not be greater than memory transaction granularity.
+        * Currently it is chosen to be 32 bits.
+        */
+       DEVMEM_MEMDESC                  *psRGXFWIFCoreClkRateMemDesc;
+       volatile IMG_UINT32             *pui32RGXFWIFCoreClkRate;
+       /**
+        * Last sampled core clk rate.
+        */
+       volatile IMG_UINT32             ui32CoreClkRateSnapshot;
+#endif
+
+       /*
+          HWPerf data for the RGX device
+        */
+
+       POS_LOCK    hHWPerfLock;  /*! Critical section lock that protects HWPerf code
+                                  *  from multiple thread duplicate init/deinit
+                                  *  and loss/freeing of FW & Host resources while in
+                                  *  use in another thread e.g. MSIR. */
+
+       IMG_UINT64  ui64HWPerfFilter; /*! Event filter for FW events (settable by AppHint) */
+       IMG_HANDLE  hHWPerfStream;    /*! TL Stream buffer (L2) for firmware event stream */
+       IMG_UINT32  ui32L2BufMaxPacketSize;/*!< Max allowed packet size in FW HWPerf TL (L2) buffer */
+       IMG_BOOL    bSuspendHWPerfL2DataCopy;  /*! Flag to indicate if copying HWPerf data is suspended */
+
+       IMG_UINT32  ui32HWPerfHostFilter;      /*! Event filter for HWPerfHost stream (settable by AppHint) */
+       POS_LOCK    hLockHWPerfHostStream;     /*! Lock guarding access to HWPerfHost stream from multiple threads */
+       IMG_HANDLE  hHWPerfHostStream;         /*! TL Stream buffer for host only event stream */
+       IMG_UINT32  ui32HWPerfHostBufSize;     /*! Host side buffer size in bytes */
+       IMG_UINT32  ui32HWPerfHostLastOrdinal; /*! Ordinal of the last packet emitted in HWPerfHost TL stream.
+                                               *  Guarded by hLockHWPerfHostStream */
+       IMG_UINT32  ui32HWPerfHostNextOrdinal; /*! Ordinal number for HWPerfHost events. Guarded by hHWPerfHostSpinLock */
+       IMG_UINT8   *pui8DeferredEvents;       /*! List of HWPerfHost events yet to be emitted in the TL stream.
+                                               *  Events generated from atomic context are deferred "emitted"
+                                                                                       *  as the "emission" code can sleep */
+       IMG_UINT16  ui16DEReadIdx;             /*! Read index in the above deferred events buffer */
+       IMG_UINT16  ui16DEWriteIdx;            /*! Write index in the above deferred events buffer */
+       void        *pvHostHWPerfMISR;         /*! MISR to emit pending/deferred events in HWPerfHost TL stream */
+       POS_SPINLOCK hHWPerfHostSpinLock;      /*! Guards data shared between an atomic & sleepable-context */
+#if defined(PVRSRV_HWPERF_HOST_DEBUG_DEFERRED_EVENTS)
+       IMG_UINT32  ui32DEHighWatermark;       /*! High watermark of deferred events buffer usage. Protected by
+                                               *! hHWPerfHostSpinLock */
+       /* Max number of times DeferredEmission waited for an atomic-context to "finish" packet write */
+       IMG_UINT32  ui32WaitForAtomicCtxPktHighWatermark; /*! Protected by hLockHWPerfHostStream */
+       /* Whether warning has been logged about an atomic-context packet loss (due to too long wait for "write" finish) */
+       IMG_BOOL    bWarnedAtomicCtxPktLost;
+       /* Max number of times DeferredEmission scheduled-out to give a chance to the right-ordinal packet to be emitted */
+       IMG_UINT32  ui32WaitForRightOrdPktHighWatermark; /*! Protected by hLockHWPerfHostStream */
+       /* Whether warning has been logged about an packet loss (due to too long wait for right ordinal to emit) */
+       IMG_BOOL    bWarnedPktOrdinalBroke;
+#endif
+
+       void        *pvGpuFtraceData;
+
+       /* Poll data for detecting firmware fatal errors */
+       IMG_UINT32                              aui32CrLastPollCount[RGXFW_THREAD_NUM];
+       IMG_UINT32                              ui32KCCBCmdsExecutedLastTime;
+       IMG_BOOL                                bKCCBCmdsWaitingLastTime;
+       IMG_UINT32                              ui32GEOTimeoutsLastTime;
+       IMG_UINT32                              ui32InterruptCountLastTime;
+       IMG_UINT32                              ui32MissingInterruptsLastTime;
+
+       /* Client stall detection */
+       IMG_UINT32                              ui32StalledClientMask;
+
+       IMG_BOOL                                bWorkEstEnabled;
+       IMG_BOOL                                bPDVFSEnabled;
+
+       void                                    *pvLISRData;
+       void                                    *pvMISRData;
+       void                                    *pvAPMISRData;
+       RGX_ACTIVEPM_CONF               eActivePMConf;
+
+       volatile IMG_UINT32             aui32SampleIRQCount[RGXFW_THREAD_NUM];
+
+       DEVMEM_MEMDESC                  *psRGXFaultAddressMemDesc;
+
+       DEVMEM_MEMDESC                  *psSLC3FenceMemDesc;
+
+       /* If we do 10 deferred memory allocations per second, then the ID would wrap around after 13 years */
+       IMG_UINT32                              ui32ZSBufferCurrID;     /*!< ID assigned to the next deferred devmem allocation */
+       IMG_UINT32                              ui32FreelistCurrID;     /*!< ID assigned to the next freelist */
+
+       POS_LOCK                                hLockZSBuffer;          /*!< Lock to protect simultaneous access to ZSBuffers */
+       DLLIST_NODE                             sZSBufferHead;          /*!< List of on-demand ZSBuffers */
+       POS_LOCK                                hLockFreeList;          /*!< Lock to protect simultaneous access to Freelists */
+       DLLIST_NODE                             sFreeListHead;          /*!< List of growable Freelists */
+       PSYNC_PRIM_CONTEXT              hSyncPrimContext;
+       PVRSRV_CLIENT_SYNC_PRIM *psPowSyncPrim;
+
+       IMG_UINT32                              ui32ActivePMReqOk;
+       IMG_UINT32                              ui32ActivePMReqDenied;
+       IMG_UINT32                              ui32ActivePMReqNonIdle;
+       IMG_UINT32                              ui32ActivePMReqRetry;
+       IMG_UINT32                              ui32ActivePMReqTotal;
+
+       IMG_HANDLE                              hProcessQueuesMISR;
+
+       IMG_UINT32                              ui32DeviceFlags;                /*!< Flags to track general device state */
+
+       /* GPU DVFS Table */
+       RGX_GPU_DVFS_TABLE              *psGpuDVFSTable;
+
+       /* Pointer to function returning the GPU utilisation statistics since the last
+        * time the function was called. Supports different users at the same time.
+        *
+        * psReturnStats [out]: GPU utilisation statistics (active high/active low/idle/blocked)
+        *                      in microseconds since the last time the function was called
+        *                      by a specific user (identified by hGpuUtilUser)
+        *
+        * Returns PVRSRV_OK in case the call completed without errors,
+        * some other value otherwise.
+        */
+       PVRSRV_ERROR (*pfnGetGpuUtilStats) (PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           IMG_HANDLE hGpuUtilUser,
+                                           RGXFWIF_GPU_UTIL_STATS *psReturnStats);
+
+       /* Pointer to function that checks if the physical GPU IRQ
+        * line has been asserted and clears it if so */
+       IMG_BOOL (*pfnRGXAckIrq) (struct _PVRSRV_RGXDEV_INFO_ *psDevInfo);
+
+       POS_LOCK                                hGPUUtilLock;
+
+       /* Register configuration */
+       RGX_REG_CONFIG                  sRegCongfig;
+
+       IMG_BOOL                                bRGXPowered;
+       DLLIST_NODE                             sMemoryContextList;
+
+       POSWR_LOCK                              hRenderCtxListLock;
+       POSWR_LOCK                              hComputeCtxListLock;
+       POSWR_LOCK                              hTransferCtxListLock;
+       POSWR_LOCK                              hTDMCtxListLock;
+       POSWR_LOCK                              hMemoryCtxListLock;
+       POSWR_LOCK                              hKickSyncCtxListLock;
+
+       /* Linked list of deferred KCCB commands due to a full KCCB.
+        * Access to members sKCCBDeferredCommandsListHead and ui32KCCBDeferredCommandsCount
+        * are protected by the hLockKCCBDeferredCommandsList spin lock. */
+       POS_SPINLOCK                    hLockKCCBDeferredCommandsList; /*!< Protects deferred KCCB commands list */
+       DLLIST_NODE                             sKCCBDeferredCommandsListHead;
+       IMG_UINT32                              ui32KCCBDeferredCommandsCount; /*!< No of commands in the deferred list */
+
+       /* Linked lists of contexts on this device */
+       DLLIST_NODE                             sRenderCtxtListHead;
+       DLLIST_NODE                             sComputeCtxtListHead;
+       DLLIST_NODE                             sTDMCtxtListHead;
+       DLLIST_NODE                             sKickSyncCtxtListHead;
+
+       DLLIST_NODE                             sCommonCtxtListHead;
+       POSWR_LOCK                              hCommonCtxtListLock;
+       IMG_UINT32                              ui32CommonCtxtCurrentID;        /*!< ID assigned to the next common context */
+
+       POS_LOCK                                hDebugFaultInfoLock;    /*!< Lock to protect the debug fault info list */
+       POS_LOCK                                hMMUCtxUnregLock;               /*!< Lock to protect list of unregistered MMU contexts */
+
+#if defined(SUPPORT_VALIDATION)
+       RGX_POWER_DOMAIN_STATE  sPowerDomainState;              /*!< Power island sequence */
+       IMG_UINT32                              ui32PowDomainKickInterval;      /*!< Power island transition interval */
+       IMG_UINT32                              ui32ValidationFlags;    /*!< Validation flags for host driver */
+#endif
+       IMG_UINT32                              ui32AvailablePowUnitsMask;
+       IMG_UINT32                              ui32AvailableRACMask;
+
+       RGX_LAYER_PARAMS                sLayerParams;
+
+       RGXFWIF_DM                              eBPDM;                                  /*!< Current breakpoint data master */
+       IMG_BOOL                                bBPSet;                                 /*!< A Breakpoint has been set */
+       POS_LOCK                                hBPLock;                                /*!< Lock for break point operations */
+
+       IMG_UINT32                              ui32CoherencyTestsDone;
+
+       ATOMIC_T                                iCCBSubmissionOrdinal; /* Rolling count used to indicate CCB submission order (all CCBs) */
+       POS_LOCK                                hCCBRecoveryLock;      /* Lock to protect pvEarliestStalledClientCCB and ui32OldestSubmissionOrdinal variables */
+       void                                    *pvEarliestStalledClientCCB; /* Will point to cCCB command to unblock in the event of a stall */
+       IMG_UINT32                              ui32OldestSubmissionOrdinal; /* Earliest submission ordinal of CCB entry found so far */
+       IMG_UINT32                              ui32SLRHoldoffCounter;   /* Decremented each time health check is called until zero. SLR only happen when zero. */
+
+       POS_LOCK                                hCCBStallCheckLock; /* Lock used to guard against multiple threads simultaneously checking for stalled CCBs */
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+       /* Firmware gcov buffer */
+       DEVMEM_MEMDESC                  *psFirmwareGcovBufferMemDesc;      /*!< mem desc for Firmware gcov dumping buffer */
+       IMG_UINT32                              ui32FirmwareGcovSize;
+#endif
+       /* Value to store for each page size range config register in MMU4 */
+       IMG_UINT64                              aui64MMUPageSizeRangeValue[RGX_MAX_NUM_MMU_PAGE_SIZE_RANGES];
+
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+       struct
+       {
+               IMG_UINT64 ui64timerGray;
+               IMG_UINT64 ui64timerBinary;
+               IMG_UINT64 *pui64uscTimers;
+       } sRGXTimerValues;
+#endif
+
+#if defined(SUPPORT_VALIDATION)
+       struct
+       {
+               IMG_UINT64 ui64RegVal;
+               struct completion sRegComp;
+       } sFwRegs;
+#endif
+
+       IMG_HANDLE                              hTQCLISharedMem;                /*!< TQ Client Shared Mem PMR */
+       IMG_HANDLE                              hTQUSCSharedMem;                /*!< TQ USC Shared Mem PMR */
+
+#if defined(SUPPORT_VALIDATION)
+       IMG_UINT32                              ui32TestSLRInterval; /* Don't enqueue an update sync checkpoint every nth kick */
+       IMG_UINT32                              ui32TestSLRCount;    /* (used to test SLR operation) */
+       IMG_UINT32                              ui32SLRSkipFWAddr;
+#endif
+
+#if defined(SUPPORT_SECURITY_VALIDATION)
+       DEVMEM_MEMDESC                  *psRGXFWIfSecureBufMemDesc;
+       DEVMEM_MEMDESC                  *psRGXFWIfNonSecureBufMemDesc;
+#endif
+
+       /* Timer Queries */
+       IMG_UINT32                              ui32ActiveQueryId;              /*!< id of the active line */
+       IMG_BOOL                                bSaveStart;                             /*!< save the start time of the next kick on the device*/
+       IMG_BOOL                                bSaveEnd;                               /*!< save the end time of the next kick on the device*/
+
+       DEVMEM_MEMDESC                  *psStartTimeMemDesc;    /*!< memdesc for Start Times */
+       IMG_UINT64                              *pui64StartTimeById;    /*!< CPU mapping of the above */
+
+       DEVMEM_MEMDESC                  *psEndTimeMemDesc;      /*!< memdesc for End Timer */
+       IMG_UINT64                              *pui64EndTimeById;      /*!< CPU mapping of the above */
+
+       IMG_UINT32                              aui32ScheduledOnId[RGX_MAX_TIMER_QUERIES];      /*!< kicks Scheduled on QueryId */
+       DEVMEM_MEMDESC                  *psCompletedMemDesc;    /*!< kicks Completed on QueryId */
+       IMG_UINT32                              *pui32CompletedById;    /*!< CPU mapping of the above */
+
+#if !defined(PVRSRV_USE_BRIDGE_LOCK)
+       POS_LOCK                                hTimerQueryLock;                /*!< lock to protect simultaneous access to timer query members */
+#endif
+
+       PVRSRV_RGXDEV_ERROR_COUNTS sErrorCounts;                /*!< struct containing device error counts */
+
+       IMG_UINT32                              ui32HostSafetyEventMask;/*!< mask of the safety events handled by the driver */
+
+       RGX_CONTEXT_RESET_REASON        eLastDeviceError;       /*!< device error reported to client */
+
+       IMG_UINT32              ui32Log2Non4KPgSize; /* Page size of Non4k heap in log2 form */
+} PVRSRV_RGXDEV_INFO;
+
+
+
+typedef struct _RGX_TIMING_INFORMATION_
+{
+       /*! GPU default core clock speed in Hz */
+       IMG_UINT32                      ui32CoreClockSpeed;
+
+       /*! Active Power Management: GPU actively requests the host driver to be powered off */
+       IMG_BOOL                        bEnableActivePM;
+
+       /*! Enable the GPU to power off internal Power Islands independently from the host driver */
+       IMG_BOOL                        bEnableRDPowIsland;
+
+       /*! Active Power Management: Delay between the GPU idle and the request to the host */
+       IMG_UINT32                      ui32ActivePMLatencyms;
+
+} RGX_TIMING_INFORMATION;
+
+typedef struct _RGX_DATA_
+{
+       /*! Timing information */
+       RGX_TIMING_INFORMATION  *psRGXTimingInfo;
+} RGX_DATA;
+
+
+/*
+       RGX PDUMP register bank name (prefix)
+*/
+#define RGX_PDUMPREG_NAME              "RGXREG"
+
+#endif /* RGXDEVICE_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.c
new file mode 100644 (file)
index 0000000..935e6ea
--- /dev/null
@@ -0,0 +1,8160 @@
+/*************************************************************************/ /*!
+@File
+@Title          Rogue firmware utility routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Rogue firmware utility routines
+@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(__linux__)
+#include <linux/stddef.h>
+#else
+#include <stddef.h>
+#endif
+
+#include "img_defs.h"
+
+#include "rgxdefs_km.h"
+#include "rgx_fwif_km.h"
+#include "pdump_km.h"
+#include "osfunc.h"
+#if defined(__linux__)
+#include "km_apphint.h"
+#endif
+#include "cache_km.h"
+#include "allocmem.h"
+#include "physheap.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "devicemem_server.h"
+
+#include "pvr_debug.h"
+#include "pvr_notifier.h"
+#include "rgxfwutils.h"
+#include "rgx_options.h"
+#include "rgx_fwif_alignchecks.h"
+#include "rgx_fwif_resetframework.h"
+#include "rgx_pdump_panics.h"
+#include "fwtrace_string.h"
+#include "rgxheapconfig.h"
+#include "pvrsrv.h"
+#include "rgxdebug.h"
+#include "rgxhwperf.h"
+#include "rgxccb.h"
+#include "rgxcompute.h"
+#include "rgxtdmtransfer.h"
+#include "rgxpower.h"
+#if defined(SUPPORT_DISPLAY_CLASS)
+#include "dc_server.h"
+#endif
+#include "rgxmem.h"
+#include "rgxmmudefs_km.h"
+#include "rgxta3d.h"
+#include "rgxkicksync.h"
+#include "rgxutils.h"
+#include "rgxtimecorr.h"
+#include "rgxfwimageutils.h"
+#include "sync_internal.h"
+#include "sync.h"
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_external.h"
+#include "tlstream.h"
+#include "devicemem_server_utils.h"
+#include "htbuffer.h"
+#include "info_page.h"
+
+#include "physmem_lma.h"
+#include "physmem_osmem.h"
+#include "oskm_apphint.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>      /* sprintf */
+#include "rogue_trace_events.h"
+#else
+#include <stdio.h>
+#endif
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+#include "rgxsoctimer.h"
+#endif
+
+#include "vz_vmm_pvz.h"
+#include "rgx_heaps.h"
+
+/*!
+ ******************************************************************************
+ * HWPERF
+ *****************************************************************************/
+/* Size of the Firmware L1 HWPERF buffer in bytes (2MB). Accessed by the
+ * Firmware and host driver. */
+#define RGXFW_HWPERF_L1_SIZE_MIN        (16U)
+#define RGXFW_HWPERF_L1_SIZE_DEFAULT    PVRSRV_APPHINT_HWPERFFWBUFSIZEINKB
+#define RGXFW_HWPERF_L1_SIZE_MAX        (12288U)
+#if defined(DEBUG)
+/* Catch the use of auto-increment when meta_registers_unpacked_accesses feature is
+ * present in case we ever use it. No WA exists so it must not be used */
+#define CHECK_HWBRN_68777(v) \
+       do { \
+               PVR_ASSERT(((v) & RGX_CR_META_SP_MSLVCTRL0_AUTOINCR_EN) == 0); \
+       } while (0)
+#else
+#define CHECK_HWBRN_68777(v)
+#endif
+
+/* Firmware CCB length */
+#if defined(NO_HARDWARE) && defined(PDUMP)
+#define RGXFWIF_FWCCB_NUMCMDS_LOG2   (10)
+#elif defined(SUPPORT_PDVFS) || defined(SUPPORT_WORKLOAD_ESTIMATION)
+#define RGXFWIF_FWCCB_NUMCMDS_LOG2   (8)
+#else
+#define RGXFWIF_FWCCB_NUMCMDS_LOG2   (5)
+#endif
+
+/*
+ * Maximum length of time a DM can run for before the DM will be marked
+ * as out-of-time. CDM has an increased value due to longer running kernels.
+ *
+ * These deadlines are increased on FPGA, EMU and VP due to the slower
+ * execution time of these platforms. PDUMPS are also included since they
+ * are often run on EMU, FPGA or in CSim.
+ */
+#if defined(FPGA) || defined(EMULATOR) || defined(VIRTUAL_PLATFORM) || defined(PDUMP)
+#define RGXFWIF_MAX_WORKLOAD_DEADLINE_MS     (480000)
+#define RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS (1000000)
+#else
+#define RGXFWIF_MAX_WORKLOAD_DEADLINE_MS     (30000)
+#define RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS (90000)
+#endif
+
+/* Workload Estimation Firmware CCB length */
+#define RGXFWIF_WORKEST_FWCCB_NUMCMDS_LOG2   (7)
+
+/* Size of memory buffer for firmware gcov data
+ * The actual data size is several hundred kilobytes. The buffer is an order of magnitude larger. */
+#define RGXFWIF_FIRMWARE_GCOV_BUFFER_SIZE (4*1024*1024)
+
+typedef struct
+{
+       RGXFWIF_KCCB_CMD        sKCCBcmd;
+       DLLIST_NODE             sListNode;
+       PDUMP_FLAGS_T           uiPDumpFlags;
+       PVRSRV_RGXDEV_INFO      *psDevInfo;
+} RGX_DEFERRED_KCCB_CMD;
+
+#if defined(PDUMP)
+/* ensure PIDs are 32-bit because a 32-bit PDump load is generated for the
+ * PID filter example entries
+ */
+static_assert(sizeof(IMG_PID) == sizeof(IMG_UINT32),
+               "FW PID filtering assumes the IMG_PID type is 32-bits wide as it "
+               "generates WRW commands for loading the PID values");
+#endif
+
+static void RGXFreeFwOsData(PVRSRV_RGXDEV_INFO *psDevInfo);
+static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+static PVRSRV_ERROR _AllocateSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo, RGXFWIF_SYSINIT* psFwSysInit)
+{
+       PVRSRV_ERROR eError;
+       DEVMEM_MEMDESC** ppsSLC3FenceMemDesc = &psDevInfo->psSLC3FenceMemDesc;
+       IMG_UINT32 ui32CacheLineSize = GET_ROGUE_CACHE_LINE_SIZE(
+                       RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS));
+
+       PVR_DPF_ENTERED;
+
+       eError = DevmemAllocate(psDevInfo->psFirmwareMainHeap,
+                       1,
+                       ui32CacheLineSize,
+                       PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                       PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                       PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                       "FwSLC3FenceWA",
+                       ppsSLC3FenceMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       /* We need to map it so the heap for this allocation is set */
+       eError = DevmemMapToDevice(*ppsSLC3FenceMemDesc,
+                                                          psDevInfo->psFirmwareMainHeap,
+                                                          &psFwSysInit->sSLC3FenceDevVAddr);
+       if (eError != PVRSRV_OK)
+       {
+               DevmemFree(*ppsSLC3FenceMemDesc);
+               *ppsSLC3FenceMemDesc = NULL;
+       }
+
+       PVR_DPF_RETURN_RC1(eError, *ppsSLC3FenceMemDesc);
+}
+
+static void _FreeSLC3Fence(PVRSRV_RGXDEV_INFO* psDevInfo)
+{
+       DEVMEM_MEMDESC* psSLC3FenceMemDesc = psDevInfo->psSLC3FenceMemDesc;
+
+       if (psSLC3FenceMemDesc)
+       {
+               DevmemReleaseDevVirtAddr(psSLC3FenceMemDesc);
+               DevmemFree(psSLC3FenceMemDesc);
+       }
+}
+
+static void __MTSScheduleWrite(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Value)
+{
+       /* ensure memory is flushed before kicking MTS */
+       OSWriteMemoryBarrier(NULL);
+
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_SCHEDULE, ui32Value);
+
+       /* ensure the MTS kick goes through before continuing */
+#if !defined(NO_HARDWARE)
+       OSWriteMemoryBarrier((IMG_BYTE*) psDevInfo->pvRegsBaseKM + RGX_CR_MTS_SCHEDULE);
+#else
+       OSWriteMemoryBarrier(NULL);
+#endif
+}
+
+/*************************************************************************/ /*!
+@Function       RGXSetupFwAllocation
+
+@Description    Sets a pointer in a firmware data structure.
+
+@Input          psDevInfo       Device Info struct
+@Input          uiAllocFlags    Flags determining type of memory allocation
+@Input          ui32Size        Size of memory allocation
+@Input          pszName         Allocation label
+@Input          ppsMemDesc      pointer to the allocation's memory descriptor
+@Input          psFwPtr         Address of the firmware pointer to set
+@Input          ppvCpuPtr       Address of the cpu pointer to set
+@Input          ui32DevVAFlags  Any combination of  RFW_FWADDR_*_FLAG
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSetupFwAllocation(PVRSRV_RGXDEV_INFO*  psDevInfo,
+                                                                 PVRSRV_MEMALLOCFLAGS_T uiAllocFlags,
+                                                                 IMG_UINT32           ui32Size,
+                                                                 const IMG_CHAR       *pszName,
+                                                                 DEVMEM_MEMDESC       **ppsMemDesc,
+                                                                 RGXFWIF_DEV_VIRTADDR *psFwPtr,
+                                                                 void                 **ppvCpuPtr,
+                                                                 IMG_UINT32           ui32DevVAFlags)
+{
+       PVRSRV_ERROR eError;
+#if defined(SUPPORT_AUTOVZ)
+       IMG_BOOL bClearByMemset;
+       if (PVRSRV_CHECK_ZERO_ON_ALLOC(uiAllocFlags))
+       {
+               /* Under AutoVz the ZERO_ON_ALLOC flag is avoided as it causes the memory to
+                * be allocated from a different PMR than an allocation without the flag.
+                * When the content of an allocation needs to be recovered from physical memory
+                * on a later driver reboot, the memory then cannot be zeroed but the allocation
+                * addresses must still match.
+                * If the memory requires clearing, perform a memset after the allocation. */
+               uiAllocFlags &= ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+               bClearByMemset = IMG_TRUE;
+       }
+       else
+       {
+               bClearByMemset = IMG_FALSE;
+       }
+#endif
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate %s", pszName);
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         ui32Size,
+                                                         uiAllocFlags,
+                                                         pszName,
+                                                         ppsMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to allocate %u bytes for %s (%u)",
+                                __func__,
+                                ui32Size,
+                                pszName,
+                                eError));
+               goto fail_alloc;
+       }
+
+       if (psFwPtr)
+       {
+               eError = RGXSetFirmwareAddress(psFwPtr, *ppsMemDesc, 0, ui32DevVAFlags);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to acquire firmware virtual address for %s (%u)",
+                                        __func__,
+                                        pszName,
+                                        eError));
+                       goto fail_fwaddr;
+               }
+       }
+
+#if defined(SUPPORT_AUTOVZ)
+       if ((bClearByMemset) || (ppvCpuPtr))
+#else
+       if (ppvCpuPtr)
+#endif
+       {
+               void *pvTempCpuPtr;
+
+               eError = DevmemAcquireCpuVirtAddr(*ppsMemDesc, &pvTempCpuPtr);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to acquire CPU virtual address for %s (%u)",
+                                       __func__,
+                                        pszName,
+                                       eError));
+                       goto fail_cpuva;
+               }
+
+#if defined(SUPPORT_AUTOVZ)
+               if (bClearByMemset)
+               {
+                       if (PVRSRV_CHECK_CPU_WRITE_COMBINE(uiAllocFlags))
+                       {
+                               OSCachedMemSetWMB(pvTempCpuPtr, 0, ui32Size);
+                       }
+                       else
+                       {
+                               OSDeviceMemSet(pvTempCpuPtr, 0, ui32Size);
+                       }
+               }
+               if (ppvCpuPtr)
+#endif
+               {
+                       *ppvCpuPtr = pvTempCpuPtr;
+               }
+#if defined(SUPPORT_AUTOVZ)
+               else
+               {
+                       DevmemReleaseCpuVirtAddr(*ppsMemDesc);
+                       pvTempCpuPtr = NULL;
+               }
+#endif
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE, "%s: %s set up at Fw VA 0x%x and CPU VA 0x%p with alloc flags 0x%" IMG_UINT64_FMTSPECX,
+                        __func__, pszName,
+                        (psFwPtr)   ? (psFwPtr->ui32Addr) : (0),
+                        (ppvCpuPtr) ? (*ppvCpuPtr)        : (NULL),
+                        uiAllocFlags));
+
+       return eError;
+
+fail_cpuva:
+       if (psFwPtr)
+       {
+               RGXUnsetFirmwareAddress(*ppsMemDesc);
+       }
+fail_fwaddr:
+       DevmemFree(*ppsMemDesc);
+fail_alloc:
+       return eError;
+}
+
+/*************************************************************************/ /*!
+@Function       GetHwPerfBufferSize
+
+@Description    Computes the effective size of the HW Perf Buffer
+@Input          ui32HWPerfFWBufSizeKB       Device Info struct
+@Return         HwPerfBufferSize
+*/ /**************************************************************************/
+static IMG_UINT32 GetHwPerfBufferSize(IMG_UINT32 ui32HWPerfFWBufSizeKB)
+{
+       IMG_UINT32 HwPerfBufferSize;
+
+       /* HWPerf: Determine the size of the FW buffer */
+       if (ui32HWPerfFWBufSizeKB == 0 ||
+                       ui32HWPerfFWBufSizeKB == RGXFW_HWPERF_L1_SIZE_DEFAULT)
+       {
+               /* Under pvrsrvctl 0 size implies AppHint not set or is set to zero,
+                * use default size from driver constant. Set it to the default
+                * size, no logging.
+                */
+               HwPerfBufferSize = RGXFW_HWPERF_L1_SIZE_DEFAULT<<10;
+       }
+       else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MAX))
+       {
+               /* Size specified as a AppHint but it is too big */
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: HWPerfFWBufSizeInKB value (%u) too big, using maximum (%u)",
+                               __func__,
+                               ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MAX));
+               HwPerfBufferSize = RGXFW_HWPERF_L1_SIZE_MAX<<10;
+       }
+       else if (ui32HWPerfFWBufSizeKB > (RGXFW_HWPERF_L1_SIZE_MIN))
+       {
+               /* Size specified as in AppHint HWPerfFWBufSizeInKB */
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: Using HWPerf FW buffer size of %u KB",
+                               __func__,
+                               ui32HWPerfFWBufSizeKB));
+               HwPerfBufferSize = ui32HWPerfFWBufSizeKB<<10;
+       }
+       else
+       {
+               /* Size specified as a AppHint but it is too small */
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: HWPerfFWBufSizeInKB value (%u) too small, using minimum (%u)",
+                               __func__,
+                               ui32HWPerfFWBufSizeKB, RGXFW_HWPERF_L1_SIZE_MIN));
+               HwPerfBufferSize = RGXFW_HWPERF_L1_SIZE_MIN<<10;
+       }
+
+       return HwPerfBufferSize;
+}
+
+#if defined(PDUMP)
+/*!
+*******************************************************************************
+ @Function             RGXFWSetupSignatureChecks
+ @Description
+ @Input                        psDevInfo
+
+ @Return               PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXFWSetupSignatureChecks(PVRSRV_RGXDEV_INFO* psDevInfo,
+                                              DEVMEM_MEMDESC**    ppsSigChecksMemDesc,
+                                              IMG_UINT32          ui32SigChecksBufSize,
+                                              RGXFWIF_SIGBUF_CTL* psSigBufCtl)
+{
+       PVRSRV_ERROR    eError;
+
+       /* Allocate memory for the checks */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS,
+                                                                 ui32SigChecksBufSize,
+                                                                 "FwSignatureChecks",
+                                                                 ppsSigChecksMemDesc,
+                                                                 &psSigBufCtl->sBuffer,
+                                                                 NULL,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       DevmemPDumpLoadMem(     *ppsSigChecksMemDesc,
+                       0,
+                       ui32SigChecksBufSize,
+                       PDUMP_FLAGS_CONTINUOUS);
+
+       psSigBufCtl->ui32LeftSizeInRegs = ui32SigChecksBufSize / sizeof(IMG_UINT32);
+fail:
+       return eError;
+}
+#endif
+
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+/*!
+*******************************************************************************
+ @Function             RGXFWSetupFirmwareGcovBuffer
+ @Description
+ @Input                        psDevInfo
+
+ @Return               PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXFWSetupFirmwareGcovBuffer(PVRSRV_RGXDEV_INFO*                   psDevInfo,
+               DEVMEM_MEMDESC**                        ppsBufferMemDesc,
+               IMG_UINT32                                      ui32FirmwareGcovBufferSize,
+               RGXFWIF_FIRMWARE_GCOV_CTL*      psFirmwareGcovCtl,
+               const IMG_CHAR*                         pszBufferName)
+{
+       PVRSRV_ERROR    eError;
+
+       /* Allocate memory for gcov */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 (RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS |
+                                                                  PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED)),
+                                                                 ui32FirmwareGcovBufferSize,
+                                                                 pszBufferName,
+                                                                 ppsBufferMemDesc,
+                                                                 &psFirmwareGcovCtl->sBuffer,
+                                                                 NULL,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXSetupFwAllocation");
+
+       psFirmwareGcovCtl->ui32Size = ui32FirmwareGcovBufferSize;
+
+       return PVRSRV_OK;
+}
+#endif
+
+/*!
+*******************************************************************************
+ @Function      RGXFWSetupAlignChecks
+ @Description   This functions allocates and fills memory needed for the
+                aligns checks of the UM and KM structures shared with the
+                firmware. The format of the data in the memory is as follows:
+                    <number of elements in the KM array>
+                    <array of KM structures' sizes and members' offsets>
+                    <number of elements in the UM array>
+                    <array of UM structures' sizes and members' offsets>
+                The UM array is passed from the user side. Now the firmware is
+                is responsible for filling this part of the memory. If that
+                happens the check of the UM structures will be performed
+                by the host driver on client's connect.
+                If the macro is not defined the client driver fills the memory
+                and the firmware checks for the alignment of all structures.
+ @Input                        psDeviceNode
+
+ @Return               PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXFWSetupAlignChecks(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                               RGXFWIF_DEV_VIRTADDR    *psAlignChecksDevFW)
+{
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32                      aui32RGXFWAlignChecksKM[] = { RGXFW_ALIGN_CHECKS_INIT_KM };
+       IMG_UINT32                      ui32RGXFWAlignChecksTotal;
+       IMG_UINT32*                     paui32AlignChecks;
+       PVRSRV_ERROR            eError;
+
+       /* In this case we don't know the number of elements in UM array.
+        * We have to assume something so we assume RGXFW_ALIGN_CHECKS_UM_MAX.
+        */
+       ui32RGXFWAlignChecksTotal = sizeof(aui32RGXFWAlignChecksKM)
+                                   + RGXFW_ALIGN_CHECKS_UM_MAX * sizeof(IMG_UINT32)
+                                   + 2 * sizeof(IMG_UINT32);
+
+       /* Allocate memory for the checks */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 ui32RGXFWAlignChecksTotal,
+                                                                 "FwAlignmentChecks",
+                                                                 &psDevInfo->psRGXFWAlignChecksMemDesc,
+                                                                 psAlignChecksDevFW,
+                                                                 (void**) &paui32AlignChecks,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       if (!psDeviceNode->bAutoVzFwIsUp)
+       {
+               /* Copy the values */
+               *paui32AlignChecks++ = ARRAY_SIZE(aui32RGXFWAlignChecksKM);
+               OSCachedMemCopy(paui32AlignChecks, &aui32RGXFWAlignChecksKM[0],
+                               sizeof(aui32RGXFWAlignChecksKM));
+               paui32AlignChecks += ARRAY_SIZE(aui32RGXFWAlignChecksKM);
+
+               *paui32AlignChecks = 0;
+       }
+
+       OSWriteMemoryBarrier(paui32AlignChecks);
+
+       DevmemPDumpLoadMem(     psDevInfo->psRGXFWAlignChecksMemDesc,
+                                               0,
+                                               ui32RGXFWAlignChecksTotal,
+                                               PDUMP_FLAGS_CONTINUOUS);
+
+       return PVRSRV_OK;
+
+fail:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+static void RGXFWFreeAlignChecks(PVRSRV_RGXDEV_INFO* psDevInfo)
+{
+       if (psDevInfo->psRGXFWAlignChecksMemDesc != NULL)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWAlignChecksMemDesc);
+               psDevInfo->psRGXFWAlignChecksMemDesc = NULL;
+       }
+}
+
+PVRSRV_ERROR RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR        *ppDest,
+                                                  DEVMEM_MEMDESC               *psSrc,
+                                                  IMG_UINT32                   uiExtraOffset,
+                                                  IMG_UINT32                   ui32Flags)
+{
+       PVRSRV_ERROR            eError;
+       IMG_DEV_VIRTADDR        psDevVirtAddr;
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       PVRSRV_RGXDEV_INFO      *psDevInfo;
+
+       psDeviceNode = (PVRSRV_DEVICE_NODE *) DevmemGetConnection(psSrc);
+       psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               IMG_UINT32          ui32Offset;
+               IMG_BOOL            bCachedInMETA;
+               PVRSRV_MEMALLOCFLAGS_T uiDevFlags;
+               IMG_UINT32          uiGPUCacheMode;
+
+               eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
+               PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireDevVirtAddr", failDevVAAcquire);
+
+               /* Convert to an address in META memmap */
+               ui32Offset = psDevVirtAddr.uiAddr + uiExtraOffset - RGX_FIRMWARE_RAW_HEAP_BASE;
+
+               /* Check in the devmem flags whether this memory is cached/uncached */
+               DevmemGetFlags(psSrc, &uiDevFlags);
+
+               /* Honour the META cache flags */
+               bCachedInMETA = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) & uiDevFlags) != 0;
+
+               /* Honour the SLC cache flags */
+               eError = DevmemDeviceCacheMode(psDeviceNode, uiDevFlags, &uiGPUCacheMode);
+               PVR_LOG_GOTO_IF_ERROR(eError, "DevmemDeviceCacheMode", failDevCacheMode);
+
+               /*
+                * Choose Meta virtual address based on Meta and SLC cacheability.
+                */
+               ui32Offset += RGXFW_SEGMMU_DATA_BASE_ADDRESS;
+
+               if (bCachedInMETA)
+               {
+                       ui32Offset |= RGXFW_SEGMMU_DATA_META_CACHED;
+               }
+               else
+               {
+                       ui32Offset |= RGXFW_SEGMMU_DATA_META_UNCACHED;
+               }
+
+               if (PVRSRV_CHECK_GPU_CACHED(uiGPUCacheMode))
+               {
+                       ui32Offset |= RGXFW_SEGMMU_DATA_VIVT_SLC_CACHED;
+               }
+               else
+               {
+                       ui32Offset |= RGXFW_SEGMMU_DATA_VIVT_SLC_UNCACHED;
+               }
+
+               ppDest->ui32Addr = ui32Offset;
+       }
+       else
+       {
+               IMG_UINT32      ui32Offset;
+               IMG_BOOL        bCachedInRISCV;
+               PVRSRV_MEMALLOCFLAGS_T uiDevFlags;
+
+               eError = DevmemAcquireDevVirtAddr(psSrc, &psDevVirtAddr);
+               PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireDevVirtAddr", failDevVAAcquire);
+
+               /* Convert to an address in RISCV memmap */
+               ui32Offset = psDevVirtAddr.uiAddr + uiExtraOffset - RGX_FIRMWARE_RAW_HEAP_BASE;
+
+               /* Check in the devmem flags whether this memory is cached/uncached */
+               DevmemGetFlags(psSrc, &uiDevFlags);
+
+               /* Honour the RISCV cache flags */
+               bCachedInRISCV = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) & uiDevFlags) != 0;
+
+               if (bCachedInRISCV)
+               {
+                       ui32Offset |= RGXRISCVFW_SHARED_CACHED_DATA_BASE;
+               }
+               else
+               {
+                       ui32Offset |= RGXRISCVFW_SHARED_UNCACHED_DATA_BASE;
+               }
+
+               ppDest->ui32Addr = ui32Offset;
+       }
+
+       if ((ppDest->ui32Addr & 0x3U) != 0)
+       {
+               IMG_CHAR *pszAnnotation;
+               /* It is expected that the annotation returned by DevmemGetAnnotation() is always valid */
+               DevmemGetAnnotation(psSrc, &pszAnnotation);
+
+               PVR_DPF((PVR_DBG_ERROR, "%s: %s @ 0x%x is not aligned to 32 bit",
+                                __func__, pszAnnotation, ppDest->ui32Addr));
+
+               return PVRSRV_ERROR_INVALID_ALIGNMENT;
+       }
+
+       if (ui32Flags & RFW_FWADDR_NOREF_FLAG)
+       {
+               DevmemReleaseDevVirtAddr(psSrc);
+       }
+
+       return PVRSRV_OK;
+
+failDevCacheMode:
+       DevmemReleaseDevVirtAddr(psSrc);
+failDevVAAcquire:
+       return eError;
+}
+
+void RGXSetMetaDMAAddress(RGXFWIF_DMA_ADDR             *psDest,
+                                                 DEVMEM_MEMDESC                *psSrcMemDesc,
+                                                 RGXFWIF_DEV_VIRTADDR  *psSrcFWDevVAddr,
+                                                 IMG_UINT32                    uiOffset)
+{
+       PVRSRV_ERROR            eError;
+       IMG_DEV_VIRTADDR        sDevVirtAddr;
+
+       eError = DevmemAcquireDevVirtAddr(psSrcMemDesc, &sDevVirtAddr);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+       psDest->psDevVirtAddr.uiAddr = sDevVirtAddr.uiAddr;
+       psDest->psDevVirtAddr.uiAddr += uiOffset;
+       psDest->pbyFWAddr.ui32Addr = psSrcFWDevVAddr->ui32Addr;
+
+       DevmemReleaseDevVirtAddr(psSrcMemDesc);
+}
+
+
+void RGXUnsetFirmwareAddress(DEVMEM_MEMDESC *psSrc)
+{
+       DevmemReleaseDevVirtAddr(psSrc);
+}
+
+PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       /* Wait for Slave Port to be Ready */
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+       {
+               eError = RGXPollReg32(hPrivate,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                         | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                         | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN);
+               if (eError == PVRSRV_OK)
+               {
+                       /* Issue a Write */
+                       CHECK_HWBRN_68777(ui32RegAddr);
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES, ui32RegAddr);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES); /* Fence write */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT__META_REGISTER_UNPACKED_ACCESSES, ui32RegValue);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT__META_REGISTER_UNPACKED_ACCESSES); /* Fence write */
+               }
+       }
+       else
+       {
+               eError = RGXPollReg32(hPrivate,
+                                                         RGX_CR_META_SP_MSLVCTRL1,
+                                                         RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                                                         RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+               if (eError == PVRSRV_OK)
+               {
+                       /* Issue a Write */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0, ui32RegAddr);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0); /* Fence write */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT, ui32RegValue);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAT); /* Fence write */
+               }
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXReadMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32* ui32RegValue)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       /* Wait for Slave Port to be Ready */
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+       {
+               eError = RGXPollReg32(hPrivate,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                         | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                                                         RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                         | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN);
+               if (eError == PVRSRV_OK)
+               {
+                       /* Issue a Read */
+                       CHECK_HWBRN_68777(ui32RegAddr);
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES,
+                                                                       ui32RegAddr | RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES__RD_EN);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES); /* Fence write */
+
+                       /* Wait for Slave Port to be Ready */
+                       eError = RGXPollReg32(hPrivate,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                                 | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                                 | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN);
+                       if (eError != PVRSRV_OK) return eError;
+               }
+#if !defined(NO_HARDWARE)
+               *ui32RegValue = RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAX__META_REGISTER_UNPACKED_ACCESSES);
+#else
+               *ui32RegValue = 0xFFFFFFFF;
+#endif
+       }
+       else
+       {
+               eError = RGXPollReg32(hPrivate,
+                                                         RGX_CR_META_SP_MSLVCTRL1,
+                                                         RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                                                         RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+               if (eError == PVRSRV_OK)
+               {
+                       /* Issue a Read */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0, ui32RegAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVCTRL0); /* Fence write */
+
+                       /* Wait for Slave Port to be Ready */
+                       eError = RGXPollReg32(hPrivate,
+                                                                 RGX_CR_META_SP_MSLVCTRL1,
+                                                                 RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                                                                 RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+                       if (eError != PVRSRV_OK) return eError;
+               }
+#if !defined(NO_HARDWARE)
+               *ui32RegValue = RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVDATAX);
+#else
+               *ui32RegValue = 0xFFFFFFFF;
+#endif
+       }
+
+       return eError;
+}
+
+
+struct _RGX_SERVER_COMMON_CONTEXT_ {
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       DEVMEM_MEMDESC *psFWCommonContextMemDesc;
+       PRGXFWIF_FWCOMMONCONTEXT sFWCommonContextFWAddr;
+       SERVER_MMU_CONTEXT *psServerMMUContext;
+       DEVMEM_MEMDESC *psFWMemContextMemDesc;
+       DEVMEM_MEMDESC *psFWFrameworkMemDesc;
+       DEVMEM_MEMDESC *psContextStateMemDesc;
+       RGX_CLIENT_CCB *psClientCCB;
+       DEVMEM_MEMDESC *psClientCCBMemDesc;
+       DEVMEM_MEMDESC *psClientCCBCtrlMemDesc;
+       IMG_BOOL bCommonContextMemProvided;
+       IMG_UINT32 ui32ContextID;
+       DLLIST_NODE sListNode;
+       RGX_CONTEXT_RESET_REASON eLastResetReason;
+       IMG_UINT32 ui32LastResetJobRef;
+       IMG_INT32 i32Priority;
+       RGX_CCB_REQUESTOR_TYPE eRequestor;
+};
+
+/*************************************************************************/ /*!
+@Function       _CheckPriority
+@Description    Check if priority is allowed for requestor type
+@Input          psDevInfo    pointer to DevInfo struct
+@Input          i32Priority Requested priority
+@Input          eRequestor   Requestor type specifying data master
+@Return         PVRSRV_ERROR PVRSRV_OK on success
+*/ /**************************************************************************/
+static PVRSRV_ERROR _CheckPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                  IMG_INT32 i32Priority,
+                                                                  RGX_CCB_REQUESTOR_TYPE eRequestor)
+{
+       /* Only one context allowed with real time priority (highest priority) */
+       if (i32Priority == RGX_CTX_PRIORITY_REALTIME)
+       {
+               DLLIST_NODE *psNode, *psNext;
+
+               dllist_foreach_node(&psDevInfo->sCommonCtxtListHead, psNode, psNext)
+               {
+                       RGX_SERVER_COMMON_CONTEXT *psThisContext =
+                               IMG_CONTAINER_OF(psNode, RGX_SERVER_COMMON_CONTEXT, sListNode);
+
+                       if (psThisContext->i32Priority == RGX_CTX_PRIORITY_REALTIME &&
+                               psThisContext->eRequestor == eRequestor)
+                       {
+                               PVR_LOG(("Only one context with real time priority allowed"));
+                               return PVRSRV_ERROR_INVALID_PARAMS;
+                       }
+               }
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
+                                                                        PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                        RGX_CCB_REQUESTOR_TYPE eRGXCCBRequestor,
+                                                                        RGXFWIF_DM eDM,
+                                                                        SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                                        DEVMEM_MEMDESC *psAllocatedMemDesc,
+                                                                        IMG_UINT32 ui32AllocatedOffset,
+                                                                        DEVMEM_MEMDESC *psFWMemContextMemDesc,
+                                                                        DEVMEM_MEMDESC *psContextStateMemDesc,
+                                                                        IMG_UINT32 ui32CCBAllocSize,
+                                                                        IMG_UINT32 ui32CCBMaxAllocSize,
+                                                                        IMG_UINT32 ui32ContextFlags,
+                                                                        IMG_UINT32 ui32Priority,
+                                                                        IMG_UINT32 ui32MaxDeadlineMS,
+                                                                        IMG_UINT64 ui64RobustnessAddress,
+                                                                        RGX_COMMON_CONTEXT_INFO *psInfo,
+                                                                        RGX_SERVER_COMMON_CONTEXT **ppsServerCommonContext)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       RGX_SERVER_COMMON_CONTEXT *psServerCommonContext;
+       RGXFWIF_FWCOMMONCONTEXT *psFWCommonContext;
+       IMG_UINT32 ui32FWCommonContextOffset;
+       IMG_UINT8 *pui8Ptr;
+       IMG_INT32 i32Priority = (IMG_INT32)ui32Priority;
+       PVRSRV_ERROR eError;
+
+       /*
+        * Allocate all the resources that are required
+        */
+       psServerCommonContext = OSAllocMem(sizeof(*psServerCommonContext));
+       if (psServerCommonContext == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto fail_alloc;
+       }
+
+       psServerCommonContext->psDevInfo = psDevInfo;
+       psServerCommonContext->psServerMMUContext = psServerMMUContext;
+
+       if (psAllocatedMemDesc)
+       {
+               PDUMPCOMMENT(psDeviceNode,
+                                        "Using existing MemDesc for Rogue firmware %s context (offset = %d)",
+                                        aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+                                        ui32AllocatedOffset);
+               ui32FWCommonContextOffset = ui32AllocatedOffset;
+               psServerCommonContext->psFWCommonContextMemDesc = psAllocatedMemDesc;
+               psServerCommonContext->bCommonContextMemProvided = IMG_TRUE;
+       }
+       else
+       {
+               /* Allocate device memory for the firmware context */
+               PDUMPCOMMENT(psDeviceNode,
+                                        "Allocate Rogue firmware %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
+               eError = DevmemFwAllocate(psDevInfo,
+                                                               sizeof(*psFWCommonContext),
+                                                               RGX_FWCOMCTX_ALLOCFLAGS,
+                                                               "FwContext",
+                                                               &psServerCommonContext->psFWCommonContextMemDesc);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to allocate firmware %s context (%s)",
+                                __func__,
+                                aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+                                PVRSRVGetErrorString(eError)));
+                       goto fail_contextalloc;
+               }
+               ui32FWCommonContextOffset = 0;
+               psServerCommonContext->bCommonContextMemProvided = IMG_FALSE;
+       }
+
+       /* Record this context so we can refer to it if the FW needs to tell us it was reset. */
+       psServerCommonContext->eLastResetReason    = RGX_CONTEXT_RESET_REASON_NONE;
+       psServerCommonContext->ui32LastResetJobRef = 0;
+       psServerCommonContext->ui32ContextID       = psDevInfo->ui32CommonCtxtCurrentID++;
+
+       /*
+        * Temporarily map the firmware context to the kernel and initialise it
+        */
+       eError = DevmemAcquireCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc,
+                                         (void **)&pui8Ptr);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to map firmware %s context to CPU (%s)",
+                        __func__,
+                        aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+                        PVRSRVGetErrorString(eError)));
+               goto fail_cpuvirtacquire;
+       }
+
+       /* Allocate the client CCB */
+       eError = RGXCreateCCB(psDevInfo,
+                                                 ui32CCBAllocSize,
+                                                 ui32CCBMaxAllocSize,
+                                                 ui32ContextFlags,
+                                                 psConnection,
+                                                 eRGXCCBRequestor,
+                                                 psServerCommonContext,
+                                                 &psServerCommonContext->psClientCCB,
+                                                 &psServerCommonContext->psClientCCBMemDesc,
+                                                 &psServerCommonContext->psClientCCBCtrlMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: failed to create CCB for %s context (%s)",
+                        __func__,
+                        aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+                        PVRSRVGetErrorString(eError)));
+               goto fail_allocateccb;
+       }
+
+       psFWCommonContext = (RGXFWIF_FWCOMMONCONTEXT *) (pui8Ptr + ui32FWCommonContextOffset);
+       psFWCommonContext->eDM = eDM;
+
+       /* Set the firmware CCB device addresses in the firmware common context */
+       eError = RGXSetFirmwareAddress(&psFWCommonContext->psCCB,
+                                                 psServerCommonContext->psClientCCBMemDesc,
+                                                 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", fail_cccbfwaddr);
+
+       eError = RGXSetFirmwareAddress(&psFWCommonContext->psCCBCtl,
+                                                 psServerCommonContext->psClientCCBCtrlMemDesc,
+                                                 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", fail_cccbctrlfwaddr);
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
+       {
+               RGXSetMetaDMAAddress(&psFWCommonContext->sCCBMetaDMAAddr,
+                                                        psServerCommonContext->psClientCCBMemDesc,
+                                                        &psFWCommonContext->psCCB,
+                                                        0);
+       }
+
+       /* Set the memory context device address */
+       psServerCommonContext->psFWMemContextMemDesc = psFWMemContextMemDesc;
+       eError = RGXSetFirmwareAddress(&psFWCommonContext->psFWMemContext,
+                                                 psFWMemContextMemDesc,
+                                                 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:3", fail_fwmemctxfwaddr);
+
+       /* Set the framework register updates address */
+       psServerCommonContext->psFWFrameworkMemDesc = psInfo->psFWFrameworkMemDesc;
+       if (psInfo->psFWFrameworkMemDesc != NULL)
+       {
+               eError = RGXSetFirmwareAddress(&psFWCommonContext->psRFCmd,
+                               psInfo->psFWFrameworkMemDesc,
+                               0, RFW_FWADDR_FLAG_NONE);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:4", fail_fwframeworkfwadd);
+       }
+       else
+       {
+               /* This should never be touched in this contexts without a framework
+                * memdesc, but ensure it is zero so we see crashes if it is.
+                */
+               psFWCommonContext->psRFCmd.ui32Addr = 0;
+       }
+
+       eError = _CheckPriority(psDevInfo, i32Priority, eRGXCCBRequestor);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_CheckPriority", fail_checkpriority);
+
+       psServerCommonContext->i32Priority = i32Priority;
+       psServerCommonContext->eRequestor = eRGXCCBRequestor;
+
+       /* Store the FWMemContext device virtual address in server mmu context
+        * to be used in schedule command path */
+       RGXSetFWMemContextDevVirtAddr(psServerMMUContext, psFWCommonContext->psFWMemContext);
+
+       psFWCommonContext->i32Priority = i32Priority;
+       psFWCommonContext->ui32PrioritySeqNum = 0;
+       psFWCommonContext->ui32MaxDeadlineMS = MIN(ui32MaxDeadlineMS,
+                                                                                          (eDM == RGXFWIF_DM_CDM ?
+                                                                                               RGXFWIF_MAX_CDM_WORKLOAD_DEADLINE_MS :
+                                                                                               RGXFWIF_MAX_WORKLOAD_DEADLINE_MS));
+       psFWCommonContext->ui64RobustnessAddress = ui64RobustnessAddress;
+
+       /* Store a references to Server Common Context and PID for notifications back from the FW. */
+       psFWCommonContext->ui32ServerCommonContextID = psServerCommonContext->ui32ContextID;
+       psFWCommonContext->ui32PID                   = OSGetCurrentClientProcessIDKM();
+
+       /* Set the firmware GPU context state buffer */
+       psServerCommonContext->psContextStateMemDesc = psContextStateMemDesc;
+       if (psContextStateMemDesc)
+       {
+               eError = RGXSetFirmwareAddress(&psFWCommonContext->psContextState,
+                                                         psContextStateMemDesc,
+                                                         0,
+                                                         RFW_FWADDR_FLAG_NONE);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:5", fail_ctxstatefwaddr);
+       }
+
+       /*
+        * Dump the created context
+        */
+       PDUMPCOMMENT(psDeviceNode,
+                                "Dump %s context", aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT]);
+       DevmemPDumpLoadMem(psServerCommonContext->psFWCommonContextMemDesc,
+                                          ui32FWCommonContextOffset,
+                                          sizeof(*psFWCommonContext),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       /* We've finished the setup so release the CPU mapping */
+       DevmemReleaseCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc);
+
+       /* Map this allocation into the FW */
+       eError = RGXSetFirmwareAddress(&psServerCommonContext->sFWCommonContextFWAddr,
+                                                 psServerCommonContext->psFWCommonContextMemDesc,
+                                                 ui32FWCommonContextOffset,
+                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:6", fail_fwcommonctxfwaddr);
+
+#if defined(__linux__)
+       {
+               IMG_UINT32 ui32FWAddr;
+               switch (eDM) {
+                       case RGXFWIF_DM_GEOM:
+                               ui32FWAddr = (IMG_UINT32) ((uintptr_t) IMG_CONTAINER_OF((void *) ((uintptr_t)
+                                               psServerCommonContext->sFWCommonContextFWAddr.ui32Addr), RGXFWIF_FWRENDERCONTEXT, sTAContext));
+                               break;
+                       case RGXFWIF_DM_3D:
+                               ui32FWAddr = (IMG_UINT32) ((uintptr_t) IMG_CONTAINER_OF((void *) ((uintptr_t)
+                                               psServerCommonContext->sFWCommonContextFWAddr.ui32Addr), RGXFWIF_FWRENDERCONTEXT, s3DContext));
+                               break;
+                       default:
+                               ui32FWAddr = psServerCommonContext->sFWCommonContextFWAddr.ui32Addr;
+                               break;
+               }
+
+               trace_rogue_create_fw_context(OSGetCurrentClientProcessNameKM(),
+                                                                         aszCCBRequestors[eRGXCCBRequestor][REQ_PDUMP_COMMENT],
+                                                                         ui32FWAddr);
+       }
+#endif
+       /*Add the node to the list when finalised */
+       OSWRLockAcquireWrite(psDevInfo->hCommonCtxtListLock);
+       dllist_add_to_tail(&(psDevInfo->sCommonCtxtListHead), &(psServerCommonContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hCommonCtxtListLock);
+
+       *ppsServerCommonContext = psServerCommonContext;
+       return PVRSRV_OK;
+
+fail_fwcommonctxfwaddr:
+       if (psContextStateMemDesc)
+       {
+               RGXUnsetFirmwareAddress(psContextStateMemDesc);
+       }
+fail_ctxstatefwaddr:
+fail_checkpriority:
+       if (psInfo->psFWFrameworkMemDesc != NULL)
+       {
+               RGXUnsetFirmwareAddress(psInfo->psFWFrameworkMemDesc);
+       }
+fail_fwframeworkfwadd:
+       RGXUnsetFirmwareAddress(psFWMemContextMemDesc);
+fail_fwmemctxfwaddr:
+       RGXUnsetFirmwareAddress(psServerCommonContext->psClientCCBCtrlMemDesc);
+fail_cccbctrlfwaddr:
+       RGXUnsetFirmwareAddress(psServerCommonContext->psClientCCBMemDesc);
+fail_cccbfwaddr:
+       RGXDestroyCCB(psDevInfo, psServerCommonContext->psClientCCB);
+fail_allocateccb:
+       DevmemReleaseCpuVirtAddr(psServerCommonContext->psFWCommonContextMemDesc);
+fail_cpuvirtacquire:
+       RGXUnsetFirmwareAddress(psServerCommonContext->psFWCommonContextMemDesc);
+       if (!psServerCommonContext->bCommonContextMemProvided)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psServerCommonContext->psFWCommonContextMemDesc);
+               psServerCommonContext->psFWCommonContextMemDesc = NULL;
+       }
+fail_contextalloc:
+       OSFreeMem(psServerCommonContext);
+fail_alloc:
+       return eError;
+}
+
+void FWCommonContextFree(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+
+       OSWRLockAcquireWrite(psServerCommonContext->psDevInfo->hCommonCtxtListLock);
+       /* Remove the context from the list of all contexts. */
+       dllist_remove_node(&psServerCommonContext->sListNode);
+       OSWRLockReleaseWrite(psServerCommonContext->psDevInfo->hCommonCtxtListLock);
+
+       /*
+               Unmap the context itself and then all its resources
+       */
+
+       /* Unmap the FW common context */
+       RGXUnsetFirmwareAddress(psServerCommonContext->psFWCommonContextMemDesc);
+       /* Umap context state buffer (if there was one) */
+       if (psServerCommonContext->psContextStateMemDesc)
+       {
+               RGXUnsetFirmwareAddress(psServerCommonContext->psContextStateMemDesc);
+       }
+       /* Unmap the framework buffer */
+       if (psServerCommonContext->psFWFrameworkMemDesc != NULL)
+       {
+               RGXUnsetFirmwareAddress(psServerCommonContext->psFWFrameworkMemDesc);
+       }
+       /* Unmap client CCB and CCB control */
+       RGXUnsetFirmwareAddress(psServerCommonContext->psClientCCBCtrlMemDesc);
+       RGXUnsetFirmwareAddress(psServerCommonContext->psClientCCBMemDesc);
+       /* Unmap the memory context */
+       RGXUnsetFirmwareAddress(psServerCommonContext->psFWMemContextMemDesc);
+
+       /* Destroy the client CCB */
+       RGXDestroyCCB(psServerCommonContext->psDevInfo, psServerCommonContext->psClientCCB);
+
+
+       /* Free the FW common context (if there was one) */
+       if (!psServerCommonContext->bCommonContextMemProvided)
+       {
+               DevmemFwUnmapAndFree(psServerCommonContext->psDevInfo,
+                                               psServerCommonContext->psFWCommonContextMemDesc);
+               psServerCommonContext->psFWCommonContextMemDesc = NULL;
+       }
+       /* Free the hosts representation of the common context */
+       OSFreeMem(psServerCommonContext);
+}
+
+PRGXFWIF_FWCOMMONCONTEXT FWCommonContextGetFWAddress(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+       return psServerCommonContext->sFWCommonContextFWAddr;
+}
+
+RGX_CLIENT_CCB *FWCommonContextGetClientCCB(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+       return psServerCommonContext->psClientCCB;
+}
+
+SERVER_MMU_CONTEXT *FWCommonContextGetServerMMUCtx(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+       return psServerCommonContext->psServerMMUContext;
+}
+
+RGX_CONTEXT_RESET_REASON FWCommonContextGetLastResetReason(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                                               IMG_UINT32 *pui32LastResetJobRef)
+{
+       RGX_CONTEXT_RESET_REASON eLastResetReason;
+
+       PVR_ASSERT(psServerCommonContext != NULL);
+       PVR_ASSERT(pui32LastResetJobRef != NULL);
+
+       /* Take the most recent reason & job ref and reset for next time... */
+       eLastResetReason      = psServerCommonContext->eLastResetReason;
+       *pui32LastResetJobRef = psServerCommonContext->ui32LastResetJobRef;
+       psServerCommonContext->eLastResetReason = RGX_CONTEXT_RESET_REASON_NONE;
+       psServerCommonContext->ui32LastResetJobRef = 0;
+
+       if (eLastResetReason == RGX_CONTEXT_RESET_REASON_HARD_CONTEXT_SWITCH)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                        "A Hard Context Switch was triggered on the GPU to ensure Quality of Service."));
+       }
+
+       return eLastResetReason;
+}
+
+PVRSRV_RGXDEV_INFO* FWCommonContextGetRGXDevInfo(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext)
+{
+       return psServerCommonContext->psDevInfo;
+}
+
+PVRSRV_ERROR RGXGetFWCommonContextAddrFromServerMMUCtx(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                          SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                                                                          PRGXFWIF_FWCOMMONCONTEXT *psFWCommonContextFWAddr)
+{
+       DLLIST_NODE *psNode, *psNext;
+       dllist_foreach_node(&psDevInfo->sCommonCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_COMMON_CONTEXT *psThisContext =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_COMMON_CONTEXT, sListNode);
+
+               if (psThisContext->psServerMMUContext == psServerMMUContext)
+               {
+                       psFWCommonContextFWAddr->ui32Addr = psThisContext->sFWCommonContextFWAddr.ui32Addr;
+                       return PVRSRV_OK;
+               }
+       }
+       return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+PVRSRV_ERROR FWCommonContextSetFlags(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                     IMG_UINT32 ui32ContextFlags)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (BITMASK_ANY(ui32ContextFlags, ~RGX_CONTEXT_FLAGS_WRITEABLE_MASK))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Context flag(s) invalid or not writeable (%d)",
+                        __func__, ui32ContextFlags));
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       else
+       {
+               RGXSetCCBFlags(psServerCommonContext->psClientCCB,
+                              ui32ContextFlags);
+       }
+
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function             RGXFreeCCB
+ @Description  Free the kernel or firmware CCB
+ @Input                        psDevInfo
+ @Input                        ppsCCBCtl
+ @Input                        ppsCCBCtlMemDesc
+ @Input                        ppsCCBMemDesc
+ @Input                        psCCBCtlFWAddr
+******************************************************************************/
+static void RGXFreeCCB(PVRSRV_RGXDEV_INFO      *psDevInfo,
+                                          RGXFWIF_CCB_CTL              **ppsCCBCtl,
+                                          DEVMEM_MEMDESC               **ppsCCBCtlMemDesc,
+                                          IMG_UINT8                    **ppui8CCB,
+                                          DEVMEM_MEMDESC               **ppsCCBMemDesc)
+{
+       if (*ppsCCBMemDesc != NULL)
+       {
+               if (*ppui8CCB != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(*ppsCCBMemDesc);
+                       *ppui8CCB = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, *ppsCCBMemDesc);
+               *ppsCCBMemDesc = NULL;
+       }
+       if (*ppsCCBCtlMemDesc != NULL)
+       {
+               if (*ppsCCBCtl != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(*ppsCCBCtlMemDesc);
+                       *ppsCCBCtl = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, *ppsCCBCtlMemDesc);
+               *ppsCCBCtlMemDesc = NULL;
+       }
+}
+
+/*!
+*******************************************************************************
+ @Function             RGXFreeCCBReturnSlots
+ @Description  Free the kernel CCB's return slot array and associated mappings
+ @Input                        psDevInfo              Device Info struct
+ @Input                        ppui32CCBRtnSlots      CPU mapping of slot array
+ @Input                        ppsCCBRtnSlotsMemDesc  Slot array's device memdesc
+******************************************************************************/
+static void RGXFreeCCBReturnSlots(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                  IMG_UINT32         **ppui32CCBRtnSlots,
+                                                                 DEVMEM_MEMDESC     **ppsCCBRtnSlotsMemDesc)
+{
+       /* Free the return slot array if allocated */
+       if (*ppsCCBRtnSlotsMemDesc != NULL)
+       {
+               /* Before freeing, ensure the CPU mapping as well is released */
+               if (*ppui32CCBRtnSlots != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(*ppsCCBRtnSlotsMemDesc);
+                       *ppui32CCBRtnSlots = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, *ppsCCBRtnSlotsMemDesc);
+               *ppsCCBRtnSlotsMemDesc = NULL;
+       }
+}
+
+/*!
+*******************************************************************************
+ @Function             RGXSetupCCB
+ @Description  Allocate and initialise a circular command buffer
+ @Input                        psDevInfo
+ @Input                        ppsCCBCtl
+ @Input                        ppsCCBCtlMemDesc
+ @Input                        ppui8CCB
+ @Input                        ppsCCBMemDesc
+ @Input                        psCCBCtlFWAddr
+ @Input                        ui32NumCmdsLog2
+ @Input                        ui32CmdSize
+ @Input                        uiCCBMemAllocFlags
+ @Input                        pszName
+
+ @Return               PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupCCB(PVRSRV_RGXDEV_INFO     *psDevInfo,
+                                                               RGXFWIF_CCB_CTL         **ppsCCBCtl,
+                                                               DEVMEM_MEMDESC          **ppsCCBCtlMemDesc,
+                                                               IMG_UINT8                       **ppui8CCB,
+                                                               DEVMEM_MEMDESC          **ppsCCBMemDesc,
+                                                               PRGXFWIF_CCB_CTL        *psCCBCtlFWAddr,
+                                                               PRGXFWIF_CCB            *psCCBFWAddr,
+                                                               IMG_UINT32                      ui32NumCmdsLog2,
+                                                               IMG_UINT32                      ui32CmdSize,
+                                                               PVRSRV_MEMALLOCFLAGS_T uiCCBMemAllocFlags,
+                                                               const IMG_CHAR          *pszName)
+{
+       PVRSRV_ERROR            eError;
+       RGXFWIF_CCB_CTL         *psCCBCtl;
+       IMG_UINT32              ui32CCBSize = (1U << ui32NumCmdsLog2);
+       IMG_CHAR                szCCBCtlName[DEVMEM_ANNOTATION_MAX_LEN];
+       IMG_INT32               iStrLen;
+
+       /* Append "Control" to the name for the control struct. */
+       iStrLen = OSSNPrintf(szCCBCtlName, sizeof(szCCBCtlName), "%sControl", pszName);
+       PVR_ASSERT(iStrLen < sizeof(szCCBCtlName));
+
+       if (unlikely(iStrLen < 0))
+       {
+               OSStringLCopy(szCCBCtlName, "FwCCBControl", DEVMEM_ANNOTATION_MAX_LEN);
+       }
+
+       /* Allocate memory for the CCB control.*/
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
+                                                                 sizeof(RGXFWIF_CCB_CTL),
+                                                                 szCCBCtlName,
+                                                                 ppsCCBCtlMemDesc,
+                                                                 psCCBCtlFWAddr,
+                                                                 (void**) ppsCCBCtl,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       /*
+        * Allocate memory for the CCB.
+        * (this will reference further command data in non-shared CCBs)
+        */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 uiCCBMemAllocFlags,
+                                                                 ui32CCBSize * ui32CmdSize,
+                                                                 pszName,
+                                                                 ppsCCBMemDesc,
+                                                                 psCCBFWAddr,
+                                                                 (void**) ppui8CCB,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       /*
+        * Initialise the CCB control.
+        */
+       psCCBCtl = *ppsCCBCtl;
+       psCCBCtl->ui32WriteOffset = 0;
+       psCCBCtl->ui32ReadOffset = 0;
+       psCCBCtl->ui32WrapMask = ui32CCBSize - 1;
+       psCCBCtl->ui32CmdSize = ui32CmdSize;
+
+       /* Pdump the CCB control */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Initialise %s", szCCBCtlName);
+       DevmemPDumpLoadMem(*ppsCCBCtlMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_CCB_CTL),
+                                          0);
+
+       return PVRSRV_OK;
+
+fail:
+       RGXFreeCCB(psDevInfo,
+                          ppsCCBCtl,
+                          ppsCCBCtlMemDesc,
+                          ppui8CCB,
+                          ppsCCBMemDesc);
+
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+#if defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK)
+static void RGXSetupFaultReadRegisterRollback(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       PMR *psPMR;
+
+       /* Run-time check feature support */
+       if (PVRSRV_IS_FEATURE_SUPPORTED(psDevInfo->psDeviceNode, SLC_FAULT_ACCESS_ADDR_PHYS))
+       {
+               if (psDevInfo->psRGXFaultAddressMemDesc)
+               {
+                       if (DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc, (void **)&psPMR) == PVRSRV_OK)
+                       {
+                               PMRUnlockSysPhysAddresses(psPMR);
+                       }
+                       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFaultAddressMemDesc);
+                       psDevInfo->psRGXFaultAddressMemDesc = NULL;
+               }
+       }
+}
+
+static PVRSRV_ERROR RGXSetupFaultReadRegister(PVRSRV_DEVICE_NODE *psDeviceNode, RGXFWIF_SYSINIT *psFwSysInit)
+{
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       IMG_UINT32                      *pui32MemoryVirtAddr;
+       IMG_UINT32                      i;
+       size_t                          ui32PageSize = OSGetPageSize();
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       PMR                                     *psPMR;
+
+       /* Run-time check feature support */
+       if (!PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, SLC_FAULT_ACCESS_ADDR_PHYS))
+       {
+               return PVRSRV_OK;
+       }
+
+       /* Allocate page of memory to use for page faults on non-blocking memory transactions.
+        * Doesn't need to be cleared as it is initialised with the 0xDEADBEEF pattern below. */
+       psDevInfo->psRGXFaultAddressMemDesc = NULL;
+       eError = DevmemFwAllocateExportable(psDeviceNode,
+                       ui32PageSize,
+                       ui32PageSize,
+                       RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS & ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+                       "FwExFaultAddress",
+                       &psDevInfo->psRGXFaultAddressMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to allocate mem for fault address (%u)",
+                        __func__, eError));
+               goto failFaultAddressDescAlloc;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc,
+                                                                         (void **)&pui32MemoryVirtAddr);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to acquire mem for fault address (%u)",
+                        __func__, eError));
+               goto failFaultAddressDescAqCpuVirt;
+       }
+
+       if (!psDeviceNode->bAutoVzFwIsUp)
+       {
+               /* fill the page with a known pattern when booting the firmware */
+               for (i = 0; i < ui32PageSize/sizeof(IMG_UINT32); i++)
+               {
+                       *(pui32MemoryVirtAddr + i) = 0xDEADBEEF;
+               }
+       }
+
+       OSWriteMemoryBarrier(pui32MemoryVirtAddr);
+
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFaultAddressMemDesc);
+
+       eError = DevmemServerGetImportHandle(psDevInfo->psRGXFaultAddressMemDesc, (void **)&psPMR);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Error getting PMR for fault address (%u)",
+                        __func__, eError));
+
+               goto failFaultAddressDescGetPMR;
+       }
+       else
+       {
+               IMG_BOOL bValid;
+               IMG_UINT32 ui32Log2PageSize = OSGetPageShift();
+
+               eError = PMRLockSysPhysAddresses(psPMR);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Error locking physical address for fault address MemDesc (%u)",
+                                __func__, eError));
+
+                       goto failFaultAddressDescLockPhys;
+               }
+
+               eError = PMR_DevPhysAddr(psPMR,ui32Log2PageSize, 1, 0, &(psFwSysInit->sFaultPhysAddr), &bValid);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Error getting physical address for fault address MemDesc (%u)",
+                                __func__, eError));
+
+                       goto failFaultAddressDescGetPhys;
+               }
+
+               if (!bValid)
+               {
+                       psFwSysInit->sFaultPhysAddr.uiAddr = 0;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed getting physical address for fault address MemDesc - invalid page (0x%" IMG_UINT64_FMTSPECX ")",
+                                __func__, psFwSysInit->sFaultPhysAddr.uiAddr));
+
+                       goto failFaultAddressDescGetPhys;
+               }
+       }
+
+       return PVRSRV_OK;
+
+failFaultAddressDescGetPhys:
+       PMRUnlockSysPhysAddresses(psPMR);
+
+failFaultAddressDescLockPhys:
+failFaultAddressDescGetPMR:
+failFaultAddressDescAqCpuVirt:
+       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFaultAddressMemDesc);
+       psDevInfo->psRGXFaultAddressMemDesc = NULL;
+
+failFaultAddressDescAlloc:
+
+       return eError;
+}
+
+#if defined(PDUMP)
+/* Replace the DevPhy address with the one Pdump allocates at pdump_player run time */
+static PVRSRV_ERROR RGXPDumpFaultReadRegister(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       PVRSRV_ERROR eError;
+       PMR *psFWInitPMR, *psFaultAddrPMR;
+       IMG_UINT32 ui32Dstoffset;
+
+       /* Run-time check feature support */
+       if (!PVRSRV_IS_FEATURE_SUPPORTED(psDevInfo->psDeviceNode, SLC_FAULT_ACCESS_ADDR_PHYS))
+       {
+               return PVRSRV_OK;
+       }
+
+       psFWInitPMR = (PMR *)(psDevInfo->psRGXFWIfSysInitMemDesc->psImport->hPMR);
+       ui32Dstoffset = psDevInfo->psRGXFWIfSysInitMemDesc->uiOffset + offsetof(RGXFWIF_SYSINIT, sFaultPhysAddr.uiAddr);
+
+       psFaultAddrPMR = (PMR *)(psDevInfo->psRGXFaultAddressMemDesc->psImport->hPMR);
+
+       eError = PDumpMemLabelToMem64(psFaultAddrPMR,
+                               psFWInitPMR,
+                               0,
+                               ui32Dstoffset,
+                               PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Dump of Fault Page Phys address failed(%u)", __func__, eError));
+       }
+       return eError;
+}
+#endif
+#endif /* defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK) */
+
+#if defined(SUPPORT_TBI_INTERFACE)
+/*************************************************************************/ /*!
+@Function       RGXTBIBufferIsInitRequired
+
+@Description    Returns true if the firmware tbi buffer is not allocated and
+               might be required by the firmware soon. TBI buffer allocated
+               on-demand to reduce RAM footprint on systems not needing
+               tbi.
+
+@Input          psDevInfo       RGX device info
+
+@Return                IMG_BOOL        Whether on-demand allocation(s) is/are needed
+                               or not
+*/ /**************************************************************************/
+INLINE IMG_BOOL RGXTBIBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_TRACEBUF*  psTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+
+       /* The firmware expects a tbi buffer only when:
+        *      - Logtype is "tbi"
+        */
+       if ((psDevInfo->psRGXFWIfTBIBufferMemDesc == NULL)
+                && (psTraceBufCtl->ui32LogType & ~RGXFWIF_LOG_TYPE_TRACE)
+                && (psTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_GROUP_MASK))
+       {
+               return IMG_TRUE;
+       }
+
+       return IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXTBIBufferDeinit
+
+@Description    Deinitialises all the allocations and references that are made
+               for the FW tbi buffer
+
+@Input          ppsDevInfo      RGX device info
+@Return                void
+*/ /**************************************************************************/
+static void RGXTBIBufferDeinit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfTBIBufferMemDesc);
+       psDevInfo->psRGXFWIfTBIBufferMemDesc = NULL;
+       psDevInfo->ui32RGXFWIfHWPerfBufSize = 0;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXTBIBufferInitOnDemandResources
+
+@Description    Allocates the firmware TBI buffer required for reading SFs
+               strings and initialize it with SFs.
+
+@Input          psDevInfo       RGX device info
+
+@Return                PVRSRV_OK       If all went good, PVRSRV_ERROR otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXTBIBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       PVRSRV_ERROR       eError = PVRSRV_OK;
+       IMG_UINT32         i, ui32Len;
+       const IMG_UINT32   ui32FWTBIBufsize = g_ui32SFsCount * sizeof(RGXFW_STID_FMT);
+       RGXFW_STID_FMT     *psFW_SFs = NULL;
+
+       /* Firmware address should not be already set */
+       if (psDevInfo->sRGXFWIfTBIBuffer.ui32Addr)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: FW address for FWTBI is already set. Resetting it with newly allocated one",
+                        __func__));
+       }
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS,
+                                                                 ui32FWTBIBufsize,
+                                                                 "FwTBIBuffer",
+                                                                 &psDevInfo->psRGXFWIfTBIBufferMemDesc,
+                                                                 &psDevInfo->sRGXFWIfTBIBuffer,
+                                                                 (void**)&psFW_SFs,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       /* Copy SFs entries to FW buffer */
+       for (i = 0; i < g_ui32SFsCount; i++)
+       {
+               OSDeviceMemCopy(&psFW_SFs[i].ui32Id, &SFs[i].ui32Id, sizeof(SFs[i].ui32Id));
+               ui32Len = OSStringLength(SFs[i].psName);
+               OSDeviceMemCopy(psFW_SFs[i].sName, SFs[i].psName, MIN(ui32Len, IMG_SF_STRING_MAX_SIZE - 1));
+       }
+
+       /* flush write buffers for psFW_SFs */
+       OSWriteMemoryBarrier(psFW_SFs);
+
+       /* Set size of TBI buffer */
+       psDevInfo->ui32FWIfTBIBufferSize = ui32FWTBIBufsize;
+
+       /* release CPU mapping */
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTBIBufferMemDesc);
+
+       return PVRSRV_OK;
+fail:
+       RGXTBIBufferDeinit(psDevInfo);
+       return eError;
+}
+#endif
+
+/*************************************************************************/ /*!
+@Function       RGXTraceBufferIsInitRequired
+
+@Description    Returns true if the firmware trace buffer is not allocated and
+               might be required by the firmware soon. Trace buffer allocated
+               on-demand to reduce RAM footprint on systems not needing
+               firmware trace.
+
+@Input          psDevInfo       RGX device info
+
+@Return                IMG_BOOL        Whether on-demand allocation(s) is/are needed
+                               or not
+*/ /**************************************************************************/
+INLINE IMG_BOOL RGXTraceBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_TRACEBUF*  psTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+
+       /* The firmware expects a trace buffer only when:
+        *      - Logtype is "trace" AND
+        *      - at least one LogGroup is configured
+        *      - the Driver Mode is not Guest
+        */
+       if ((psDevInfo->psRGXFWIfTraceBufferMemDesc[0] == NULL)
+               && (psTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_TRACE)
+               && (psTraceBufCtl->ui32LogType & RGXFWIF_LOG_TYPE_GROUP_MASK)
+               && !PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               return IMG_TRUE;
+       }
+
+       return IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXTraceBufferDeinit
+
+@Description    Deinitialises all the allocations and references that are made
+               for the FW trace buffer(s)
+
+@Input          ppsDevInfo      RGX device info
+@Return                void
+*/ /**************************************************************************/
+static void RGXTraceBufferDeinit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_TRACEBUF*  psTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       IMG_UINT32 i;
+
+       for (i = 0; i < RGXFW_THREAD_NUM; i++)
+       {
+               if (psDevInfo->psRGXFWIfTraceBufferMemDesc[i])
+               {
+                       if (psTraceBufCtl->sTraceBuf[i].pui32TraceBuffer != NULL)
+                       {
+                               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufferMemDesc[i]);
+                               psTraceBufCtl->sTraceBuf[i].pui32TraceBuffer = NULL;
+                       }
+
+                       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfTraceBufferMemDesc[i]);
+                       psDevInfo->psRGXFWIfTraceBufferMemDesc[i] = NULL;
+               }
+       }
+}
+
+/*************************************************************************/ /*!
+@Function       RGXTraceBufferInitOnDemandResources
+
+@Description    Allocates the firmware trace buffer required for dumping trace
+               info from the firmware.
+
+@Input          psDevInfo       RGX device info
+
+@Return                PVRSRV_OK       If all went good, PVRSRV_ERROR otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXTraceBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO* psDevInfo,
+                                                                                                PVRSRV_MEMALLOCFLAGS_T uiAllocFlags)
+{
+       RGXFWIF_TRACEBUF*  psTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       PVRSRV_ERROR       eError = PVRSRV_OK;
+       IMG_UINT32         ui32FwThreadNum;
+       IMG_UINT32         ui32DefaultTraceBufSize;
+       IMG_DEVMEM_SIZE_T  uiTraceBufSizeInBytes;
+       void               *pvAppHintState = NULL;
+       IMG_CHAR           pszBufferName[] = "FwTraceBuffer_Thread0";
+
+       /* Check AppHint value for module-param FWTraceBufSizeInDWords */
+       OSCreateKMAppHintState(&pvAppHintState);
+       ui32DefaultTraceBufSize = RGXFW_TRACE_BUF_DEFAULT_SIZE_IN_DWORDS;
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                                pvAppHintState,
+                                                FWTraceBufSizeInDWords,
+                                                &ui32DefaultTraceBufSize,
+                                                &psTraceBufCtl->ui32TraceBufSizeInDWords);
+       OSFreeKMAppHintState(pvAppHintState);
+       pvAppHintState = NULL;
+
+       uiTraceBufSizeInBytes = psTraceBufCtl->ui32TraceBufSizeInDWords * sizeof(IMG_UINT32);
+
+       for (ui32FwThreadNum = 0; ui32FwThreadNum < RGXFW_THREAD_NUM; ui32FwThreadNum++)
+       {
+#if !defined(SUPPORT_AUTOVZ)
+               /* Ensure allocation API is only called when not already allocated */
+               PVR_ASSERT(psDevInfo->psRGXFWIfTraceBufferMemDesc[ui32FwThreadNum] == NULL);
+               /* Firmware address should not be already set */
+               PVR_ASSERT(psTraceBufCtl->sTraceBuf[ui32FwThreadNum].pui32RGXFWIfTraceBuffer.ui32Addr == 0x0);
+#endif
+
+               /* update the firmware thread number in the Trace Buffer's name */
+               pszBufferName[sizeof(pszBufferName) - 2] += ui32FwThreadNum;
+
+               eError = RGXSetupFwAllocation(psDevInfo,
+                                                                         uiAllocFlags,
+                                                                         uiTraceBufSizeInBytes,
+                                                                         pszBufferName,
+                                                                         &psDevInfo->psRGXFWIfTraceBufferMemDesc[ui32FwThreadNum],
+                                                                         &psTraceBufCtl->sTraceBuf[ui32FwThreadNum].pui32RGXFWIfTraceBuffer,
+                                                                         (void**)&psTraceBufCtl->sTraceBuf[ui32FwThreadNum].pui32TraceBuffer,
+                                                                         RFW_FWADDR_NOREF_FLAG);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+       }
+
+       return PVRSRV_OK;
+
+fail:
+       RGXTraceBufferDeinit(psDevInfo);
+       return eError;
+}
+
+#if defined(SUPPORT_POWMON_COMPONENT) && defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+/*************************************************************************/ /*!
+@Function       RGXPowmonBufferIsInitRequired
+
+@Description    Returns true if the power monitoring buffer is not allocated and
+               might be required by the firmware soon. Powmon buffer allocated
+               on-demand to reduce RAM footprint on systems not needing
+               power monitoring.
+
+@Input          psDevInfo       RGX device info
+
+@Return                IMG_BOOL        Whether on-demand allocation(s) is/are needed
+                               or not
+*/ /**************************************************************************/
+INLINE IMG_BOOL RGXPowmonBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       /* The firmware expects a power monitoring buffer only when:
+        *      - Single-shot power counters are enabled with RGX_HWPERF_PWR_EST_REQUEST
+        *      - the Driver Mode is not Guest
+        */
+       if ((psDevInfo->psRGXFWIfPowMonBufferMemDesc == NULL)
+               && (psDevInfo->ui64HWPerfFilter & RGX_HWPERF_EVENT_MASK_VALUE(RGX_HWPERF_PWR_EST_REQUEST))
+               && !PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               return IMG_TRUE;
+       }
+
+       return IMG_FALSE;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXPowmonBufferDeinit
+
+@Description    Deinitialises all the allocations and references that are made
+               for the FW power monitoring buffer
+
+@Input          ppsDevInfo      RGX device info
+@Return                void
+*/ /**************************************************************************/
+static void RGXPowmonBufferDeinit(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+       if (psDevInfo->psRGXFWIfPowMonBufferMemDesc)
+       {
+               if (psFwSysData->sPowerMonBuf.pui32TraceBuffer != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfPowMonBufferMemDesc);
+                       psFwSysData->sPowerMonBuf.pui32TraceBuffer = NULL;
+               }
+
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfPowMonBufferMemDesc);
+               psDevInfo->psRGXFWIfPowMonBufferMemDesc = NULL;
+       }
+}
+
+/*************************************************************************/ /*!
+@Function       RGXPowmonBufferInitOnDemandResources
+
+@Description    Allocates the power monitoring buffer.
+
+@Input          psDevInfo      RGX device info
+
+@Return                    PVRSRV_OK   If all went good, PVRSRV_ERROR otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXPowmonBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_SYSDATA    *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_ERROR       eError = PVRSRV_OK;
+
+#define POWER_MON_BUF_SIZE     (8192UL)
+       /* Ensure allocation API is only called when not already allocated */
+       PVR_ASSERT(psDevInfo->psRGXFWIfPowMonBufferMemDesc == NULL);
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS,
+                                                                 POWER_MON_BUF_SIZE,
+                                                                 "FwPowMonBuffer",
+                                                                 &psDevInfo->psRGXFWIfPowMonBufferMemDesc,
+                                                                 &psFwSysData->sPowerMonBuf.pui32RGXFWIfTraceBuffer,
+                                                                 (void **)&psFwSysData->sPowerMonBuf.pui32TraceBuffer,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Power Monitoring Buffer allocation", fail);
+
+       psFwSysData->ui32PowerMonBufSizeInDWords = POWER_MON_BUF_SIZE >> 2;
+       OSWriteMemoryBarrier(psFwSysData->sPowerMonBuf.pui32TraceBuffer);
+
+       return PVRSRV_OK;
+fail:
+       RGXPowmonBufferDeinit(psDevInfo);
+       return eError;
+}
+#endif
+
+#if defined(PDUMP)
+/*************************************************************************/ /*!
+@Function       RGXPDumpLoadFWInitData
+
+@Description    Allocates the firmware trace buffer required for dumping trace
+                info from the firmware.
+
+@Input          psDevInfo RGX device info
+ */ /*************************************************************************/
+static void RGXPDumpLoadFWInitData(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                  IMG_UINT32         ui32HWPerfCountersDataSize,
+                                                                  IMG_UINT32         ui32RenderKillingCtl,
+                                                                  IMG_UINT32         ui32CDMTDMKillingCtl,
+                                                                  IMG_BOOL           bEnableSignatureChecks)
+{
+       IMG_UINT32 ui32ConfigFlags    = psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags;
+       IMG_UINT32 ui32FwOsCfgFlags   = psDevInfo->psRGXFWIfFwOsData->ui32FwOsConfigFlags;
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Dump RGXFW Init data");
+       if (!bEnableSignatureChecks)
+       {
+               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                        "(to enable rgxfw signatures place the following line after the RTCONF line)");
+               DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                  offsetof(RGXFWIF_SYSINIT, asSigBufCtl),
+                                                  sizeof(RGXFWIF_SIGBUF_CTL)*(RGXFWIF_DM_MAX),
+                                                  PDUMP_FLAGS_CONTINUOUS);
+       }
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump initial state of FW runtime configuration");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_RUNTIME_CFG),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw hwperfctl structure");
+       DevmemPDumpLoadZeroMem (psDevInfo->psRGXFWIfHWPerfCountersMemDesc,
+                                                       0,
+                                                       ui32HWPerfCountersDataSize,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw trace control structure");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_TRACEBUF),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump firmware system data structure");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_SYSDATA),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump firmware OS data structure");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfFwOsDataMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_OSDATA),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(SUPPORT_TBI_INTERFACE)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgx TBI buffer");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfTBIBufferMemDesc,
+                                          0,
+                                          psDevInfo->ui32FWIfTBIBufferSize,
+                                          PDUMP_FLAGS_CONTINUOUS);
+#endif /* defined(SUPPORT_TBI_INTERFACE) */
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw register configuration buffer");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_REG_CFG),
+                                          PDUMP_FLAGS_CONTINUOUS);
+#endif /* defined(SUPPORT_USER_REGISTER_CONFIGURATION) */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw system init structure");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_SYSINIT),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Dump rgxfw os init structure");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_OSINIT),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK)
+       /* RGXFW Init structure needs to be loaded before we overwrite FaultPhysAddr, else this address patching won't have any effect */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Overwrite FaultPhysAddr of FwSysInit in pdump with actual physical address");
+       RGXPDumpFaultReadRegister(psDevInfo);
+#endif /* defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK) */
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "RTCONF: run-time configuration");
+
+       /* Dump the config options so they can be edited. */
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the FW system config options here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch Rand mode:                      0x%08x)", RGXFWIF_INICFG_CTXSWITCH_MODE_RAND);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch Soft Reset Enable:              0x%08x)", RGXFWIF_INICFG_CTXSWITCH_SRESET_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable HWPerf:                             0x%08x)", RGXFWIF_INICFG_HWPERF_EN);
+#if defined(SUPPORT_VALIDATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable generic DM Killing Rand mode:       0x%08x)", RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN);
+#endif /* defined(SUPPORT_VALIDATION) */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Rascal+Dust Power Island:                  0x%08x)", RGXFWIF_INICFG_POW_RASCALDUST);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( FBCDC Version 3.1 Enable:                  0x%08x)", RGXFWIF_INICFG_FBCDC_V3_1_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Check MList:                               0x%08x)", RGXFWIF_INICFG_CHECK_MLIST_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable Auto Clock Gating:                 0x%08x)", RGXFWIF_INICFG_DISABLE_CLKGATING_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable register configuration:             0x%08x)", RGXFWIF_INICFG_REGCONFIG_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Assert on TA Out-of-Memory:                0x%08x)", RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable HWPerf counter filter:             0x%08x)", RGXFWIF_INICFG_HWP_DISABLE_FILTER);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Ctx Switch profile mode: 0x%08x (none=d'0, fast=d'1, medium=d'2, slow=d'3, nodelay=d'4))", RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Disable DM overlap (except TA during SPM): 0x%08x)", RGXFWIF_INICFG_DISABLE_DM_OVERLAP);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Assert on HWR trigger (page fault, lockup, overrun or poll failure): 0x%08x)", RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable coherent memory accesses:           0x%08x)", RGXFWIF_INICFG_FABRIC_COHERENCY_ENABLED);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable IRQ validation:                     0x%08x)", RGXFWIF_INICFG_VALIDATE_IRQ);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( SPU power state mask change Enable:        0x%08x)", RGXFWIF_INICFG_SPU_POWER_STATE_MASK_CHANGE_EN);
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Workload Estimation:                0x%08x)", RGXFWIF_INICFG_WORKEST);
+#if defined(SUPPORT_PDVFS)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Enable Proactive DVFS:                     0x%08x)", RGXFWIF_INICFG_PDVFS);
+#endif /* defined(SUPPORT_PDVFS) */
+#endif /* defined(SUPPORT_WORKLOAD_ESTIMATION) */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CDM Arbitration Mode (task demand=b'01, round robin=b'10): 0x%08x)", RGXFWIF_INICFG_CDM_ARBITRATION_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( ISP Scheduling Mode (v1=b'01, v2=b'10):    0x%08x)", RGXFWIF_INICFG_ISPSCHEDMODE_MASK);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Validate SOC & USC timers:                 0x%08x)", RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER);
+
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                                       offsetof(RGXFWIF_SYSDATA, ui32ConfigFlags),
+                                                       ui32ConfigFlags,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Extended FW system config options not used.)");
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the FW OS config options here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch TDM Enable:                0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_TDM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch GEOM Enable:               0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_GEOM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch 3D Enable:                 0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch CDM Enable:                0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_CDM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Ctx Switch RDM Enable:                0x%08x)", RGXFWIF_INICFG_OS_CTXSWITCH_RDM_EN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  2D Enable: 0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_TDM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  TA Enable: 0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_GEOM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch  3D Enable: 0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_3D);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch CDM Enable: 0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_CDM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Lower Priority Ctx Switch RDM Enable: 0x%08x)", RGXFWIF_INICFG_OS_LOW_PRIO_CS_RDM);
+
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwOsDataMemDesc,
+                                                         offsetof(RGXFWIF_OSDATA, ui32FwOsConfigFlags),
+                                                         ui32FwOsCfgFlags,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+
+       {
+               PDUMP_FLAGS_T      ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+               IMG_UINT32         ui32AllPowUnitsMask = (1 << psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount) - 1;
+#if defined(SUPPORT_VALIDATION)
+               IMG_BOOL           bRunTimeUpdate = (RGX_GET_FEATURE_VALUE(psDevInfo, POWER_ISLAND_VERSION) == 1);
+#else
+               IMG_BOOL           bRunTimeUpdate = IMG_FALSE;
+#endif
+               IMG_UINT32         ui32DstOffset = psDevInfo->psRGXFWIfRuntimeCfgMemDesc->uiOffset + offsetof(RGXFWIF_RUNTIME_CFG, ui32PowUnitsStateMask);
+               IMG_CHAR           aszPowUnitsMaskRegVar[] = ":SYSMEM:$1";
+               IMG_CHAR           aszPowUnitsEnable[] = "RUNTIME_POW_UNITS_MASK";
+               PMR                *psPMR = (PMR *)(psDevInfo->psRGXFWIfRuntimeCfgMemDesc->psImport->hPMR);
+
+
+               if (bRunTimeUpdate)
+               {
+                       PDUMPIF(psDevInfo->psDeviceNode, aszPowUnitsEnable, ui32PDumpFlags);
+               }
+
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Load initial value power units mask in FW runtime configuration");
+               DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                                 ui32DstOffset,
+                                                                 psDevInfo->psRGXFWIfRuntimeCfg->ui32PowUnitsStateMask,
+                                                                 ui32PDumpFlags);
+
+               if (bRunTimeUpdate)
+               {
+                       PDUMPELSE(psDevInfo->psDeviceNode, aszPowUnitsEnable, ui32PDumpFlags);
+                       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags, "Read initial SPU mask value from HW registers");
+                       PDumpRegRead32ToInternalVar(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_SPU_ENABLE, aszPowUnitsMaskRegVar, ui32PDumpFlags);
+                       PDumpWriteVarANDValueOp(psDevInfo->psDeviceNode, aszPowUnitsMaskRegVar, ui32AllPowUnitsMask, ui32PDumpFlags);
+                       PDumpInternalVarToMemLabel(psPMR, ui32DstOffset, aszPowUnitsMaskRegVar, ui32PDumpFlags);
+                       PDUMPFI(psDevInfo->psDeviceNode, aszPowUnitsEnable, ui32PDumpFlags);
+               }
+       }
+
+#if defined(SUPPORT_SECURITY_VALIDATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Select one or more security tests here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Read/write FW private data from non-FW contexts: 0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_DATA);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Read/write FW code from non-FW contexts:         0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_READ_WRITE_FW_CODE);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Execute FW code from non-secure memory:          0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_NONSECURE);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Execute FW code from secure (non-FW) memory:     0x%08x)", RGXFWIF_SECURE_ACCESS_TEST_RUN_FROM_SECURE);
+
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                         offsetof(RGXFWIF_SYSINIT, ui32SecurityTestFlags),
+                                                         psDevInfo->psRGXFWIfSysInit->ui32SecurityTestFlags,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif /* defined(SUPPORT_SECURITY_VALIDATION) */
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PID filter type: %X=INCLUDE_ALL_EXCEPT, %X=EXCLUDE_ALL_EXCEPT)",
+                                RGXFW_PID_FILTER_INCLUDE_ALL_EXCEPT,
+                                RGXFW_PID_FILTER_EXCLUDE_ALL_EXCEPT);
+
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                         offsetof(RGXFWIF_SYSINIT, sPIDFilter.eMode),
+                                                         psDevInfo->psRGXFWIfSysInit->sPIDFilter.eMode,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PID filter PID/OSID list (Up to %u entries. Terminate with a zero PID))",
+                                RGXFWIF_PID_FILTER_MAX_NUM_PIDS);
+       {
+               IMG_UINT32 i;
+
+               /* generate a few WRWs in the pdump stream as an example */
+               for (i = 0; i < MIN(RGXFWIF_PID_FILTER_MAX_NUM_PIDS, 8); i++)
+               {
+                       /*
+                        * Some compilers cannot cope with the uses of offsetof() below - the specific problem being the use of
+                        * a non-const variable in the expression, which it needs to be const. Typical compiler output is
+                        * "expression must have a constant value".
+                        */
+                       const IMG_DEVMEM_OFFSET_T uiPIDOff
+                       = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_SYSINIT *)0)->sPIDFilter.asItems[i].uiPID);
+
+                       const IMG_DEVMEM_OFFSET_T uiOSIDOff
+                       = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_SYSINIT *)0)->sPIDFilter.asItems[i].ui32OSID);
+
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(PID and OSID pair %u)", i);
+
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(PID)");
+                       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                                         uiPIDOff,
+                                                                         0,
+                                                                         PDUMP_FLAGS_CONTINUOUS);
+
+                       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(OSID)");
+                       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                                         uiOSIDOff,
+                                                                         0,
+                                                                         PDUMP_FLAGS_CONTINUOUS);
+               }
+       }
+#if defined(SUPPORT_VALIDATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(Set the FW GEOM/3D Killing Control.)");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                                         offsetof(RGXFWIF_SYSDATA, ui32RenderKillingCtl),
+                                                         ui32RenderKillingCtl,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(Set the FW CDM/TDM Killing Control.)");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                                         offsetof(RGXFWIF_SYSDATA, ui32CDMTDMKillingCtl),
+                                                         ui32CDMTDMKillingCtl,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif /* defined(SUPPORT_VALIDATION) */
+       /*
+        * Dump the log config so it can be edited.
+        */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Set the log config here)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( Log Type: set bit 0 for TRACE, reset for TBI)");
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MAIN Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MAIN);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MTS Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MTS);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CLEANUP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CLEANUP);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( CSW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_CSW);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( BIF Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_BIF);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( PM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_PM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( RTD Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_RTD);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( SPM Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_SPM);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( POW Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_POW);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( HWR Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWR);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( HWP Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_HWP);
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
+       {
+               PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                        "( DMA Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DMA);
+       }
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( MISC Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_MISC);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "( DEBUG Group Enable: 0x%08x)", RGXFWIF_LOG_TYPE_GROUP_DEBUG);
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                                         offsetof(RGXFWIF_TRACEBUF, ui32LogType),
+                                                         psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Set the HWPerf Filter config here, see \"hwperfbin2jsont -h\"");
+       DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                         offsetof(RGXFWIF_SYSINIT, ui64HWPerfFilter),
+                                                         psDevInfo->psRGXFWIfSysInit->ui64HWPerfFilter,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "(Number of registers configurations for types(byte index): pow on(%d), dust change(%d), ta(%d), 3d(%d), cdm(%d), TDM(%d))",
+                                RGXFWIF_REG_CFG_TYPE_PWR_ON,
+                                RGXFWIF_REG_CFG_TYPE_DUST_CHANGE,
+                                RGXFWIF_REG_CFG_TYPE_TA,
+                                RGXFWIF_REG_CFG_TYPE_3D,
+                                RGXFWIF_REG_CFG_TYPE_CDM,
+                                RGXFWIF_REG_CFG_TYPE_TDM);
+
+       {
+               IMG_UINT32 i;
+
+               /* Write 32 bits in each iteration as required by PDUMP WRW command */
+               for (i = 0; i < RGXFWIF_REG_CFG_TYPE_ALL; i += sizeof(IMG_UINT32))
+               {
+                       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                                                       offsetof(RGXFWIF_REG_CFG, aui8NumRegsType[i]),
+                                                                       0,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+               }
+       }
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "(Set registers here: address, mask, value)");
+       DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                                         offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Addr),
+                                                         0,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+       DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                                         offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Mask),
+                                                         0,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+       DevmemPDumpLoadMemValue64(psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                                         offsetof(RGXFWIF_REG_CFG, asRegConfigs[0].ui64Value),
+                                                         0,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif /* SUPPORT_USER_REGISTER_CONFIGURATION */
+}
+#endif /* defined(PDUMP) */
+
+/*!
+*******************************************************************************
+ @Function    RGXSetupFwGuardPage
+
+ @Description Allocate a Guard Page at the start of a Guest's Main Heap
+
+ @Input       psDevceNode
+
+ @Return      PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupFwGuardPage(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       PVRSRV_ERROR eError;
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 (RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS |
+                                                                  PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN)),
+                                                                 OSGetPageSize(),
+                                                                 "FwGuardPage",
+                                                                 &psDevInfo->psRGXFWHeapGuardPageReserveMemDesc,
+                                                                 NULL,
+                                                                 NULL,
+                                                                 RFW_FWADDR_FLAG_NONE);
+
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXSetupFwSysData
+
+ @Description Sets up all system-wide firmware related data
+
+ @Input       psDevInfo
+
+ @Return      PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupFwSysData(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                                         IMG_BOOL                 bEnableSignatureChecks,
+                                                                         IMG_UINT32               ui32SignatureChecksBufSize,
+                                                                         IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                                                                         IMG_UINT64               ui64HWPerfFilter,
+                                                                         IMG_UINT32               ui32ConfigFlags,
+                                                                         IMG_UINT32               ui32ConfigFlagsExt,
+                                                                         IMG_UINT32               ui32LogType,
+                                                                         IMG_UINT32               ui32FilterFlags,
+                                                                         IMG_UINT32               ui32JonesDisableMask,
+                                                                         IMG_UINT32               ui32HWPerfCountersDataSize,
+                                                                         IMG_UINT32               ui32RenderKillingCtl,
+                                                                         IMG_UINT32               ui32CDMTDMKillingCtl,
+                                                                         IMG_UINT32               *pui32TPUTrilinearFracMask,
+                                                                         IMG_UINT32               *pui32USRMNumRegions,
+                                                                         IMG_UINT64               *pui64UVBRMNumRegions,
+                                                                         RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
+                                                                         FW_PERF_CONF             eFirmwarePerf,
+                                                                         IMG_UINT32               ui32AvailablePowUnitsMask,
+                                                                         IMG_UINT32               ui32AvailableRACMask)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32         ui32AllPowUnitsMask = (1 << psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount) - 1;
+       IMG_UINT32                      ui32AllRACMask = (1 << psDevInfo->sDevFeatureCfg.ui32MAXRACCount) - 1;
+       RGXFWIF_SYSINIT    *psFwSysInitScratch = NULL;
+#if defined(SUPPORT_VALIDATION)
+       /* Create AppHint reference handle for use in SUPPORT_VALIDATION case.
+        * This is freed on exit from this routine.
+        */
+       IMG_UINT32 ui32ApphintDefault = 0;
+       void *pvAppHintState = NULL;
+       OSCreateKMAppHintState(&pvAppHintState);
+#endif /* defined(SUPPORT_VALIDATION) */
+
+       psFwSysInitScratch = OSAllocZMem(sizeof(*psFwSysInitScratch));
+       PVR_LOG_GOTO_IF_NOMEM(psFwSysInitScratch, eError, fail);
+
+       /* Sys Fw init data */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                     (RGX_FWSHAREDMEM_CONFIG_ALLOCFLAGS |
+                                     PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED)) &
+                                     RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                     sizeof(RGXFWIF_SYSINIT),
+                                     "FwSysInitStructure",
+                                     &psDevInfo->psRGXFWIfSysInitMemDesc,
+                                     NULL,
+                                     (void**) &psDevInfo->psRGXFWIfSysInit,
+                                     RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware Sys Init structure allocation", fail);
+
+#if defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK)
+       /* Setup Fault read register */
+       eError = RGXSetupFaultReadRegister(psDeviceNode, psFwSysInitScratch);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Fault read register setup", fail);
+#endif
+
+#if defined(SUPPORT_AUTOVZ)
+       psFwSysInitScratch->ui32VzWdgPeriod = PVR_AUTOVZ_WDG_PERIOD_MS;
+#endif
+
+       /* RD Power Island */
+       {
+               RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+               IMG_BOOL bSysEnableRDPowIsland = psRGXData->psRGXTimingInfo->bEnableRDPowIsland;
+               IMG_BOOL bEnableRDPowIsland = ((eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_DEFAULT) && bSysEnableRDPowIsland) ||
+                                              (eRGXRDPowerIslandConf == RGX_RD_POWER_ISLAND_FORCE_ON);
+
+               ui32ConfigFlags |= bEnableRDPowIsland? RGXFWIF_INICFG_POW_RASCALDUST : 0;
+       }
+
+       /* Make sure to inform firmware if the device supports fullace fabric coherency */
+       ui32ConfigFlags |= (PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig) &&
+                           PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig)) ?
+                          RGXFWIF_INICFG_FABRIC_COHERENCY_ENABLED : 0;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       ui32ConfigFlags |= RGXFWIF_INICFG_WORKEST;
+#if defined(SUPPORT_PDVFS)
+       {
+               RGXFWIF_PDVFS_OPP   *psPDVFSOPPInfo;
+               IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg;
+
+               /* Pro-active DVFS depends on Workload Estimation */
+               psPDVFSOPPInfo = &psFwSysInitScratch->sPDVFSOPPInfo;
+               psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+               PVR_LOG_IF_FALSE(psDVFSDeviceCfg->pasOPPTable, "RGXSetupFwSysData: Missing OPP Table");
+
+               if (psDVFSDeviceCfg->pasOPPTable != NULL)
+               {
+                       if (psDVFSDeviceCfg->ui32OPPTableSize > ARRAY_SIZE(psPDVFSOPPInfo->asOPPValues))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: OPP Table too large: Size = %u, Maximum size = %lu",
+                                        __func__,
+                                        psDVFSDeviceCfg->ui32OPPTableSize,
+                                        (unsigned long)(ARRAY_SIZE(psPDVFSOPPInfo->asOPPValues))));
+                               eError = PVRSRV_ERROR_INVALID_PARAMS;
+                               goto fail;
+                       }
+
+                       OSDeviceMemCopy(psPDVFSOPPInfo->asOPPValues,
+                                       psDVFSDeviceCfg->pasOPPTable,
+                                       sizeof(psPDVFSOPPInfo->asOPPValues));
+
+                       psPDVFSOPPInfo->ui32MaxOPPPoint = psDVFSDeviceCfg->ui32OPPTableSize - 1;
+
+                       ui32ConfigFlags |= RGXFWIF_INICFG_PDVFS;
+               }
+       }
+#endif /* defined(SUPPORT_PDVFS) */
+#endif /* defined(SUPPORT_WORKLOAD_ESTIMATION) */
+
+       /* FW trace control structure */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 sizeof(RGXFWIF_TRACEBUF),
+                                                                 "FwTraceCtlStruct",
+                                                                 &psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                                                 &psFwSysInitScratch->sTraceBufCtl,
+                                                                 (void**) &psDevInfo->psRGXFWIfTraceBufCtl,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       if (!psDeviceNode->bAutoVzFwIsUp)
+       {
+               /* Set initial firmware log type/group(s) */
+               if (ui32LogType & ~RGXFWIF_LOG_TYPE_MASK)
+               {
+                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Invalid initial log type (0x%X)",
+                                __func__, ui32LogType));
+                       goto fail;
+               }
+               psDevInfo->psRGXFWIfTraceBufCtl->ui32LogType = ui32LogType;
+       }
+
+       /* When PDUMP is enabled, ALWAYS allocate on-demand trace buffer resource
+        * (irrespective of loggroup(s) enabled), given that logtype/loggroups can
+        * be set during PDump playback in logconfig, at any point of time,
+        * Otherwise, allocate only if required. */
+#if !defined(PDUMP)
+#if defined(SUPPORT_AUTOVZ)
+       /* always allocate trace buffer for AutoVz Host drivers to allow
+        * deterministic addresses of all SysData structures */
+       if ((PVRSRV_VZ_MODE_IS(HOST)) || (RGXTraceBufferIsInitRequired(psDevInfo)))
+#else
+       if (RGXTraceBufferIsInitRequired(psDevInfo))
+#endif
+#endif
+       {
+               eError = RGXTraceBufferInitOnDemandResources(psDevInfo,
+                                                                                                        RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS &
+                                                                                                        RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp));
+       }
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXTraceBufferInitOnDemandResources", fail);
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                     RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                     RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                     sizeof(RGXFWIF_SYSDATA),
+                                     "FwSysData",
+                                     &psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                     &psFwSysInitScratch->sFwSysData,
+                                     (void**) &psDevInfo->psRGXFWIfFwSysData,
+                                     RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       /* GPIO validation setup */
+       psFwSysInitScratch->eGPIOValidationMode = RGXFWIF_GPIO_VAL_OFF;
+#if defined(SUPPORT_VALIDATION)
+       {
+               IMG_INT32 ui32GPIOValidationMode;
+               ui32ApphintDefault = PVRSRV_APPHINT_GPIOVALIDATIONMODE;
+               /* Check AppHint for GPIO validation mode */
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                    pvAppHintState,
+                                    GPIOValidationMode,
+                                    &ui32ApphintDefault,
+                                    &ui32GPIOValidationMode);
+
+               if (ui32GPIOValidationMode >= RGXFWIF_GPIO_VAL_LAST)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Invalid GPIO validation mode: %d, only valid if smaller than %d. Disabling GPIO validation.",
+                               __func__,
+                               ui32GPIOValidationMode,
+                               RGXFWIF_GPIO_VAL_LAST));
+               }
+               else
+               {
+                       psFwSysInitScratch->eGPIOValidationMode = (RGXFWIF_GPIO_VAL_MODE) ui32GPIOValidationMode;
+               }
+
+               psFwSysInitScratch->eGPIOValidationMode = ui32GPIOValidationMode;
+       }
+
+//if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_STATE_PIN))
+       {
+               IMG_BOOL bGPUStatePin;
+               IMG_BOOL bApphintDefault = IMG_FALSE;
+               /* Check AppHint for GPU state pin */
+               OSGetKMAppHintBOOL(APPHINT_NO_DEVICE,
+                                  pvAppHintState,
+                                  GPUStatePin,
+                                  &bApphintDefault,
+                                  &bGPUStatePin);
+
+               psDevInfo->ui32ValidationFlags |= (bGPUStatePin) ? RGX_VAL_GPUSTATEPIN_EN : 0;
+       }
+
+       {
+               IMG_UINT32 ui32EnablePollOnChecksumErrorStatus;
+               ui32ApphintDefault = 0;
+
+               /* Check AppHint for polling on GPU Checksum status */
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                                    pvAppHintState,
+                                    EnablePollOnChecksumErrorStatus,
+                                    &ui32ApphintDefault,
+                                    &ui32EnablePollOnChecksumErrorStatus);
+
+               switch (ui32EnablePollOnChecksumErrorStatus)
+               {
+                       case 0: /* no checking */ break;
+                       case 1: psDevInfo->ui32ValidationFlags |= RGX_VAL_FBDC_SIG_CHECK_NOERR_EN; break;
+                       case 2: psDevInfo->ui32ValidationFlags |= RGX_VAL_FBDC_SIG_CHECK_ERR_EN; break;
+                       case 3: psDevInfo->ui32ValidationFlags |= RGX_VAL_KZ_SIG_CHECK_NOERR_EN; break;
+                       case 4: psDevInfo->ui32ValidationFlags |= RGX_VAL_KZ_SIG_CHECK_ERR_EN; break;
+                       default:
+                               PVR_DPF((PVR_DBG_WARNING, "Unsupported value in EnablePollOnChecksumErrorStatus (%d)", ui32EnablePollOnChecksumErrorStatus));
+                               break;
+               }
+       }
+
+       /* Check AppHint for power island transition interval */
+       ui32ApphintDefault = 0;
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE,
+                            pvAppHintState,
+                            PowerDomainKickInterval,
+                            &ui32ApphintDefault,
+                            &psDevInfo->ui32PowDomainKickInterval);
+
+#if defined(SUPPORT_RAY_TRACING)
+       {
+               IMG_UINT64 ui64RCEDisableMask;
+               IMG_UINT64 ui64ApphintDefault = PVRSRV_APPHINT_RCEDISABLEMASK;
+               OSGetKMAppHintUINT64(APPHINT_NO_DEVICE,
+                                    pvAppHintState,
+                                    RCEDisableMask,
+                                    &ui64ApphintDefault,
+                                    &ui64RCEDisableMask);
+               psFwSysInitScratch->ui64RCEDisableMask = ui64RCEDisableMask;
+
+       }
+#endif
+
+#endif /* defined(SUPPORT_VALIDATION) */
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+       eError = RGXFWSetupFirmwareGcovBuffer(psDevInfo,
+                                             &psDevInfo->psFirmwareGcovBufferMemDesc,
+                                             RGXFWIF_FIRMWARE_GCOV_BUFFER_SIZE,
+                                             &psFwSysInitScratch->sFirmwareGcovCtl,
+                                             "FirmwareGcovBuffer");
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware GCOV buffer allocation", fail);
+       psDevInfo->ui32FirmwareGcovSize = RGXFWIF_FIRMWARE_GCOV_BUFFER_SIZE;
+#endif /* defined(SUPPORT_FIRMWARE_GCOV) */
+
+#if defined(PDUMP)
+       /* Require a minimum amount of memory for the signature buffers */
+       if (ui32SignatureChecksBufSize < RGXFW_SIG_BUFFER_SIZE_MIN)
+       {
+               ui32SignatureChecksBufSize = RGXFW_SIG_BUFFER_SIZE_MIN;
+       }
+
+       /* Setup Signature and Checksum Buffers for TDM, GEOM, 3D and CDM */
+       eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                          &psDevInfo->psRGXFWSigTDMChecksMemDesc,
+                                          ui32SignatureChecksBufSize,
+                                          &psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_TDM]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "TDM Signature check setup", fail);
+       psDevInfo->ui32SigTDMChecksSize = ui32SignatureChecksBufSize;
+
+       eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                          &psDevInfo->psRGXFWSigTAChecksMemDesc,
+                                          ui32SignatureChecksBufSize,
+                                          &psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_GEOM]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "GEOM Signature check setup", fail);
+       psDevInfo->ui32SigTAChecksSize = ui32SignatureChecksBufSize;
+
+       eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                          &psDevInfo->psRGXFWSig3DChecksMemDesc,
+                                          ui32SignatureChecksBufSize,
+                                          &psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_3D]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "3D Signature check setup", fail);
+       psDevInfo->ui32Sig3DChecksSize = ui32SignatureChecksBufSize;
+
+       eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                          &psDevInfo->psRGXFWSigCDMChecksMemDesc,
+                                          ui32SignatureChecksBufSize,
+                                          &psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_CDM]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "CDM Signature check setup", fail);
+       psDevInfo->ui32SigCDMChecksSize = ui32SignatureChecksBufSize;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 1)
+       {
+               eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                                  &psDevInfo->psRGXFWSigRDMChecksMemDesc,
+                                                  ui32SignatureChecksBufSize,
+                                                  &psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_RAY]);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RDM Signature check setup", fail);
+               psDevInfo->ui32SigRDMChecksSize = ui32SignatureChecksBufSize;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       eError = RGXFWSetupSignatureChecks(psDevInfo,
+                                          &psDevInfo->psRGXFWValidationSigMemDesc,
+                                          ui32SignatureChecksBufSize,
+                                          &psFwSysInitScratch->asValidationSigBufCtl[RGXFWIF_DM_3D]);
+       psFwSysInitScratch->asValidationSigBufCtl[RGXFWIF_DM_CDM] = psFwSysInitScratch->asValidationSigBufCtl[RGXFWIF_DM_3D];
+       PVR_LOG_GOTO_IF_ERROR(eError, "FBCDC/TRP/WGP Signature check setup", fail);
+       psDevInfo->ui32ValidationSigSize = ui32SignatureChecksBufSize;
+#endif
+#endif
+
+       if (!bEnableSignatureChecks)
+       {
+               psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_TDM].sBuffer.ui32Addr = 0x0;
+               psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_GEOM].sBuffer.ui32Addr = 0x0;
+               psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_3D].sBuffer.ui32Addr = 0x0;
+               psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_CDM].sBuffer.ui32Addr = 0x0;
+               psFwSysInitScratch->asSigBufCtl[RGXFWIF_DM_RAY].sBuffer.ui32Addr = 0x0;
+       }
+
+       eError = RGXFWSetupAlignChecks(psDeviceNode,
+                                      &psFwSysInitScratch->sAlignChecks);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Alignment checks setup", fail);
+
+       psFwSysInitScratch->ui32FilterFlags = ui32FilterFlags;
+
+       /* Fill the remaining bits of fw the init data */
+       psFwSysInitScratch->sPDSExecBase.uiAddr = RGX_PDSCODEDATA_HEAP_BASE;
+       psFwSysInitScratch->sUSCExecBase.uiAddr = RGX_USCCODE_HEAP_BASE;
+       psFwSysInitScratch->sFBCDCStateTableBase.uiAddr = RGX_FBCDC_HEAP_BASE;
+       psFwSysInitScratch->sFBCDCLargeStateTableBase.uiAddr = RGX_FBCDC_LARGE_HEAP_BASE;
+       psFwSysInitScratch->sTextureHeapBase.uiAddr = RGX_TEXTURE_STATE_HEAP_BASE;
+       psFwSysInitScratch->sPDSIndirectHeapBase.uiAddr = RGX_PDS_INDIRECT_STATE_HEAP_BASE;
+
+       psFwSysInitScratch->ui32JonesDisableMask = ui32JonesDisableMask;
+
+       eError = _AllocateSLC3Fence(psDevInfo, psFwSysInitScratch);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SLC3Fence memory allocation", fail);
+
+#if defined(SUPPORT_PDVFS)
+       /* Core clock rate */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                     RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS &
+                                     RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                     sizeof(IMG_UINT32),
+                                     "FwPDVFSCoreClkRate",
+                                     &psDevInfo->psRGXFWIFCoreClkRateMemDesc,
+                                     &psFwSysInitScratch->sCoreClockRate,
+                                     (void**) &psDevInfo->pui32RGXFWIFCoreClkRate,
+                                     RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PDVFS core clock rate memory setup", fail);
+#endif
+       {
+       /* Timestamps */
+       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags =
+               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) |
+               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+               PVRSRV_MEMALLOCFLAG_GPU_READABLE | /* XXX ?? */
+               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+               PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+               PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC;
+
+       /*
+         the timer query arrays
+       */
+       PDUMPCOMMENT(psDeviceNode, "Allocate timer query arrays (FW)");
+       eError = DevmemFwAllocate(psDevInfo,
+                                 sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
+                                 uiMemAllocFlags |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+                                 "FwStartTimesArray",
+                                 & psDevInfo->psStartTimeMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map start times array",
+                               __func__));
+               goto fail;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psStartTimeMemDesc,
+                                         (void **)& psDevInfo->pui64StartTimeById);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map start times array",
+                               __func__));
+               goto fail;
+       }
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                 sizeof(IMG_UINT64) * RGX_MAX_TIMER_QUERIES,
+                                 uiMemAllocFlags |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE,
+                                 "FwEndTimesArray",
+                                 & psDevInfo->psEndTimeMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map end times array",
+                               __func__));
+               goto fail;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psEndTimeMemDesc,
+                                         (void **)& psDevInfo->pui64EndTimeById);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map end times array",
+                               __func__));
+               goto fail;
+       }
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                 sizeof(IMG_UINT32) * RGX_MAX_TIMER_QUERIES,
+                                 uiMemAllocFlags,
+                                 "FwCompletedOpsArray",
+                                 & psDevInfo->psCompletedMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to completed ops array",
+                               __func__));
+               goto fail;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psCompletedMemDesc,
+                                         (void **)& psDevInfo->pui32CompletedById);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map completed ops array",
+                               __func__));
+               goto fail;
+       }
+
+#if !defined(PVRSRV_USE_BRIDGE_LOCK)
+       eError = OSLockCreate(&psDevInfo->hTimerQueryLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate log for timer query",
+                               __func__));
+               goto fail;
+       }
+#endif
+       }
+#if defined(SUPPORT_TBI_INTERFACE)
+#if !defined(PDUMP)
+       /* allocate only if required */
+       if (RGXTBIBufferIsInitRequired(psDevInfo))
+#endif /* !defined(PDUMP) */
+       {
+               /* When PDUMP is enabled, ALWAYS allocate on-demand TBI buffer resource
+                * (irrespective of loggroup(s) enabled), given that logtype/loggroups
+                * can be set during PDump playback in logconfig, at any point of time
+                */
+               eError = RGXTBIBufferInitOnDemandResources(psDevInfo);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXTBIBufferInitOnDemandResources", fail);
+       }
+
+       psFwSysInitScratch->sTBIBuf = psDevInfo->sRGXFWIfTBIBuffer;
+#endif /* defined(SUPPORT_TBI_INTERFACE) */
+
+       /* Allocate shared buffer for GPU utilisation */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 sizeof(RGXFWIF_GPU_UTIL_FWCB),
+                                                                 "FwGPUUtilisationBuffer",
+                                                                 &psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc,
+                                                                 &psFwSysInitScratch->sGpuUtilFWCbCtl,
+                                                                 (void**) &psDevInfo->psRGXFWIfGpuUtilFWCb,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "GPU Utilisation Buffer ctl allocation", fail);
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 sizeof(RGXFWIF_RUNTIME_CFG),
+                                                                 "FwRuntimeCfg",
+                                                                 &psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                                 &psFwSysInitScratch->sRuntimeCfg,
+                                                                 (void**) &psDevInfo->psRGXFWIfRuntimeCfg,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware runtime configuration memory allocation", fail);
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 sizeof(RGXFWIF_REG_CFG),
+                                                                 "FwRegisterConfigStructure",
+                                                                 &psDevInfo->psRGXFWIfRegCfgMemDesc,
+                                                                 &psFwSysInitScratch->sRegCfg,
+                                                                 NULL,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware register user configuration structure allocation", fail);
+#endif
+
+       psDevInfo->ui32RGXFWIfHWPerfBufSize = GetHwPerfBufferSize(ui32HWPerfFWBufSizeKB);
+       /* Second stage initialisation or HWPerf, hHWPerfLock created in first
+        * stage. See RGXRegisterDevice() call to RGXHWPerfInit(). */
+       if (psDevInfo->ui64HWPerfFilter == 0)
+       {
+               psDevInfo->ui64HWPerfFilter = ui64HWPerfFilter;
+               psFwSysInitScratch->ui64HWPerfFilter = ui64HWPerfFilter;
+       }
+       else
+       {
+               /* The filter has already been modified. This can happen if
+                * pvr/apphint/EnableFTraceGPU was enabled. */
+               psFwSysInitScratch->ui64HWPerfFilter = psDevInfo->ui64HWPerfFilter;
+       }
+
+#if !defined(PDUMP)
+       /* Allocate if HWPerf filter has already been set. This is possible either
+        * by setting a proper AppHint or enabling GPU ftrace events. */
+       if (psDevInfo->ui64HWPerfFilter != 0)
+#endif
+       {
+               /* When PDUMP is enabled, ALWAYS allocate on-demand HWPerf resources
+                * (irrespective of HWPerf enabled or not), given that HWPerf can be
+                * enabled during PDump playback via RTCONF at any point of time. */
+               eError = RGXHWPerfInitOnDemandResources(psDevInfo);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfInitOnDemandResources", fail);
+#if defined(SUPPORT_POWMON_COMPONENT) && defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+               if (RGXPowmonBufferIsInitRequired(psDevInfo))
+               {
+                       /* Allocate power monitoring log buffer if enabled */
+                       eError = RGXPowmonBufferInitOnDemandResources(psDevInfo);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXPowmonBufferInitOnDemandResources", fail);
+               }
+#endif
+       }
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS &
+                                                                 RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp),
+                                                                 ui32HWPerfCountersDataSize,
+                                                                 "FwHWPerfControlStructure",
+                                                                 &psDevInfo->psRGXFWIfHWPerfCountersMemDesc,
+                                                                 &psFwSysInitScratch->sHWPerfCtl,
+                                                                 NULL,
+                                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware HW Perf control struct allocation", fail);
+
+       psDevInfo->bPDPEnabled = (ui32ConfigFlags & RGXFWIF_INICFG_DISABLE_PDP_EN)
+                                                         ? IMG_FALSE : IMG_TRUE;
+
+       psFwSysInitScratch->eFirmwarePerf = eFirmwarePerf;
+
+#if defined(PDUMP)
+       /* default: no filter */
+       psFwSysInitScratch->sPIDFilter.eMode = RGXFW_PID_FILTER_INCLUDE_ALL_EXCEPT;
+       psFwSysInitScratch->sPIDFilter.asItems[0].uiPID = 0;
+#endif
+
+#if defined(SUPPORT_VALIDATION)
+       {
+               IMG_UINT32 dm;
+
+               /* TPU trilinear rounding mask override */
+               for (dm = 0; dm < RGXFWIF_TPU_DM_LAST; dm++)
+               {
+                       psFwSysInitScratch->aui32TPUTrilinearFracMask[dm] = pui32TPUTrilinearFracMask[dm];
+               }
+
+               /* USRM Config override */
+               for (dm = 0; dm < RGXFWIF_USRM_DM_LAST; dm++)
+               {
+                       psFwSysInitScratch->aui32USRMNumRegions[dm] = pui32USRMNumRegions[dm];
+               }
+
+               /* UVBRM Config override */
+               for (dm = 0; dm < RGXFWIF_UVBRM_DM_LAST; dm++)
+               {
+                       psFwSysInitScratch->aui64UVBRMNumRegions[dm] = pui64UVBRMNumRegions[dm];
+               }
+       }
+#endif
+
+#if defined(SUPPORT_SECURITY_VALIDATION)
+       {
+               PVRSRV_MEMALLOCFLAGS_T uiFlags = RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS;
+               PVRSRV_SET_PHYS_HEAP_HINT(GPU_SECURE, uiFlags);
+
+               PDUMPCOMMENT(psDeviceNode, "Allocate non-secure buffer for security validation test");
+               eError = DevmemFwAllocateExportable(psDeviceNode,
+                                                                                       OSGetPageSize(),
+                                                                                       OSGetPageSize(),
+                                                                                       RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS,
+                                                                                       "FwExNonSecureBuffer",
+                                                                                       &psDevInfo->psRGXFWIfNonSecureBufMemDesc);
+               PVR_LOG_GOTO_IF_ERROR(eError, "Non-secure buffer allocation", fail);
+
+               eError = RGXSetFirmwareAddress(&psFwSysInitScratch->pbNonSecureBuffer,
+                                                                          psDevInfo->psRGXFWIfNonSecureBufMemDesc,
+                                                                          0, RFW_FWADDR_NOREF_FLAG);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", fail);
+
+               PDUMPCOMMENT(psDeviceNode, "Allocate secure buffer for security validation test");
+               eError = DevmemFwAllocateExportable(psDeviceNode,
+                                                                                       OSGetPageSize(),
+                                                                                       OSGetPageSize(),
+                                                                                       uiFlags,
+                                                                                       "FwExSecureBuffer",
+                                                                                       &psDevInfo->psRGXFWIfSecureBufMemDesc);
+               PVR_LOG_GOTO_IF_ERROR(eError, "Secure buffer allocation", fail);
+
+               eError = RGXSetFirmwareAddress(&psFwSysInitScratch->pbSecureBuffer,
+                                                                          psDevInfo->psRGXFWIfSecureBufMemDesc,
+                                                                          0, RFW_FWADDR_NOREF_FLAG);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", fail);
+       }
+#endif /* SUPPORT_SECURITY_VALIDATION */
+
+       /* Initialize FW started flag */
+       psFwSysInitScratch->bFirmwareStarted = IMG_FALSE;
+       psFwSysInitScratch->ui32MarkerVal = 1;
+
+       if (!psDeviceNode->bAutoVzFwIsUp)
+       {
+               IMG_UINT32 ui32OSIndex;
+
+               RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+               RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+
+               /* Required info by FW to calculate the ActivePM idle timer latency */
+               psFwSysInitScratch->ui32InitialCoreClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+               psFwSysInitScratch->ui32InitialActivePMLatencyms = psRGXData->psRGXTimingInfo->ui32ActivePMLatencyms;
+
+               /* Initialise variable runtime configuration to the system defaults */
+               psRuntimeCfg->ui32CoreClockSpeed = psFwSysInitScratch->ui32InitialCoreClockSpeed;
+               psRuntimeCfg->ui32ActivePMLatencyms = psFwSysInitScratch->ui32InitialActivePMLatencyms;
+               psRuntimeCfg->bActivePMLatencyPersistant = IMG_TRUE;
+               psRuntimeCfg->ui32WdgPeriodUs = RGXFW_SAFETY_WATCHDOG_PERIOD_IN_US;
+               psRuntimeCfg->ui32HCSDeadlineMS = RGX_HCS_DEFAULT_DEADLINE_MS;
+
+               if (PVRSRV_VZ_MODE_IS(NATIVE))
+               {
+                       psRuntimeCfg->aui32OSidPriority[RGXFW_HOST_OS] = 0;
+               }
+               else
+               {
+                       for (ui32OSIndex = 0; ui32OSIndex < RGX_NUM_OS_SUPPORTED; ui32OSIndex++)
+                       {
+                               const IMG_INT32 ai32DefaultOsPriority[RGXFW_MAX_NUM_OS] =
+                                       {RGX_OSID_0_DEFAULT_PRIORITY, RGX_OSID_1_DEFAULT_PRIORITY, RGX_OSID_2_DEFAULT_PRIORITY, RGX_OSID_3_DEFAULT_PRIORITY,
+                                        RGX_OSID_4_DEFAULT_PRIORITY, RGX_OSID_5_DEFAULT_PRIORITY, RGX_OSID_6_DEFAULT_PRIORITY, RGX_OSID_7_DEFAULT_PRIORITY};
+
+                               /* Set up initial priorities between different OSes */
+                               psRuntimeCfg->aui32OSidPriority[ui32OSIndex] = (IMG_UINT32)ai32DefaultOsPriority[ui32OSIndex];
+                       }
+               }
+
+#if defined(PVR_ENABLE_PHR) && defined(PDUMP)
+               psRuntimeCfg->ui32PHRMode = RGXFWIF_PHR_MODE_RD_RESET;
+#else
+               psRuntimeCfg->ui32PHRMode = 0;
+#endif
+
+               /* Validate the power units mask and initialize to number of units to power up */
+               if ((ui32AvailablePowUnitsMask & ui32AllPowUnitsMask) == 0)
+               {
+                       eError = PVRSRV_ERROR_INVALID_SPU_MASK;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s:Invalid power units mask (All=0x%X, Non Fused=0x%X). At-least one power unit must to be powered up.",
+                                __func__,
+                                ui32AllPowUnitsMask,
+                                ui32AvailablePowUnitsMask));
+                       goto fail;
+               }
+               psRuntimeCfg->ui32PowUnitsStateMask = ui32AvailablePowUnitsMask & ui32AllPowUnitsMask;
+
+               psRuntimeCfg->ui32RACStateMask = ui32AvailableRACMask & ui32AllRACMask;
+
+               /* flush write buffers for psDevInfo->psRGXFWIfRuntimeCfg */
+               OSWriteMemoryBarrier(psDevInfo->psRGXFWIfRuntimeCfg);
+
+               /* Setup FW coremem data */
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META_COREMEM_SIZE))
+               {
+                       psFwSysInitScratch->sCorememDataStore.pbyFWAddr = psDevInfo->sFWCorememDataStoreFWAddr;
+
+                       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
+                       {
+                               RGXSetMetaDMAAddress(&psFwSysInitScratch->sCorememDataStore,
+                                                                        psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+                                                                        &psFwSysInitScratch->sCorememDataStore.pbyFWAddr,
+                                                                        0);
+                       }
+               }
+
+               psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags    = ui32ConfigFlags    & RGXFWIF_INICFG_ALL;
+               psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlagsExt = ui32ConfigFlagsExt & RGXFWIF_INICFG_EXT_ALL;
+#if defined(SUPPORT_VALIDATION)
+               psDevInfo->psRGXFWIfFwSysData->ui32RenderKillingCtl     = ui32RenderKillingCtl;
+               psDevInfo->psRGXFWIfFwSysData->ui32CDMTDMKillingCtl     = ui32CDMTDMKillingCtl;
+#else
+               PVR_UNREFERENCED_PARAMETER(ui32RenderKillingCtl);
+               PVR_UNREFERENCED_PARAMETER(ui32CDMTDMKillingCtl);
+#endif
+
+               /* Initialise GPU utilisation buffer */
+               psDevInfo->psRGXFWIfGpuUtilFWCb->ui64LastWord =
+                   RGXFWIF_GPU_UTIL_MAKE_WORD(OSClockns64(),RGXFWIF_GPU_UTIL_STATE_IDLE);
+
+               /* init HWPERF data */
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfRIdx = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfWIdx = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfWrapCount = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfSize = psDevInfo->ui32RGXFWIfHWPerfBufSize;
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfUt = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32HWPerfDropCount = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32FirstDropOrdinal = 0;
+               psDevInfo->psRGXFWIfFwSysData->ui32LastDropOrdinal = 0;
+
+               // flush write buffers for psRGXFWIfFwSysData
+               OSWriteMemoryBarrier(psDevInfo->psRGXFWIfFwSysData);
+
+               /*Send through the BVNC Feature Flags*/
+               eError = RGXServerFeatureFlagsToHWPerfFlags(psDevInfo, &psFwSysInitScratch->sBvncKmFeatureFlags);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXServerFeatureFlagsToHWPerfFlags", fail);
+
+               /* populate the real FwOsInit structure with the values stored in the scratch copy */
+               OSCachedMemCopyWMB(psDevInfo->psRGXFWIfSysInit, psFwSysInitScratch, sizeof(RGXFWIF_SYSINIT));
+       }
+
+       OSFreeMem(psFwSysInitScratch);
+
+#if defined(SUPPORT_VALIDATION)
+       OSFreeKMAppHintState(pvAppHintState);
+#endif
+
+       return PVRSRV_OK;
+
+fail:
+       if (psFwSysInitScratch)
+       {
+               OSFreeMem(psFwSysInitScratch);
+       }
+
+       RGXFreeFwSysData(psDevInfo);
+
+       PVR_ASSERT(eError != PVRSRV_OK);
+#if defined(SUPPORT_VALIDATION)
+       OSFreeKMAppHintState(pvAppHintState);
+#endif
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXSetupFwOsData
+
+ @Description Sets up all os-specific firmware related data
+
+ @Input       psDevInfo
+
+ @Return      PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXSetupFwOsData(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                                        IMG_UINT32               ui32KCCBSizeLog2,
+                                                                        IMG_UINT32               ui32HWRDebugDumpLimit,
+                                                                        IMG_UINT32               ui32FwOsCfgFlags)
+{
+       PVRSRV_ERROR       eError;
+       RGXFWIF_OSINIT     sFwOsInitScratch;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       OSCachedMemSet(&sFwOsInitScratch, 0, sizeof(RGXFWIF_OSINIT));
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = RGXSetupFwGuardPage(psDevInfo);
+               PVR_LOG_GOTO_IF_ERROR(eError, "Setting up firmware heap guard pages", fail);
+       }
+
+       /* Memory tracking the connection state should be non-volatile and
+        * is not cleared on allocation to prevent loss of pre-reset information */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CONFIG_ALLOCFLAGS &
+                                                                 ~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC,
+                                                                 sizeof(RGXFWIF_CONNECTION_CTL),
+                                                                 "FwConnectionCtl",
+                                                                 &psDevInfo->psRGXFWIfConnectionCtlMemDesc,
+                                                                 NULL,
+                                                                 (void**) &psDevInfo->psRGXFWIfConnectionCtl,
+                                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware Connection Control structure allocation", fail);
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_CONFIG_ALLOCFLAGS |
+                                                                 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED),
+                                                                 sizeof(RGXFWIF_OSINIT),
+                                                                 "FwOsInitStructure",
+                                                                 &psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                 NULL,
+                                                                 (void**) &psDevInfo->psRGXFWIfOsInit,
+                                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware Os Init structure allocation", fail);
+
+       /* init HWR frame info */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
+                                                                 sizeof(RGXFWIF_HWRINFOBUF),
+                                                                 "FwHWRInfoBuffer",
+                                                                 &psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc,
+                                                                 &sFwOsInitScratch.sRGXFWIfHWRInfoBufCtl,
+                                                                 (void**) &psDevInfo->psRGXFWIfHWRInfoBufCtl,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "HWR Info Buffer allocation", fail);
+
+       OSCachedMemSetWMB(psDevInfo->psRGXFWIfHWRInfoBufCtl, 0, sizeof(RGXFWIF_HWRINFOBUF));
+
+       /* Allocate a sync for power management */
+       eError = SyncPrimContextCreate(psDevInfo->psDeviceNode,
+                                      &psDevInfo->hSyncPrimContext);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Sync primitive context allocation", fail);
+
+       eError = SyncPrimAlloc(psDevInfo->hSyncPrimContext, &psDevInfo->psPowSyncPrim, "fw power ack");
+       PVR_LOG_GOTO_IF_ERROR(eError, "Sync primitive allocation", fail);
+
+       /* Set up kernel CCB */
+       eError = RGXSetupCCB(psDevInfo,
+                                                &psDevInfo->psKernelCCBCtl,
+                                                &psDevInfo->psKernelCCBCtlMemDesc,
+                                                &psDevInfo->psKernelCCB,
+                                                &psDevInfo->psKernelCCBMemDesc,
+                                                &sFwOsInitScratch.psKernelCCBCtl,
+                                                &sFwOsInitScratch.psKernelCCB,
+                                                ui32KCCBSizeLog2,
+                                                sizeof(RGXFWIF_KCCB_CMD),
+                                                (RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS |
+                                                PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED)),
+                                                "FwKernelCCB");
+       PVR_LOG_GOTO_IF_ERROR(eError, "Kernel CCB allocation", fail);
+
+       /* KCCB additionally uses a return slot array for FW to be able to send back
+        * return codes for each required command
+        */
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
+                                                                 (1U << ui32KCCBSizeLog2) * sizeof(IMG_UINT32),
+                                                                 "FwKernelCCBRtnSlots",
+                                                                 &psDevInfo->psKernelCCBRtnSlotsMemDesc,
+                                                                 &sFwOsInitScratch.psKernelCCBRtnSlots,
+                                                                 (void**) &psDevInfo->pui32KernelCCBRtnSlots,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Kernel CCB return slot array allocation", fail);
+
+       /* Set up firmware CCB */
+       eError = RGXSetupCCB(psDevInfo,
+                                                &psDevInfo->psFirmwareCCBCtl,
+                                                &psDevInfo->psFirmwareCCBCtlMemDesc,
+                                                &psDevInfo->psFirmwareCCB,
+                                                &psDevInfo->psFirmwareCCBMemDesc,
+                                                &sFwOsInitScratch.psFirmwareCCBCtl,
+                                                &sFwOsInitScratch.psFirmwareCCB,
+                                                RGXFWIF_FWCCB_NUMCMDS_LOG2,
+                                                sizeof(RGXFWIF_FWCCB_CMD),
+                                                RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS,
+                                                "FwCCB");
+       PVR_LOG_GOTO_IF_ERROR(eError, "Firmware CCB allocation", fail);
+
+       eError = RGXSetupFwAllocation(psDevInfo,
+                                                                 RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS,
+                                                                 sizeof(RGXFWIF_OSDATA),
+                                                                 "FwOsData",
+                                                                 &psDevInfo->psRGXFWIfFwOsDataMemDesc,
+                                                                 &sFwOsInitScratch.sFwOsData,
+                                                                 (void**) &psDevInfo->psRGXFWIfFwOsData,
+                                                                 RFW_FWADDR_NOREF_FLAG);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetupFwAllocation", fail);
+
+       psDevInfo->psRGXFWIfFwOsData->ui32FwOsConfigFlags = ui32FwOsCfgFlags & RGXFWIF_INICFG_OS_ALL;
+
+       eError = SyncPrimGetFirmwareAddr(psDevInfo->psPowSyncPrim, &psDevInfo->psRGXFWIfFwOsData->sPowerSync.ui32Addr);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Get Sync Prim FW address", fail);
+
+       /* flush write buffers for psRGXFWIfFwOsData */
+       OSWriteMemoryBarrier(psDevInfo->psRGXFWIfFwOsData);
+
+       sFwOsInitScratch.ui32HWRDebugDumpLimit = ui32HWRDebugDumpLimit;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Set up Workload Estimation firmware CCB */
+       eError = RGXSetupCCB(psDevInfo,
+                                                &psDevInfo->psWorkEstFirmwareCCBCtl,
+                                                &psDevInfo->psWorkEstFirmwareCCBCtlMemDesc,
+                                                &psDevInfo->psWorkEstFirmwareCCB,
+                                                &psDevInfo->psWorkEstFirmwareCCBMemDesc,
+                                                &sFwOsInitScratch.psWorkEstFirmwareCCBCtl,
+                                                &sFwOsInitScratch.psWorkEstFirmwareCCB,
+                                                RGXFWIF_WORKEST_FWCCB_NUMCMDS_LOG2,
+                                                sizeof(RGXFWIF_WORKEST_FWCCB_CMD),
+                                                RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS,
+                                                "FwWEstCCB");
+       PVR_LOG_GOTO_IF_ERROR(eError, "Workload Estimation Firmware CCB allocation", fail);
+#endif /* defined(SUPPORT_WORKLOAD_ESTIMATION) */
+
+       /* Initialise the compatibility check data */
+       RGXFWIF_COMPCHECKS_BVNC_INIT(sFwOsInitScratch.sRGXCompChecks.sFWBVNC);
+       RGXFWIF_COMPCHECKS_BVNC_INIT(sFwOsInitScratch.sRGXCompChecks.sHWBVNC);
+
+       /* populate the real FwOsInit structure with the values stored in the scratch copy */
+       OSCachedMemCopyWMB(psDevInfo->psRGXFWIfOsInit, &sFwOsInitScratch, sizeof(RGXFWIF_OSINIT));
+
+       return PVRSRV_OK;
+
+fail:
+       RGXFreeFwOsData(psDevInfo);
+
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXSetupFirmware
+
+ @Description Sets up all firmware related data
+
+ @Input       psDevInfo
+
+ @Return      PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXSetupFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                         IMG_BOOL                 bEnableSignatureChecks,
+                                                         IMG_UINT32               ui32SignatureChecksBufSize,
+                                                         IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                                                         IMG_UINT64               ui64HWPerfFilter,
+                                                         IMG_UINT32               ui32ConfigFlags,
+                                                         IMG_UINT32               ui32ConfigFlagsExt,
+                                                         IMG_UINT32               ui32FwOsCfgFlags,
+                                                         IMG_UINT32               ui32LogType,
+                                                         IMG_UINT32               ui32FilterFlags,
+                                                         IMG_UINT32               ui32JonesDisableMask,
+                                                         IMG_UINT32               ui32HWRDebugDumpLimit,
+                                                         IMG_UINT32               ui32HWPerfCountersDataSize,
+                                                         IMG_UINT32               ui32RenderKillingCtl,
+                                                         IMG_UINT32               ui32CDMTDMKillingCtl,
+                                                         IMG_UINT32               *pui32TPUTrilinearFracMask,
+                                                         IMG_UINT32               *pui32USRMNumRegions,
+                                                         IMG_UINT64               *pui64UVBRMNumRegions,
+                                                         RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
+                                                         FW_PERF_CONF             eFirmwarePerf,
+                                                         IMG_UINT32               ui32KCCBSizeLog2,
+                                                         IMG_UINT32               ui32AvailablePowUnitsMask,
+                                                         IMG_UINT32               ui32AvailableRACMask)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       eError = RGXSetupFwOsData(psDeviceNode,
+                                                         ui32KCCBSizeLog2,
+                                                         ui32HWRDebugDumpLimit,
+                                                         ui32FwOsCfgFlags);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Setting up firmware os data", fail);
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               /* Guest drivers do not configure system-wide firmware data */
+               psDevInfo->psRGXFWIfSysInit = NULL;
+       }
+       else
+       {
+               /* Native and Host drivers must initialise the firmware's system data */
+               eError = RGXSetupFwSysData(psDeviceNode,
+                                                                  bEnableSignatureChecks,
+                                                                  ui32SignatureChecksBufSize,
+                                                                  ui32HWPerfFWBufSizeKB,
+                                                                  ui64HWPerfFilter,
+                                                                  ui32ConfigFlags,
+                                                                  ui32ConfigFlagsExt,
+                                                                  ui32LogType,
+                                                                  ui32FilterFlags,
+                                                                  ui32JonesDisableMask,
+                                                                  ui32HWPerfCountersDataSize,
+                                                                  ui32RenderKillingCtl,
+                                                                  ui32CDMTDMKillingCtl,
+                                                                  pui32TPUTrilinearFracMask,
+                                                                  pui32USRMNumRegions,
+                                                                  pui64UVBRMNumRegions,
+                                                                  eRGXRDPowerIslandConf,
+                                                                  eFirmwarePerf,
+                                                                  ui32AvailablePowUnitsMask,
+                                                                  ui32AvailableRACMask);
+               PVR_LOG_GOTO_IF_ERROR(eError, "Setting up firmware system data", fail);
+       }
+
+       psDevInfo->bFirmwareInitialised = IMG_TRUE;
+
+#if defined(PDUMP)
+       RGXPDumpLoadFWInitData(psDevInfo,
+                                                  ui32HWPerfCountersDataSize,
+                                                  ui32RenderKillingCtl,
+                                                  ui32CDMTDMKillingCtl,
+                                                  bEnableSignatureChecks);
+#endif /* PDUMP */
+
+fail:
+       return eError;
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXFreeFwSysData
+
+ @Description Frees all system-wide firmware related data
+
+ @Input       psDevInfo
+******************************************************************************/
+static void RGXFreeFwSysData(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       psDevInfo->bFirmwareInitialised = IMG_FALSE;
+
+       if (psDevInfo->psRGXFWAlignChecksMemDesc)
+       {
+               RGXFWFreeAlignChecks(psDevInfo);
+       }
+
+#if defined(PDUMP)
+       if (psDevInfo->psRGXFWSigTDMChecksMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSigTDMChecksMemDesc);
+               psDevInfo->psRGXFWSigTDMChecksMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWSigTAChecksMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSigTAChecksMemDesc);
+               psDevInfo->psRGXFWSigTAChecksMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWSig3DChecksMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSig3DChecksMemDesc);
+               psDevInfo->psRGXFWSig3DChecksMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWSigCDMChecksMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSigCDMChecksMemDesc);
+               psDevInfo->psRGXFWSigCDMChecksMemDesc = NULL;
+       }
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 1 &&
+          psDevInfo->psRGXFWSigRDMChecksMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWSigRDMChecksMemDesc);
+               psDevInfo->psRGXFWSigRDMChecksMemDesc = NULL;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       if (psDevInfo->psRGXFWValidationSigMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWValidationSigMemDesc);
+               psDevInfo->psRGXFWValidationSigMemDesc = NULL;
+       }
+#endif
+#endif
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+       if (psDevInfo->psFirmwareGcovBufferMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psFirmwareGcovBufferMemDesc);
+               psDevInfo->psFirmwareGcovBufferMemDesc = NULL;
+       }
+#endif
+
+#if defined(RGX_FEATURE_SLC_FAULT_ACCESS_ADDR_PHYS_BIT_MASK)
+       RGXSetupFaultReadRegisterRollback(psDevInfo);
+#endif
+
+       if (psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfGpuUtilFWCb != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+                       psDevInfo->psRGXFWIfGpuUtilFWCb = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc);
+               psDevInfo->psRGXFWIfGpuUtilFWCbCtlMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfRuntimeCfgMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfRuntimeCfg != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+                       psDevInfo->psRGXFWIfRuntimeCfg = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfRuntimeCfgMemDesc);
+               psDevInfo->psRGXFWIfRuntimeCfgMemDesc = NULL;
+       }
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META_COREMEM_SIZE))
+       {
+               if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
+               {
+                       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+                       psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
+               }
+       }
+
+       if (psDevInfo->psRGXFWIfTraceBufCtlMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfTraceBufCtl != NULL)
+               {
+                       /* first deinit/free the tracebuffer allocation */
+                       RGXTraceBufferDeinit(psDevInfo);
+
+#if defined(SUPPORT_POWMON_COMPONENT) && defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+                       /* second free the powmon log buffer if used */
+                       RGXPowmonBufferDeinit(psDevInfo);
+#endif
+
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+                       psDevInfo->psRGXFWIfTraceBufCtl = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfTraceBufCtlMemDesc);
+               psDevInfo->psRGXFWIfTraceBufCtlMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfFwSysDataMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfFwSysData != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfFwSysDataMemDesc);
+                       psDevInfo->psRGXFWIfFwSysData = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfFwSysDataMemDesc);
+               psDevInfo->psRGXFWIfFwSysDataMemDesc = NULL;
+       }
+
+#if defined(SUPPORT_TBI_INTERFACE)
+       if (psDevInfo->psRGXFWIfTBIBufferMemDesc)
+       {
+               RGXTBIBufferDeinit(psDevInfo);
+       }
+#endif
+
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+       if (psDevInfo->psRGXFWIfRegCfgMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfRegCfgMemDesc);
+               psDevInfo->psRGXFWIfRegCfgMemDesc = NULL;
+       }
+#endif
+       if (psDevInfo->psRGXFWIfHWPerfCountersMemDesc)
+       {
+               RGXUnsetFirmwareAddress(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
+               psDevInfo->psRGXFWIfHWPerfCountersMemDesc = NULL;
+       }
+
+#if defined(SUPPORT_SECURITY_VALIDATION)
+       if (psDevInfo->psRGXFWIfNonSecureBufMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfNonSecureBufMemDesc);
+               psDevInfo->psRGXFWIfNonSecureBufMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfSecureBufMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfSecureBufMemDesc);
+               psDevInfo->psRGXFWIfSecureBufMemDesc = NULL;
+       }
+#endif
+
+       /* Free the SLC3 fence object */
+       _FreeSLC3Fence(psDevInfo);
+
+#if defined(SUPPORT_PDVFS)
+       if (psDevInfo->psRGXFWIFCoreClkRateMemDesc)
+       {
+               if (psDevInfo->pui32RGXFWIFCoreClkRate != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIFCoreClkRateMemDesc);
+                       psDevInfo->pui32RGXFWIFCoreClkRate = NULL;
+               }
+
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIFCoreClkRateMemDesc);
+               psDevInfo->psRGXFWIFCoreClkRateMemDesc = NULL;
+       }
+#endif
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXFreeFwOsData
+
+ @Description Frees all os-specific firmware related data
+
+ @Input       psDevInfo
+******************************************************************************/
+static void RGXFreeFwOsData(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFreeCCBReturnSlots(psDevInfo,
+                             &psDevInfo->pui32KernelCCBRtnSlots,
+                             &psDevInfo->psKernelCCBRtnSlotsMemDesc);
+       RGXFreeCCB(psDevInfo,
+                  &psDevInfo->psKernelCCBCtl,
+                  &psDevInfo->psKernelCCBCtlMemDesc,
+                  &psDevInfo->psKernelCCB,
+                  &psDevInfo->psKernelCCBMemDesc);
+
+       RGXFreeCCB(psDevInfo,
+                  &psDevInfo->psFirmwareCCBCtl,
+                  &psDevInfo->psFirmwareCCBCtlMemDesc,
+                  &psDevInfo->psFirmwareCCB,
+                  &psDevInfo->psFirmwareCCBMemDesc);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFreeCCB(psDevInfo,
+                  &psDevInfo->psWorkEstFirmwareCCBCtl,
+                  &psDevInfo->psWorkEstFirmwareCCBCtlMemDesc,
+                  &psDevInfo->psWorkEstFirmwareCCB,
+                  &psDevInfo->psWorkEstFirmwareCCBMemDesc);
+#endif
+
+       if (psDevInfo->psPowSyncPrim != NULL)
+       {
+               SyncPrimFree(psDevInfo->psPowSyncPrim);
+               psDevInfo->psPowSyncPrim = NULL;
+       }
+
+       if (psDevInfo->hSyncPrimContext != (IMG_HANDLE) NULL)
+       {
+               SyncPrimContextDestroy(psDevInfo->hSyncPrimContext);
+               psDevInfo->hSyncPrimContext = (IMG_HANDLE) NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfHWRInfoBufCtl != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+                       psDevInfo->psRGXFWIfHWRInfoBufCtl = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc);
+               psDevInfo->psRGXFWIfHWRInfoBufCtlMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfFwOsDataMemDesc)
+       {
+               if (psDevInfo->psRGXFWIfFwOsData != NULL)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfFwOsDataMemDesc);
+                       psDevInfo->psRGXFWIfFwOsData = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfFwOsDataMemDesc);
+               psDevInfo->psRGXFWIfFwOsDataMemDesc = NULL;
+       }
+
+       if (psDevInfo->psCompletedMemDesc)
+       {
+               if (psDevInfo->pui32CompletedById)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psCompletedMemDesc);
+                       psDevInfo->pui32CompletedById = NULL;
+               }
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psCompletedMemDesc);
+               psDevInfo->psCompletedMemDesc = NULL;
+       }
+       if (psDevInfo->psEndTimeMemDesc)
+       {
+               if (psDevInfo->pui64EndTimeById)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psEndTimeMemDesc);
+                       psDevInfo->pui64EndTimeById = NULL;
+               }
+
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psEndTimeMemDesc);
+               psDevInfo->psEndTimeMemDesc = NULL;
+       }
+       if (psDevInfo->psStartTimeMemDesc)
+       {
+               if (psDevInfo->pui64StartTimeById)
+               {
+                       DevmemReleaseCpuVirtAddr(psDevInfo->psStartTimeMemDesc);
+                       psDevInfo->pui64StartTimeById = NULL;
+               }
+
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psStartTimeMemDesc);
+               psDevInfo->psStartTimeMemDesc = NULL;
+       }
+#if !defined(PVRSRV_USE_BRIDGE_LOCK)
+       if (psDevInfo->hTimerQueryLock)
+       {
+               OSLockDestroy(psDevInfo->hTimerQueryLock);
+               psDevInfo->hTimerQueryLock = NULL;
+       }
+#endif
+
+       if (psDevInfo->psRGXFWHeapGuardPageReserveMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWHeapGuardPageReserveMemDesc);
+       }
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXFreeFirmware
+
+ @Description Frees all the firmware-related allocations
+
+ @Input       psDevInfo
+******************************************************************************/
+void RGXFreeFirmware(PVRSRV_RGXDEV_INFO        *psDevInfo)
+{
+       RGXFreeFwOsData(psDevInfo);
+
+       if (psDevInfo->psRGXFWIfConnectionCtl)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfConnectionCtlMemDesc);
+               psDevInfo->psRGXFWIfConnectionCtl = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfConnectionCtlMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfConnectionCtlMemDesc);
+               psDevInfo->psRGXFWIfConnectionCtlMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfOsInit)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfOsInitMemDesc);
+               psDevInfo->psRGXFWIfOsInit = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfOsInitMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfOsInitMemDesc);
+               psDevInfo->psRGXFWIfOsInitMemDesc = NULL;
+       }
+
+       RGXFreeFwSysData(psDevInfo);
+       if (psDevInfo->psRGXFWIfSysInit)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfSysInitMemDesc);
+               psDevInfo->psRGXFWIfSysInit = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfSysInitMemDesc)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfSysInitMemDesc);
+               psDevInfo->psRGXFWIfSysInitMemDesc = NULL;
+       }
+}
+
+/******************************************************************************
+ FUNCTION      : RGXAcquireKernelCCBSlot
+
+ PURPOSE       : Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS    : psCCB - the CCB
+                       : Address of space if available, NULL otherwise
+
+ RETURNS       : PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXAcquireKernelCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                       const RGXFWIF_CCB_CTL *psKCCBCtl,
+                                                                                       IMG_UINT32              *pui32Offset)
+{
+       IMG_UINT32      ui32OldWriteOffset, ui32NextWriteOffset;
+#if defined(PDUMP)
+       const DEVMEM_MEMDESC *psKCCBCtrlMemDesc = psDevInfo->psKernelCCBCtlMemDesc;
+#endif
+
+       ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
+       ui32NextWriteOffset = (ui32OldWriteOffset + 1) & psKCCBCtl->ui32WrapMask;
+
+#if defined(PDUMP)
+       /* Wait for sufficient CCB space to become available */
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, 0,
+                             "Wait for kCCB woff=%u", ui32NextWriteOffset);
+       DevmemPDumpCBP(psKCCBCtrlMemDesc,
+                      offsetof(RGXFWIF_CCB_CTL, ui32ReadOffset),
+                      ui32NextWriteOffset,
+                      1,
+                      (psKCCBCtl->ui32WrapMask + 1));
+#endif
+
+       if (ui32NextWriteOffset == psKCCBCtl->ui32ReadOffset)
+       {
+               return PVRSRV_ERROR_KERNEL_CCB_FULL;
+       }
+       *pui32Offset = ui32NextWriteOffset;
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ FUNCTION      : RGXPollKernelCCBSlot
+
+ PURPOSE       : Poll for space in Kernel CCB
+
+ PARAMETERS    : psCCB - the CCB
+                       : Address of space if available, NULL otherwise
+
+ RETURNS       : PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXPollKernelCCBSlot(const DEVMEM_MEMDESC *psKCCBCtrlMemDesc,
+                                                                                const RGXFWIF_CCB_CTL *psKCCBCtl)
+{
+       IMG_UINT32      ui32OldWriteOffset, ui32NextWriteOffset;
+
+       ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
+       ui32NextWriteOffset = (ui32OldWriteOffset + 1) & psKCCBCtl->ui32WrapMask;
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+
+               if (ui32NextWriteOffset != psKCCBCtl->ui32ReadOffset)
+               {
+                       return PVRSRV_OK;
+               }
+
+               /*
+                * The following check doesn't impact performance, since the
+                * CPU has to wait for the GPU anyway (full kernel CCB).
+                */
+               if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+               {
+                       return PVRSRV_ERROR_KERNEL_CCB_FULL;
+               }
+
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       return PVRSRV_ERROR_KERNEL_CCB_FULL;
+}
+
+/******************************************************************************
+ FUNCTION      : RGXGetCmdMemCopySize
+
+ PURPOSE       : Calculates actual size of KCCB command getting used
+
+ PARAMETERS    : eCmdType     Type of KCCB command
+
+ RETURNS       : Returns actual size of KCCB command on success else zero
+******************************************************************************/
+static IMG_UINT32 RGXGetCmdMemCopySize(RGXFWIF_KCCB_CMD_TYPE eCmdType)
+{
+       /* First get offset of uCmdData inside the struct RGXFWIF_KCCB_CMD
+        * This will account alignment requirement of uCmdData union
+        *
+        * Then add command-data size depending on command type to calculate actual
+        * command size required to do mem copy
+        *
+        * NOTE: Make sure that uCmdData is the last member of RGXFWIF_KCCB_CMD struct.
+        */
+       switch (eCmdType)
+       {
+               case RGXFWIF_KCCB_CMD_KICK:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_KCCB_CMD_KICK_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_MMUCACHE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_MMUCACHEDATA);
+               }
+#if defined(SUPPORT_USC_BREAKPOINT)
+               case RGXFWIF_KCCB_CMD_BP:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_BPDATA);
+               }
+#endif
+               case RGXFWIF_KCCB_CMD_SLCFLUSHINVAL:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_SLCFLUSHINVALDATA);
+               }
+               case RGXFWIF_KCCB_CMD_CLEANUP:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_CLEANUP_REQUEST);
+               }
+               case RGXFWIF_KCCB_CMD_POW:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_POWER_REQUEST);
+               }
+               case RGXFWIF_KCCB_CMD_ZSBUFFER_BACKING_UPDATE:
+               case RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_ZSBUFFER_BACKING_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_FREELIST_GS_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_FREELISTS_RECONSTRUCTION_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_WRITE_OFFSET_UPDATE_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_FORCE_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_KCCB_CMD_FORCE_UPDATE_DATA);
+               }
+#if defined(SUPPORT_USER_REGISTER_CONFIGURATION)
+               case RGXFWIF_KCCB_CMD_REGCONFIG:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_REGCONFIG_DATA);
+               }
+#endif
+#if defined(SUPPORT_PDVFS)
+               case RGXFWIF_KCCB_CMD_PDVFS_LIMIT_MAX_FREQ:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_PDVFS_MAX_FREQ_DATA);
+               }
+#endif
+               case RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_OS_STATE_CHANGE_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_HWPERF_UPDATE_CONFIG:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CTRL);
+               }
+               case RGXFWIF_KCCB_CMD_HWPERF_CONFIG_BLKS:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CONFIG_ENABLE_BLKS);
+               }
+               case RGXFWIF_KCCB_CMD_HWPERF_CTRL_BLKS:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_HWPERF_CTRL_BLKS);
+               }
+               case RGXFWIF_KCCB_CMD_CORECLKSPEEDCHANGE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_CORECLKSPEEDCHANGE_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE:
+               case RGXFWIF_KCCB_CMD_WDG_CFG:
+               case RGXFWIF_KCCB_CMD_HEALTH_CHECK:
+               case RGXFWIF_KCCB_CMD_STATEFLAGS_CTRL:
+               case RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS_DIRECT:
+               {
+                       /* No command specific data */
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData);
+               }
+               case RGXFWIF_KCCB_CMD_LOGTYPE_UPDATE:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_DEV_VIRTADDR);
+               }
+#if defined(SUPPORT_VALIDATION)
+               case RGXFWIF_KCCB_CMD_RGXREG:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_RGXREG_DATA);
+               }
+               case RGXFWIF_KCCB_CMD_GPUMAP:
+               {
+                       return offsetof(RGXFWIF_KCCB_CMD, uCmdData) + sizeof(RGXFWIF_GPUMAP_DATA);
+               }
+#endif
+               default:
+               {
+                       /* Invalid (OR) Unused (OR) Newly added command type */
+                       return 0; /* Error */
+               }
+       }
+}
+
+PVRSRV_ERROR RGXWaitForKCCBSlotUpdate(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                      IMG_UINT32 ui32SlotNum,
+                                                                         IMG_UINT32 ui32PDumpFlags)
+{
+       PVRSRV_ERROR eError;
+
+       eError = PVRSRVWaitForValueKM(
+                     (IMG_UINT32 __iomem *)&psDevInfo->pui32KernelCCBRtnSlots[ui32SlotNum],
+                                 RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
+                                 RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVWaitForValueKM");
+
+#if defined(PDUMP)
+       /* PDumping conditions same as RGXSendCommandRaw for the actual command and poll command to go in harmony */
+       if (PDumpCheckFlagsWrite(psDevInfo->psDeviceNode, ui32PDumpFlags))
+       {
+               PDUMPCOMMENT(psDevInfo->psDeviceNode, "Poll on KCCB slot %u for value %u (mask: 0x%x)", ui32SlotNum,
+                                        RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED, RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED);
+
+               eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBRtnSlotsMemDesc,
+                                                                               ui32SlotNum * sizeof(IMG_UINT32),
+                                                                               RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
+                                                                               RGXFWIF_KCCB_RTN_SLOT_CMD_EXECUTED,
+                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                               ui32PDumpFlags);
+               PVR_LOG_IF_ERROR(eError, "DevmemPDumpDevmemPol32");
+
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+       return eError;
+}
+
+static PVRSRV_ERROR RGXSendCommandRaw(PVRSRV_RGXDEV_INFO  *psDevInfo,
+                                                                         RGXFWIF_KCCB_CMD    *psKCCBCmd,
+                                                                         IMG_UINT32          uiPDumpFlags,
+                                                                         IMG_UINT32          *pui32CmdKCCBSlot)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE      *psDeviceNode = psDevInfo->psDeviceNode;
+       RGXFWIF_CCB_CTL         *psKCCBCtl = psDevInfo->psKernelCCBCtl;
+       IMG_UINT8                       *pui8KCCB = psDevInfo->psKernelCCB;
+       IMG_UINT32                      ui32NewWriteOffset;
+       IMG_UINT32                      ui32OldWriteOffset = psKCCBCtl->ui32WriteOffset;
+       IMG_UINT32                      ui32CmdMemCopySize;
+
+#if !defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(uiPDumpFlags);
+#else
+       IMG_BOOL bContCaptureOn = PDumpCheckFlagsWrite(psDeviceNode, PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER); /* client connected or in pdump init phase */
+       IMG_BOOL bPDumpEnabled = PDumpCheckFlagsWrite(psDeviceNode, uiPDumpFlags); /* Are we in capture range or continuous and not in a power transition */
+
+       if (bContCaptureOn)
+       {
+               /* in capture range */
+               if (bPDumpEnabled)
+               {
+                       if (!psDevInfo->bDumpedKCCBCtlAlready)
+                       {
+                               /* entering capture range */
+                               psDevInfo->bDumpedKCCBCtlAlready = IMG_TRUE;
+
+                               /* Wait for the live FW to catch up */
+                               PVR_DPF((PVR_DBG_MESSAGE, "%s: waiting on fw to catch-up, roff: %d, woff: %d",
+                                               __func__,
+                                               psKCCBCtl->ui32ReadOffset, ui32OldWriteOffset));
+                               PVRSRVPollForValueKM(psDeviceNode,
+                                                    (IMG_UINT32 __iomem *)&psKCCBCtl->ui32ReadOffset,
+                                                    ui32OldWriteOffset, 0xFFFFFFFF,
+                                                    POLL_FLAG_LOG_ERROR | POLL_FLAG_DEBUG_DUMP);
+
+                               /* Dump Init state of Kernel CCB control (read and write offset) */
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags,
+                                               "Initial state of kernel CCB Control, roff: %d, woff: %d",
+                                               psKCCBCtl->ui32ReadOffset, psKCCBCtl->ui32WriteOffset);
+
+                               DevmemPDumpLoadMem(psDevInfo->psKernelCCBCtlMemDesc,
+                                               0,
+                                               sizeof(RGXFWIF_CCB_CTL),
+                                               uiPDumpFlags);
+                       }
+               }
+       }
+#endif
+
+#if defined(SUPPORT_AUTOVZ)
+       if (!((KM_FW_CONNECTION_IS(READY, psDevInfo) && KM_OS_CONNECTION_IS(READY, psDevInfo)) ||
+               (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) && KM_OS_CONNECTION_IS(ACTIVE, psDevInfo))) &&
+               !PVRSRV_VZ_MODE_IS(NATIVE))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: The firmware-driver connection is invalid:"
+                                                               "driver state = %u / firmware state = %u;"
+                                                               "expected READY (%u/%u) or ACTIVE (%u/%u);",
+                                                               __func__, KM_GET_OS_CONNECTION(psDevInfo), KM_GET_FW_CONNECTION(psDevInfo),
+                                                               RGXFW_CONNECTION_OS_READY, RGXFW_CONNECTION_FW_READY,
+                                                               RGXFW_CONNECTION_OS_ACTIVE, RGXFW_CONNECTION_FW_ACTIVE));
+               eError = PVRSRV_ERROR_PVZ_OSID_IS_OFFLINE;
+               goto _RGXSendCommandRaw_Exit;
+       }
+#endif
+
+       PVR_ASSERT(sizeof(RGXFWIF_KCCB_CMD) == psKCCBCtl->ui32CmdSize);
+       if (!OSLockIsLocked(psDeviceNode->hPowerLock))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s called without power lock held!",
+                               __func__));
+               PVR_ASSERT(OSLockIsLocked(psDeviceNode->hPowerLock));
+       }
+
+       /* Acquire a slot in the CCB */
+       eError = RGXAcquireKernelCCBSlot(psDevInfo, psKCCBCtl, &ui32NewWriteOffset);
+       if (eError != PVRSRV_OK)
+       {
+               goto _RGXSendCommandRaw_Exit;
+       }
+
+       /* Calculate actual size of command to optimize device mem copy */
+       ui32CmdMemCopySize = RGXGetCmdMemCopySize(psKCCBCmd->eCmdType);
+       PVR_LOG_RETURN_IF_FALSE(ui32CmdMemCopySize !=0, "RGXGetCmdMemCopySize failed", PVRSRV_ERROR_INVALID_CCB_COMMAND);
+
+       /* Copy the command into the CCB */
+       OSCachedMemCopyWMB(&pui8KCCB[ui32OldWriteOffset * psKCCBCtl->ui32CmdSize],
+                       psKCCBCmd, ui32CmdMemCopySize);
+
+       /* If non-NULL pui32CmdKCCBSlot passed-in, return the kCCB slot in which the command was enqueued */
+       if (pui32CmdKCCBSlot)
+       {
+               *pui32CmdKCCBSlot = ui32OldWriteOffset;
+
+               /* Each such command enqueue needs to reset the slot value first. This is so that a caller
+                * doesn't get to see stale/false value in allotted slot */
+               OSWriteDeviceMem32WithWMB(&psDevInfo->pui32KernelCCBRtnSlots[ui32OldWriteOffset],
+                                         RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE);
+#if defined(PDUMP)
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags,
+                                                         "Reset kCCB slot number %u", ui32OldWriteOffset);
+               DevmemPDumpLoadMem(psDevInfo->psKernelCCBRtnSlotsMemDesc,
+                                  ui32OldWriteOffset * sizeof(IMG_UINT32),
+                                                  sizeof(IMG_UINT32),
+                                                  uiPDumpFlags);
+#endif
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: Device (%p) KCCB slot %u reset with value %u for command type %x",
+                        __func__, psDevInfo, ui32OldWriteOffset, RGXFWIF_KCCB_RTN_SLOT_NO_RESPONSE, psKCCBCmd->eCmdType));
+       }
+
+       /* Move past the current command */
+       psKCCBCtl->ui32WriteOffset = ui32NewWriteOffset;
+       OSWriteMemoryBarrier(&psKCCBCtl->ui32WriteOffset);
+
+#if defined(PDUMP)
+       if (bContCaptureOn)
+       {
+               /* in capture range */
+               if (bPDumpEnabled)
+               {
+                       /* Dump new Kernel CCB content */
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                       uiPDumpFlags, "Dump kCCB cmd woff = %d",
+                                       ui32OldWriteOffset);
+                       DevmemPDumpLoadMem(psDevInfo->psKernelCCBMemDesc,
+                                       ui32OldWriteOffset * psKCCBCtl->ui32CmdSize,
+                                       ui32CmdMemCopySize,
+                                       uiPDumpFlags);
+
+                       /* Dump new kernel CCB write offset */
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                       uiPDumpFlags, "Dump kCCBCtl woff: %d",
+                                       ui32NewWriteOffset);
+                       DevmemPDumpLoadMem(psDevInfo->psKernelCCBCtlMemDesc,
+                                       offsetof(RGXFWIF_CCB_CTL, ui32WriteOffset),
+                                       sizeof(IMG_UINT32),
+                                       uiPDumpFlags);
+
+                       /* mimic the read-back of the write from above */
+                       DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBCtlMemDesc,
+                                       offsetof(RGXFWIF_CCB_CTL, ui32WriteOffset),
+                                       ui32NewWriteOffset,
+                                       0xFFFFFFFF,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       uiPDumpFlags);
+               }
+               /* out of capture range */
+               else
+               {
+                       eError = RGXPdumpDrainKCCB(psDevInfo, ui32OldWriteOffset);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXPdumpDrainKCCB", _RGXSendCommandRaw_Exit);
+               }
+       }
+#endif
+
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, uiPDumpFlags, "MTS kick for kernel CCB");
+       /*
+        * Kick the MTS to schedule the firmware.
+        */
+       __MTSScheduleWrite(psDevInfo, RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK);
+
+       PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_MTS_SCHEDULE,
+                  RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK, uiPDumpFlags);
+
+#if defined(SUPPORT_AUTOVZ)
+       RGXUpdateAutoVzWdgToken(psDevInfo);
+#endif
+
+#if defined(NO_HARDWARE)
+       /* keep the roff updated because fw isn't there to update it */
+       psKCCBCtl->ui32ReadOffset = psKCCBCtl->ui32WriteOffset;
+#endif
+
+_RGXSendCommandRaw_Exit:
+       return eError;
+}
+
+/******************************************************************************
+ FUNCTION      : _AllocDeferredCommand
+
+ PURPOSE       : Allocate a KCCB command and add it to KCCB deferred list
+
+ PARAMETERS    : psDevInfo     RGX device info
+                       : eKCCBType             Firmware Command type
+                       : psKCCBCmd             Firmware Command
+                       : uiPDumpFlags  Pdump flags
+
+ RETURNS       : PVRSRV_OK     If all went good, PVRSRV_ERROR_RETRY otherwise.
+******************************************************************************/
+static PVRSRV_ERROR _AllocDeferredCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                          RGXFWIF_KCCB_CMD   *psKCCBCmd,
+                                          IMG_UINT32         uiPDumpFlags)
+{
+       RGX_DEFERRED_KCCB_CMD *psDeferredCommand;
+       OS_SPINLOCK_FLAGS uiFlags;
+
+       psDeferredCommand = OSAllocMem(sizeof(*psDeferredCommand));
+
+       if (!psDeferredCommand)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Deferring a KCCB command failed: allocation failure: requesting retry"));
+               return PVRSRV_ERROR_RETRY;
+       }
+
+       psDeferredCommand->sKCCBcmd = *psKCCBCmd;
+       psDeferredCommand->uiPDumpFlags = uiPDumpFlags;
+       psDeferredCommand->psDevInfo = psDevInfo;
+
+       OSSpinLockAcquire(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+       dllist_add_to_tail(&(psDevInfo->sKCCBDeferredCommandsListHead), &(psDeferredCommand->sListNode));
+       psDevInfo->ui32KCCBDeferredCommandsCount++;
+       OSSpinLockRelease(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ FUNCTION      : _FreeDeferredCommand
+
+ PURPOSE       : Remove from the deferred list the sent deferred KCCB command
+
+ PARAMETERS    : psNode                        Node in deferred list
+                       : psDeferredKCCBCmd     KCCB Command to free
+
+ RETURNS       : None
+******************************************************************************/
+static void _FreeDeferredCommand(DLLIST_NODE *psNode, RGX_DEFERRED_KCCB_CMD *psDeferredKCCBCmd)
+{
+       dllist_remove_node(psNode);
+       psDeferredKCCBCmd->psDevInfo->ui32KCCBDeferredCommandsCount--;
+       OSFreeMem(psDeferredKCCBCmd);
+}
+
+/******************************************************************************
+ FUNCTION      : RGXSendCommandsFromDeferredList
+
+ PURPOSE       : Try send KCCB commands in deferred list to KCCB
+                 Should be called by holding PowerLock
+
+ PARAMETERS    : psDevInfo     RGX device info
+                       : bPoll         Poll for space in KCCB
+
+ RETURNS       : PVRSRV_OK     If all commands in deferred list are sent to KCCB,
+                         PVRSRV_ERROR_KERNEL_CCB_FULL otherwise.
+******************************************************************************/
+PVRSRV_ERROR RGXSendCommandsFromDeferredList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bPoll)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       DLLIST_NODE *psNode, *psNext;
+       RGX_DEFERRED_KCCB_CMD *psTempDeferredKCCBCmd;
+       DLLIST_NODE sCommandList;
+       OS_SPINLOCK_FLAGS uiFlags;
+
+       PVR_ASSERT(PVRSRVPwrLockIsLockedByMe(psDevInfo->psDeviceNode));
+
+       /* !!! Important !!!
+        *
+        * The idea of moving the whole list hLockKCCBDeferredCommandsList below
+        * to the temporary list is only valid under the principle that all of the
+        * operations are also protected by the power lock. It must be held
+        * so that the order of the commands doesn't get messed up while we're
+        * performing the operations on the local list.
+        *
+        * The necessity of releasing the hLockKCCBDeferredCommandsList comes from
+        * the fact that _FreeDeferredCommand() is allocating memory and it can't
+        * be done in atomic context (inside section protected by a spin lock).
+        *
+        * We're using spin lock here instead of mutex to quickly perform a check
+        * if the list is empty in MISR without a risk that the MISR is going
+        * to sleep due to a lock.
+        */
+
+       /* move the whole list to a local list so it can be processed without lock */
+       OSSpinLockAcquire(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+       dllist_replace_head(&psDevInfo->sKCCBDeferredCommandsListHead, &sCommandList);
+       OSSpinLockRelease(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if (dllist_is_empty(&sCommandList))
+               {
+                       return PVRSRV_OK;
+               }
+
+               /* For every deferred KCCB command, try to send it*/
+               dllist_foreach_node(&sCommandList, psNode, psNext)
+               {
+                       psTempDeferredKCCBCmd = IMG_CONTAINER_OF(psNode, RGX_DEFERRED_KCCB_CMD, sListNode);
+                       eError = RGXSendCommandRaw(psTempDeferredKCCBCmd->psDevInfo,
+                                                  &psTempDeferredKCCBCmd->sKCCBcmd,
+                                                  psTempDeferredKCCBCmd->uiPDumpFlags,
+                                                  NULL /* We surely aren't interested in kCCB slot number of deferred command */);
+                       if (eError != PVRSRV_OK)
+                       {
+                               if (!bPoll)
+                               {
+                                       eError = PVRSRV_ERROR_KERNEL_CCB_FULL;
+                                       goto cleanup_;
+                               }
+                               break;
+                       }
+
+                       _FreeDeferredCommand(psNode, psTempDeferredKCCBCmd);
+               }
+
+               if (bPoll)
+               {
+                       PVRSRV_ERROR eErrPollForKCCBSlot;
+
+                       /* Don't overwrite eError because if RGXPollKernelCCBSlot returns OK and the
+                        * outer loop times-out, we'll still want to return KCCB_FULL to caller
+                        */
+                       eErrPollForKCCBSlot = RGXPollKernelCCBSlot(psDevInfo->psKernelCCBCtlMemDesc,
+                                                                  psDevInfo->psKernelCCBCtl);
+                       if (eErrPollForKCCBSlot == PVRSRV_ERROR_KERNEL_CCB_FULL)
+                       {
+                               eError = PVRSRV_ERROR_KERNEL_CCB_FULL;
+                               goto cleanup_;
+                       }
+               }
+       } END_LOOP_UNTIL_TIMEOUT();
+
+cleanup_:
+       /* if the local list is not empty put it back to the deferred list head
+        * so that the old order of commands is retained */
+       OSSpinLockAcquire(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+       dllist_insert_list_at_head(&psDevInfo->sKCCBDeferredCommandsListHead, &sCommandList);
+       OSSpinLockRelease(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
+                                                                                 RGXFWIF_KCCB_CMD    *psKCCBCmd,
+                                                                                 IMG_UINT32          uiPDumpFlags,
+                                                                                 IMG_UINT32          *pui32CmdKCCBSlot)
+{
+       IMG_BOOL     bPoll = (pui32CmdKCCBSlot != NULL);
+       PVRSRV_ERROR eError;
+
+       /*
+        * First try to Flush all the cmds in deferred list.
+        *
+        * We cannot defer an incoming command if the caller is interested in
+        * knowing the command's kCCB slot: it plans to poll/wait for a
+        * response from the FW just after the command is enqueued, so we must
+        * poll for space to be available.
+        */
+       eError = RGXSendCommandsFromDeferredList(psDevInfo, bPoll);
+       if (eError == PVRSRV_OK)
+       {
+               eError = RGXSendCommandRaw(psDevInfo,
+                                                                  psKCCBCmd,
+                                                                  uiPDumpFlags,
+                                                                  pui32CmdKCCBSlot);
+       }
+
+       /*
+        * If we don't manage to enqueue one of the deferred commands or the command
+        * passed as argument because the KCCB is full, insert the latter into the deferred commands list.
+        * The deferred commands will also be flushed eventually by:
+        *  - one more KCCB command sent for any DM
+        *  - RGX_MISRHandler_CheckFWActivePowerState
+        */
+       if (eError == PVRSRV_ERROR_KERNEL_CCB_FULL)
+       {
+               if (pui32CmdKCCBSlot == NULL)
+               {
+                       eError = _AllocDeferredCommand(psDevInfo, psKCCBCmd, uiPDumpFlags);
+               }
+               else
+               {
+                       /* Let the caller retry. Otherwise if we deferred the command and returned OK,
+                        * the caller can end up looking in a stale CCB slot.
+                        */
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Couldn't flush the deferred queue for a command (Type:%d) "
+                                               "- will be retried", __func__, psKCCBCmd->eCmdType));
+               }
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXSendCommandWithPowLockAndGetKCCBSlot(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                                                                                                        RGXFWIF_KCCB_CMD       *psKCCBCmd,
+                                                                                                        IMG_UINT32                     ui32PDumpFlags,
+                                                                                                        IMG_UINT32         *pui32CmdKCCBSlot)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+
+       /* Ensure Rogue is powered up before kicking MTS */
+       eError = PVRSRVPowerLock(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: failed to acquire powerlock (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+
+               goto _PVRSRVPowerLock_Exit;
+       }
+
+       PDUMPPOWCMDSTART(psDeviceNode);
+       eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+                                                                                PVRSRV_DEV_POWER_STATE_ON,
+                                                                                PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to transition Rogue to ON (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+
+               goto _PVRSRVSetDevicePowerStateKM_Exit;
+       }
+
+       eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                                                                 psKCCBCmd,
+                                                                                 ui32PDumpFlags,
+                                             pui32CmdKCCBSlot);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to schedule command (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+#if defined(DEBUG)
+               /* PVRSRVDebugRequest must be called without powerlock */
+               PVRSRVPowerUnlock(psDeviceNode);
+               PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+               goto _PVRSRVPowerLock_Exit;
+#endif
+       }
+
+_PVRSRVSetDevicePowerStateKM_Exit:
+       PVRSRVPowerUnlock(psDeviceNode);
+
+_PVRSRVPowerLock_Exit:
+       return eError;
+}
+
+void RGXScheduleProcessQueuesKM(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE*) hCmdCompHandle;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       OSScheduleMISR(psDevInfo->hProcessQueuesMISR);
+}
+
+#if defined(SUPPORT_VALIDATION)
+PVRSRV_ERROR RGXScheduleRgxRegCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                         IMG_UINT64 ui64RegVal,
+                                                                         IMG_UINT64 ui64Size,
+                                                                         IMG_UINT32 ui32Offset,
+                                                                         IMG_BOOL bWriteOp)
+{
+       RGXFWIF_KCCB_CMD sRgxRegsCmd = {0};
+       IMG_UINT32 ui32kCCBCommandSlot;
+       PVRSRV_ERROR eError;
+
+       sRgxRegsCmd.eCmdType = RGXFWIF_KCCB_CMD_RGXREG;
+       sRgxRegsCmd.uCmdData.sFwRgxData.ui64RegVal = ui64RegVal;
+       sRgxRegsCmd.uCmdData.sFwRgxData.ui32RegWidth = ui64Size;
+       sRgxRegsCmd.uCmdData.sFwRgxData.ui32RegAddr = ui32Offset;
+       sRgxRegsCmd.uCmdData.sFwRgxData.bWriteOp = bWriteOp;
+
+       eError =  RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
+                                                                                          RGXFWIF_DM_GP,
+                                                                                          &sRgxRegsCmd,
+                                                                                          PDUMP_FLAGS_CONTINUOUS,
+                                                                                          &ui32kCCBCommandSlot);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot");
+
+       if (bWriteOp)
+       {
+               eError = RGXWaitForKCCBSlotUpdate(psDevInfo,
+                                                                                 ui32kCCBCommandSlot,
+                                                 PDUMP_FLAGS_CONTINUOUS);
+               PVR_LOG_RETURN_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate");
+       }
+
+       return eError;
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     RGX_MISRHandler_ScheduleProcessQueues
+
+ @Description - Sends uncounted kick to all the DMs (the FW will process all
+                               the queue for all the DMs)
+******************************************************************************/
+static void RGX_MISRHandler_ScheduleProcessQueues(void *pvData)
+{
+       PVRSRV_DEVICE_NODE     *psDeviceNode = pvData;
+       PVRSRV_RGXDEV_INFO     *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR           eError;
+       PVRSRV_DEV_POWER_STATE ePowerState;
+
+       eError = PVRSRVPowerLock(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to acquire powerlock (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               return;
+       }
+
+       /* Check whether it's worth waking up the GPU */
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST) &&
+               (eError == PVRSRV_OK) && (ePowerState == PVRSRV_DEV_POWER_STATE_OFF))
+       {
+               /* For now, guest drivers will always wake-up the GPU */
+               RGXFWIF_GPU_UTIL_FWCB  *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+               IMG_BOOL               bGPUHasWorkWaiting;
+
+               bGPUHasWorkWaiting =
+                   (RGXFWIF_GPU_UTIL_GET_STATE(psUtilFWCb->ui64LastWord) == RGXFWIF_GPU_UTIL_STATE_BLOCKED);
+
+               if (!bGPUHasWorkWaiting)
+               {
+                       /* all queues are empty, don't wake up the GPU */
+                       PVRSRVPowerUnlock(psDeviceNode);
+                       return;
+               }
+       }
+
+       PDUMPPOWCMDSTART(psDeviceNode);
+       /* wake up the GPU */
+       eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+                                                                                PVRSRV_DEV_POWER_STATE_ON,
+                                                                                PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to transition Rogue to ON (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+
+               PVRSRVPowerUnlock(psDeviceNode);
+               return;
+       }
+
+       /* uncounted kick to the FW */
+       HTBLOGK(HTB_SF_MAIN_KICK_UNCOUNTED);
+       __MTSScheduleWrite(psDevInfo, (RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK) | RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED);
+
+       PVRSRVPowerUnlock(psDeviceNode);
+}
+
+PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       return OSInstallMISR(phMISR,
+                       RGX_MISRHandler_ScheduleProcessQueues,
+                       psDeviceNode,
+                       "RGX_ScheduleProcessQueues");
+}
+
+PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO  *psDevInfo,
+                                              RGXFWIF_DM          eKCCBType,
+                                              RGXFWIF_KCCB_CMD    *psKCCBCmd,
+                                              IMG_UINT32          ui32PDumpFlags,
+                                              IMG_UINT32          *pui32CmdKCCBSlot)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 uiMMUSyncUpdate;
+#if defined(SUPPORT_VALIDATION)
+       static IMG_UINT32 ui32PowDomainFrameCounter;
+#endif
+
+       /* Don't send the command/power up request if the device is de-initialising.
+        * The de-init thread could destroy the device whilst the power up
+        * sequence below is accessing the HW registers.
+        */
+       if (unlikely((psDevInfo == NULL) ||
+                    (psDevInfo->psDeviceNode == NULL) ||
+                    (psDevInfo->psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_DEINIT)))
+       {
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
+
+       /* PVRSRVPowerLock guarantees atomicity between commands. This is helpful
+          in a scenario with several applications allocating resources. */
+       eError = PVRSRVPowerLock(psDevInfo->psDeviceNode);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to acquire powerlock (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+
+               /* If system is found powered OFF, Retry scheduling the command */
+               if (likely(eError == PVRSRV_ERROR_SYSTEM_STATE_POWERED_OFF))
+               {
+                       eError = PVRSRV_ERROR_RETRY;
+               }
+
+               goto RGXScheduleCommand_exit;
+       }
+
+       if (unlikely(psDevInfo->psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_DEINIT))
+       {
+               /* If we have the power lock the device is valid but the deinit
+                * thread could be waiting for the lock. */
+               PVRSRVPowerUnlock(psDevInfo->psDeviceNode);
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
+
+       /* Ensure device is powered up before sending any commands */
+       PDUMPPOWCMDSTART(psDevInfo->psDeviceNode);
+       eError = PVRSRVSetDevicePowerStateKM(psDevInfo->psDeviceNode,
+                                            PVRSRV_DEV_POWER_STATE_ON,
+                                            PVRSRV_POWER_FLAGS_NONE);
+       PDUMPPOWCMDEND(psDevInfo->psDeviceNode);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: failed to transition RGX to ON (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               goto _PVRSRVSetDevicePowerStateKM_Exit;
+       }
+
+       eError = RGXPreKickCacheCommand(psDevInfo, eKCCBType, &uiMMUSyncUpdate);
+       if (unlikely(eError != PVRSRV_OK)) goto _PVRSRVSetDevicePowerStateKM_Exit;
+
+       eError = RGXSendCommandAndGetKCCBSlot(psDevInfo, psKCCBCmd, ui32PDumpFlags, pui32CmdKCCBSlot);
+       if (unlikely(eError != PVRSRV_OK)) goto _PVRSRVSetDevicePowerStateKM_Exit;
+
+_PVRSRVSetDevicePowerStateKM_Exit:
+       PVRSRVPowerUnlock(psDevInfo->psDeviceNode);
+
+#if defined(SUPPORT_VALIDATION)
+       /**
+        * For validation, force the core to different powered units between
+        * DM kicks. PVRSRVDeviceGPUUnitsPowerChange acquires the power lock, hence
+        * ensure that this is done after the power lock is released.
+        */
+       if ((eError == PVRSRV_OK) && (eKCCBType != RGXFWIF_DM_GP))
+       {
+               IMG_BOOL bInsertPowerDomainTransition =
+                       (psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_GPU_UNITS_POWER_CHANGE_EN);
+               if (psDevInfo->ui32PowDomainKickInterval > 0)
+               {
+                       if (eKCCBType == RGXFWIF_DM_3D)
+                       {
+                               /* Insert a power domain transition every N '3D' frames */
+                               ui32PowDomainFrameCounter++;
+                               if ((ui32PowDomainFrameCounter % psDevInfo->ui32PowDomainKickInterval) == 0)
+                               {
+                                       bInsertPowerDomainTransition = IMG_TRUE;
+                               }
+                       }
+               }
+
+               if (bInsertPowerDomainTransition)
+               {
+                       IMG_UINT32 ui32PowerDomainState;
+                       IMG_BOOL bIsValid;
+                       do {
+                               ui32PowerDomainState = RGXPowerDomainGetNextState(&psDevInfo->sPowerDomainState);
+                               bIsValid = ui32PowerDomainState &&
+                                                  ((ui32PowerDomainState & ~(psDevInfo->ui32AvailablePowUnitsMask)) == 0);
+                       } while (!bIsValid);
+
+                       eError = PVRSRVDeviceGPUUnitsPowerChange(psDevInfo->psDeviceNode, ui32PowerDomainState);
+                       if (eError != PVRSRV_OK)
+                               goto RGXScheduleCommand_exit;
+               }
+       }
+#endif
+
+RGXScheduleCommand_exit:
+       return eError;
+}
+
+/*
+ * RGXCheckFirmwareCCB
+ */
+void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_CCB_CTL *psFWCCBCtl = psDevInfo->psFirmwareCCBCtl;
+       IMG_UINT8 *psFWCCB = psDevInfo->psFirmwareCCB;
+
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       PVR_LOG_RETURN_VOID_IF_FALSE(PVRSRV_VZ_MODE_IS(NATIVE) ||
+                                                                (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) &&
+                                                                KM_OS_CONNECTION_IS(ACTIVE, psDevInfo)),
+                                                                "FW-KM connection is down");
+#endif
+
+       while (psFWCCBCtl->ui32ReadOffset != psFWCCBCtl->ui32WriteOffset)
+       {
+               /* Point to the next command */
+               const RGXFWIF_FWCCB_CMD *psFwCCBCmd = ((RGXFWIF_FWCCB_CMD *)psFWCCB) + psFWCCBCtl->ui32ReadOffset;
+
+               HTBLOGK(HTB_SF_MAIN_FWCCB_CMD, psFwCCBCmd->eCmdType);
+               switch (psFwCCBCmd->eCmdType)
+               {
+                       case RGXFWIF_FWCCB_CMD_ZSBUFFER_BACKING:
+                       {
+                               if (psDevInfo->bPDPEnabled)
+                               {
+                                       PDUMP_PANIC(psDevInfo->psDeviceNode, ZSBUFFER_BACKING, "Request to add backing to ZSBuffer");
+                               }
+                               RGXProcessRequestZSBufferBacking(psDevInfo,
+                                       psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_ZSBUFFER_UNBACKING:
+                       {
+                               if (psDevInfo->bPDPEnabled)
+                               {
+                                       PDUMP_PANIC(psDevInfo->psDeviceNode, ZSBUFFER_UNBACKING, "Request to remove backing from ZSBuffer");
+                               }
+                               RGXProcessRequestZSBufferUnbacking(psDevInfo,
+                                       psFwCCBCmd->uCmdData.sCmdZSBufferBacking.ui32ZSBufferID);
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_FREELIST_GROW:
+                       {
+                               if (psDevInfo->bPDPEnabled)
+                               {
+                                       PDUMP_PANIC(psDevInfo->psDeviceNode, FREELIST_GROW, "Request to grow the free list");
+                               }
+                               RGXProcessRequestGrow(psDevInfo,
+                                       psFwCCBCmd->uCmdData.sCmdFreeListGS.ui32FreelistID);
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_FREELISTS_RECONSTRUCTION:
+                       {
+                               if (psDevInfo->bPDPEnabled)
+                               {
+                                       PDUMP_PANIC(psDevInfo->psDeviceNode, FREELISTS_RECONSTRUCTION, "Request to reconstruct free lists");
+                               }
+
+                               if (PVRSRV_VZ_MODE_IS(GUEST))
+                               {
+                                       PVR_DPF((PVR_DBG_MESSAGE, "%s: Freelist reconstruction request (%d) for %d freelists",
+                                                       __func__,
+                                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32HwrCounter+1,
+                                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32FreelistsCount));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_MESSAGE, "%s: Freelist reconstruction request (%d/%d) for %d freelists",
+                                                       __func__,
+                                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32HwrCounter+1,
+                                                       psDevInfo->psRGXFWIfHWRInfoBufCtl->ui32HwrCounter+1,
+                                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32FreelistsCount));
+                               }
+
+                               RGXProcessRequestFreelistsReconstruction(psDevInfo,
+                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.ui32FreelistsCount,
+                                       psFwCCBCmd->uCmdData.sCmdFreeListsReconstruction.aui32FreelistIDs);
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_CONTEXT_FW_PF_NOTIFICATION:
+                       {
+                               /* Notify client drivers */
+                               /* Client notification of device error will be achieved by
+                                * clients calling UM function RGXGetLastDeviceError() */
+                               psDevInfo->eLastDeviceError = RGX_CONTEXT_RESET_REASON_FW_PAGEFAULT;
+
+                               /* Notify system layer */
+                               {
+                                       PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
+                                       PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+                                       const RGXFWIF_FWCCB_CMD_FW_PAGEFAULT_DATA *psCmdFwPagefault =
+                                                       &psFwCCBCmd->uCmdData.sCmdFWPagefault;
+
+                                       if (psDevConfig->pfnSysDevErrorNotify)
+                                       {
+                                               PVRSRV_ROBUSTNESS_NOTIFY_DATA sErrorData = {0};
+
+                                               sErrorData.eResetReason = RGX_CONTEXT_RESET_REASON_FW_PAGEFAULT;
+                                               sErrorData.uErrData.sFwPFErrData.sFWFaultAddr.uiAddr = psCmdFwPagefault->sFWFaultAddr.uiAddr;
+
+                                               psDevConfig->pfnSysDevErrorNotify(psDevConfig,
+                                                                                                                 &sErrorData);
+                                       }
+                               }
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_CONTEXT_RESET_NOTIFICATION:
+                       {
+                               DLLIST_NODE *psNode, *psNext;
+                               const RGXFWIF_FWCCB_CMD_CONTEXT_RESET_DATA *psCmdContextResetNotification =
+                                               &psFwCCBCmd->uCmdData.sCmdContextResetNotification;
+                               RGX_SERVER_COMMON_CONTEXT *psServerCommonContext = NULL;
+                               IMG_UINT32 ui32ErrorPid = 0;
+
+                               OSWRLockAcquireRead(psDevInfo->hCommonCtxtListLock);
+                               dllist_foreach_node(&psDevInfo->sCommonCtxtListHead, psNode, psNext)
+                               {
+                                       RGX_SERVER_COMMON_CONTEXT *psThisContext =
+                                               IMG_CONTAINER_OF(psNode, RGX_SERVER_COMMON_CONTEXT, sListNode);
+
+                                       /* If the notification applies to all contexts update reset info
+                                        * for all contexts, otherwise only do so for the appropriate ID.
+                                        */
+                                       if (psCmdContextResetNotification->ui32Flags & RGXFWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_ALL_CTXS)
+                                       {
+                                               /* Notification applies to all contexts */
+                                               psThisContext->eLastResetReason    = psCmdContextResetNotification->eResetReason;
+                                               psThisContext->ui32LastResetJobRef = psCmdContextResetNotification->ui32ResetJobRef;
+                                       }
+                                       else
+                                       {
+                                               /* Notification applies to one context only */
+                                               if (psThisContext->ui32ContextID == psCmdContextResetNotification->ui32ServerCommonContextID)
+                                               {
+                                                       psServerCommonContext = psThisContext;
+                                                       psServerCommonContext->eLastResetReason    = psCmdContextResetNotification->eResetReason;
+                                                       psServerCommonContext->ui32LastResetJobRef = psCmdContextResetNotification->ui32ResetJobRef;
+                                                       ui32ErrorPid = RGXGetPIDFromServerMMUContext(psServerCommonContext->psServerMMUContext);
+                                                       break;
+                                               }
+                                       }
+                               }
+
+                               if (psCmdContextResetNotification->ui32Flags & RGXFWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_ALL_CTXS)
+                               {
+                                       PVR_DPF((PVR_DBG_MESSAGE, "%s: All contexts reset (Reason=%d, JobRef=0x%08x)",
+                                                       __func__,
+                                                       (IMG_UINT32)(psCmdContextResetNotification->eResetReason),
+                                                       psCmdContextResetNotification->ui32ResetJobRef));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_MESSAGE, "%s: Context 0x%p reset (ID=0x%08x, Reason=%d, JobRef=0x%08x)",
+                                                       __func__,
+                                                       psServerCommonContext,
+                                                       psCmdContextResetNotification->ui32ServerCommonContextID,
+                                                       (IMG_UINT32)(psCmdContextResetNotification->eResetReason),
+                                                       psCmdContextResetNotification->ui32ResetJobRef));
+                               }
+
+                               /* Increment error counter (if appropriate) */
+                               if (psCmdContextResetNotification->eResetReason == RGX_CONTEXT_RESET_REASON_WGP_CHECKSUM)
+                               {
+                                       /* Avoid wrapping the error count (which would then
+                                        * make it appear we had far fewer errors), by limiting
+                                        * it to IMG_UINT32_MAX.
+                                        */
+                                       if (psDevInfo->sErrorCounts.ui32WGPErrorCount < IMG_UINT32_MAX)
+                                       {
+                                               psDevInfo->sErrorCounts.ui32WGPErrorCount++;
+                                       }
+                               }
+                               else if (psCmdContextResetNotification->eResetReason == RGX_CONTEXT_RESET_REASON_TRP_CHECKSUM)
+                               {
+                                       /* Avoid wrapping the error count (which would then
+                                        * make it appear we had far fewer errors), by limiting
+                                        * it to IMG_UINT32_MAX.
+                                        */
+                                       if (psDevInfo->sErrorCounts.ui32TRPErrorCount < IMG_UINT32_MAX)
+                                       {
+                                               psDevInfo->sErrorCounts.ui32TRPErrorCount++;
+                                       }
+                               }
+                               OSWRLockReleaseRead(psDevInfo->hCommonCtxtListLock);
+
+                               /* Notify system layer */
+                               {
+                                       PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
+                                       PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+
+                                       if (psDevConfig->pfnSysDevErrorNotify)
+                                       {
+                                               PVRSRV_ROBUSTNESS_NOTIFY_DATA sErrorData = {0};
+
+                                               sErrorData.eResetReason = psCmdContextResetNotification->eResetReason;
+                                               sErrorData.pid = ui32ErrorPid;
+
+                                               /* Populate error data according to reset reason */
+                                               switch (psCmdContextResetNotification->eResetReason)
+                                               {
+                                                       case RGX_CONTEXT_RESET_REASON_WGP_CHECKSUM:
+                                                       case RGX_CONTEXT_RESET_REASON_TRP_CHECKSUM:
+                                                       {
+                                                               sErrorData.uErrData.sChecksumErrData.ui32ExtJobRef = psCmdContextResetNotification->ui32ResetJobRef;
+                                                               sErrorData.uErrData.sChecksumErrData.eDM = psCmdContextResetNotification->eDM;
+                                                               break;
+                                                       }
+                                                       default:
+                                                       {
+                                                               break;
+                                                       }
+                                               }
+
+                                               psDevConfig->pfnSysDevErrorNotify(psDevConfig,
+                                                                                 &sErrorData);
+                                       }
+                               }
+
+                               /* Notify if a page fault */
+                               if (psCmdContextResetNotification->ui32Flags & RGXFWIF_FWCCB_CMD_CONTEXT_RESET_FLAG_PF)
+                               {
+                                       DevmemIntPFNotify(psDevInfo->psDeviceNode,
+                                                       psCmdContextResetNotification->ui64PCAddress,
+                                                       psCmdContextResetNotification->sFaultAddress);
+                               }
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_DEBUG_DUMP:
+                       {
+                               PVRSRV_ERROR eError;
+                               PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+                               OSAtomicWrite(&psDevInfo->psDeviceNode->eDebugDumpRequested, PVRSRV_DEVICE_DEBUG_DUMP_CAPTURE);
+                               eError = OSEventObjectSignal(psPVRSRVData->hDevicesWatchdogEvObj);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to signal FW Cmd debug dump event, dumping now instead", __func__));
+                                       PVRSRVDebugRequest(psDevInfo->psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+                               }
+                               break;
+                       }
+
+                       case RGXFWIF_FWCCB_CMD_UPDATE_STATS:
+                       {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+                               IMG_PID pidTmp = psFwCCBCmd->uCmdData.sCmdUpdateStatsData.pidOwner;
+                               IMG_INT32 i32AdjustmentValue = psFwCCBCmd->uCmdData.sCmdUpdateStatsData.i32AdjustmentValue;
+
+                               switch (psFwCCBCmd->uCmdData.sCmdUpdateStatsData.eElementToUpdate)
+                               {
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_PARTIAL_RENDERS:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(i32AdjustmentValue,0,0,0,0,0,pidTmp);
+                                               break;
+                                       }
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_OUT_OF_MEMORY:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(0,i32AdjustmentValue,0,0,0,0,pidTmp);
+                                               break;
+                                       }
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_TA_STORES:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(0,0,i32AdjustmentValue,0,0,0,pidTmp);
+                                               break;
+                                       }
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_3D_STORES:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(0,0,0,i32AdjustmentValue,0,0,pidTmp);
+                                               break;
+                                       }
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_CDM_STORES:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(0,0,0,0,i32AdjustmentValue,0,pidTmp);
+                                               break;
+                                       }
+                                       case RGXFWIF_FWCCB_CMD_UPDATE_NUM_TDM_STORES:
+                                       {
+                                               PVRSRVStatsUpdateRenderContextStats(0,0,0,0,0,i32AdjustmentValue,pidTmp);
+                                               break;
+                                       }
+                               }
+#endif
+                               break;
+                       }
+#if defined(SUPPORT_PDVFS)
+                       case RGXFWIF_FWCCB_CMD_CORE_CLK_RATE_CHANGE:
+                       {
+                               PDVFS_PROCESS_CORE_CLK_RATE_CHANGE(psDevInfo,
+                                                                                         psFwCCBCmd->uCmdData.sCmdCoreClkRateChange.ui32CoreClkRate);
+                               break;
+                       }
+#endif
+                       case RGXFWIF_FWCCB_CMD_REQUEST_GPU_RESTART:
+                       {
+                               if (psDevInfo->psRGXFWIfFwSysData != NULL  &&
+                                   psDevInfo->psRGXFWIfFwSysData->ePowState != RGXFWIF_POW_OFF)
+                               {
+                                       PVRSRV_ERROR eError;
+
+                                       /* Power down... */
+                                       eError = PVRSRVSetDeviceSystemPowerState(psDevInfo->psDeviceNode,
+                                                                                                                        PVRSRV_SYS_POWER_STATE_OFF,
+                                                                                                                        PVRSRV_POWER_FLAGS_NONE);
+                                       if (eError == PVRSRV_OK)
+                                       {
+                                               /* Clear the FW faulted flags... */
+                                               psDevInfo->psRGXFWIfFwSysData->ui32HWRStateFlags &= ~(RGXFWIF_HWR_FW_FAULT|RGXFWIF_HWR_RESTART_REQUESTED);
+                                               OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfFwSysData->ui32HWRStateFlags);
+
+                                               /* Power back up again... */
+                                               eError = PVRSRVSetDeviceSystemPowerState(psDevInfo->psDeviceNode,
+                                                                                                                                PVRSRV_SYS_POWER_STATE_ON,
+                                                                                                                                PVRSRV_POWER_FLAGS_NONE);
+
+                                               /* Send a dummy KCCB command to ensure the FW wakes up and checks the queues... */
+                                               if (eError == PVRSRV_OK)
+                                               {
+                                                       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+                                                       {
+                                                               eError = RGXFWHealthCheckCmd(psDevInfo);
+                                                               if (eError != PVRSRV_ERROR_RETRY)
+                                                               {
+                                                                       break;
+                                                               }
+                                                               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+                                                       } END_LOOP_UNTIL_TIMEOUT();
+                                               }
+                                       }
+
+                                       /* Notify client drivers and system layer of FW fault */
+                                       {
+                                               PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
+                                               PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+
+                                               /* Client notification of device error will be achieved by
+                                                * clients calling UM function RGXGetLastDeviceError() */
+                                               psDevInfo->eLastDeviceError = RGX_CONTEXT_RESET_REASON_FW_EXEC_ERR;
+
+                                               /* Notify system layer */
+                                               if (psDevConfig->pfnSysDevErrorNotify)
+                                               {
+                                                       PVRSRV_ROBUSTNESS_NOTIFY_DATA sErrorData = {0};
+
+                                                       sErrorData.eResetReason = RGX_CONTEXT_RESET_REASON_FW_EXEC_ERR;
+                                                       psDevConfig->pfnSysDevErrorNotify(psDevConfig,
+                                                                                         &sErrorData);
+                                               }
+                                       }
+
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR, "%s: Failed firmware restart (%s)",
+                                                                __func__, PVRSRVGetErrorString(eError)));
+                                       }
+                               }
+                               break;
+                       }
+#if defined(SUPPORT_VALIDATION)
+               case RGXFWIF_FWCCB_CMD_REG_READ:
+               {
+                       psDevInfo->sFwRegs.ui64RegVal = psFwCCBCmd->uCmdData.sCmdRgxRegReadData.ui64RegValue;
+                       complete(&psDevInfo->sFwRegs.sRegComp);
+                       break;
+               }
+#if defined(SUPPORT_SOC_TIMER)
+                       case RGXFWIF_FWCCB_CMD_SAMPLE_TIMERS:
+                       {
+                               if (psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER)
+                               {
+                                       PVRSRV_ERROR eSOCtimerErr = RGXValidateSOCUSCTimer(psDevInfo,
+                                                                                             PDUMP_NONE,
+                                                                                             psFwCCBCmd->uCmdData.sCmdTimers.ui64timerGray,
+                                                                                             psFwCCBCmd->uCmdData.sCmdTimers.ui64timerBinary,
+                                                                                             psFwCCBCmd->uCmdData.sCmdTimers.aui64uscTimers);
+                                       if (PVRSRV_OK == eSOCtimerErr)
+                                       {
+                                               PVR_DPF((PVR_DBG_WARNING, "SoC or USC Timers have increased over time"));
+                                       }
+                                       else
+                                       {
+                                               PVR_DPF((PVR_DBG_WARNING, "SoC or USC Timers have NOT increased over time"));
+                                       }
+                               }
+                               break;
+                       }
+#endif
+#endif
+                       default:
+                       {
+                               /* unknown command */
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Unknown Command (eCmdType=0x%08x)",
+                                        __func__, psFwCCBCmd->eCmdType));
+                               /* Assert on magic value corruption */
+                               PVR_ASSERT((((IMG_UINT32)psFwCCBCmd->eCmdType & RGX_CMD_MAGIC_DWORD_MASK) >> RGX_CMD_MAGIC_DWORD_SHIFT) == RGX_CMD_MAGIC_DWORD);
+                       }
+               }
+
+               /* Update read offset */
+               psFWCCBCtl->ui32ReadOffset = (psFWCCBCtl->ui32ReadOffset + 1) & psFWCCBCtl->ui32WrapMask;
+       }
+}
+
+/*
+ * PVRSRVRGXFrameworkCopyCommand
+*/
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+               DEVMEM_MEMDESC  *psFWFrameworkMemDesc,
+               IMG_PBYTE               pbyGPUFRegisterList,
+               IMG_UINT32              ui32FrameworkRegisterSize)
+{
+       PVRSRV_ERROR    eError;
+       RGXFWIF_RF_REGISTERS    *psRFReg;
+
+       eError = DevmemAcquireCpuVirtAddr(psFWFrameworkMemDesc,
+                       (void **)&psRFReg);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map firmware render context state (%u)",
+                               __func__, eError));
+               return eError;
+       }
+
+       OSDeviceMemCopy(psRFReg, pbyGPUFRegisterList, ui32FrameworkRegisterSize);
+
+       /* Release the CPU mapping */
+       DevmemReleaseCpuVirtAddr(psFWFrameworkMemDesc);
+
+       /*
+        * Dump the FW framework buffer
+        */
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump FWFramework buffer");
+       DevmemPDumpLoadMem(psFWFrameworkMemDesc, 0, ui32FrameworkRegisterSize, PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVRGXFrameworkCreateKM
+*/
+PVRSRV_ERROR PVRSRVRGXFrameworkCreateKM(PVRSRV_DEVICE_NODE     *psDeviceNode,
+               DEVMEM_MEMDESC          **ppsFWFrameworkMemDesc,
+               IMG_UINT32              ui32FrameworkCommandSize)
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
+
+       /*
+               Allocate device memory for the firmware GPU framework state.
+               Sufficient info to kick one or more DMs should be contained in this buffer
+        */
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Allocate Volcanic firmware framework state");
+
+       eError = DevmemFwAllocate(psDevInfo,
+                       ui32FrameworkCommandSize,
+                       RGX_FWCOMCTX_ALLOCFLAGS,
+                       "FwGPUFrameworkState",
+                       ppsFWFrameworkMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate firmware framework state (%u)",
+                               __func__, eError));
+               return eError;
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXPollForGPCommandCompletion(PVRSRV_DEVICE_NODE  *psDevNode,
+                                                                                               volatile IMG_UINT32     __iomem *pui32LinMemAddr,
+                                                                                               IMG_UINT32                      ui32Value,
+                                                                                               IMG_UINT32                      ui32Mask)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32CurrentQueueLength, ui32MaxRetries;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDevNode->pvDevice;
+       const RGXFWIF_CCB_CTL *psKCCBCtl = psDevInfo->psKernelCCBCtl;
+
+       ui32CurrentQueueLength = (psKCCBCtl->ui32WrapMask+1 +
+                                       psKCCBCtl->ui32WriteOffset -
+                                       psKCCBCtl->ui32ReadOffset) & psKCCBCtl->ui32WrapMask;
+       ui32CurrentQueueLength += psDevInfo->ui32KCCBDeferredCommandsCount;
+
+       for (ui32MaxRetries = ui32CurrentQueueLength + 1;
+                               ui32MaxRetries > 0;
+                               ui32MaxRetries--)
+       {
+
+               /*
+                * PVRSRVPollForValueKM flags are set to POLL_FLAG_NONE in this case so that the function
+                * does not generate an error message. In this case, the PollForValueKM is expected to
+                * timeout as there is work ongoing on the GPU which may take longer than the timeout period.
+                */
+               eError = PVRSRVPollForValueKM(psDevNode, pui32LinMemAddr, ui32Value, ui32Mask, POLL_FLAG_NONE);
+               if (eError != PVRSRV_ERROR_TIMEOUT)
+               {
+                       break;
+               }
+
+               RGXSendCommandsFromDeferredList(psDevInfo, IMG_FALSE);
+       }
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed! Error(%s) CPU linear address(%p) Expected value(%u)",
+                        __func__, PVRSRVGetErrorString(eError),
+                        pui32LinMemAddr, ui32Value));
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
+                               IMG_UINT32 ui32Config,
+                               IMG_UINT32 *pui32ConfigState,
+                               IMG_BOOL bSetNotClear)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_DEV_POWER_STATE ePowerState;
+       RGXFWIF_KCCB_CMD sStateFlagCmd = { 0 };
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+       RGXFWIF_SYSDATA *psFwSysData;
+       IMG_UINT32 ui32kCCBCommandSlot;
+       IMG_BOOL bWaitForFwUpdate = IMG_FALSE;
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       if (!psDevInfo)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psDeviceNode = psDevInfo->psDeviceNode;
+       psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+       if (NULL == psFwSysData)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Fw Sys Config is not mapped into CPU space",
+                        __func__));
+               return PVRSRV_ERROR_INVALID_CPU_ADDR;
+       }
+
+       /* apply change and ensure the new data is written to memory
+        * before requesting the FW to read it
+        */
+       ui32Config = ui32Config & RGXFWIF_INICFG_ALL;
+       if (bSetNotClear)
+       {
+               psFwSysData->ui32ConfigFlags |= ui32Config;
+       }
+       else
+       {
+               psFwSysData->ui32ConfigFlags &= ~ui32Config;
+       }
+       OSWriteMemoryBarrier(&psFwSysData->ui32ConfigFlags);
+
+       /* return current/new value to caller */
+       if (pui32ConfigState)
+       {
+               *pui32ConfigState = psFwSysData->ui32ConfigFlags;
+       }
+
+       OSMemoryBarrier(&psFwSysData->ui32ConfigFlags);
+
+       eError = PVRSRVPowerLock(psDeviceNode);
+       PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVPowerLock");
+
+       /* notify FW to update setting */
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+       if ((eError == PVRSRV_OK) && (ePowerState != PVRSRV_DEV_POWER_STATE_OFF))
+       {
+               /* Ask the FW to update its cached version of the value */
+               sStateFlagCmd.eCmdType = RGXFWIF_KCCB_CMD_STATEFLAGS_CTRL;
+
+               eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                                                                         &sStateFlagCmd,
+                                                                                         PDUMP_FLAGS_CONTINUOUS,
+                                                                                         &ui32kCCBCommandSlot);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSendCommandAndGetKCCBSlot", unlock);
+               bWaitForFwUpdate = IMG_TRUE;
+       }
+
+unlock:
+       PVRSRVPowerUnlock(psDeviceNode);
+       if (bWaitForFwUpdate)
+       {
+               /* Wait for the value to be updated as the FW validates
+                * the parameters and modifies the ui32ConfigFlags
+                * accordingly
+                * (for completeness as registered callbacks should also
+                *  not permit invalid transitions)
+                */
+               eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+               PVR_LOG_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate");
+       }
+       return eError;
+}
+
+static
+PVRSRV_ERROR RGXScheduleCleanupCommand(PVRSRV_RGXDEV_INFO      *psDevInfo,
+                                                                          RGXFWIF_DM                   eDM,
+                                                                          RGXFWIF_KCCB_CMD             *psKCCBCmd,
+                                                                          RGXFWIF_CLEANUP_TYPE eCleanupType,
+                                                                          IMG_UINT32                   ui32PDumpFlags)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32kCCBCommandSlot;
+
+       /* Clean-up commands sent during frame capture intervals must be dumped even when not in capture range... */
+       ui32PDumpFlags |= PDUMP_FLAGS_INTERVAL;
+
+       psKCCBCmd->eCmdType = RGXFWIF_KCCB_CMD_CLEANUP;
+       psKCCBCmd->uCmdData.sCleanupData.eCleanupType = eCleanupType;
+
+       /*
+               Send the cleanup request to the firmware. If the resource is still busy
+               the firmware will tell us and we'll drop out with a retry.
+       */
+       eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
+                                                                                         eDM,
+                                                                                         psKCCBCmd,
+                                                                                         ui32PDumpFlags,
+                                                                                         &ui32kCCBCommandSlot);
+       if (eError != PVRSRV_OK)
+       {
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR ,"RGXScheduleCommandAndGetKCCBSlot() failed (%s) in %s()",
+                                PVRSRVGETERRORSTRING(eError), __func__));
+               }
+               goto fail_command;
+       }
+
+       /* Wait for command kCCB slot to be updated by FW */
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                                 "Wait for the firmware to reply to the cleanup command");
+       eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot,
+                                                                         ui32PDumpFlags);
+       /*
+               If the firmware hasn't got back to us in a timely manner
+               then bail and let the caller retry the command.
+        */
+       if (eError == PVRSRV_ERROR_TIMEOUT)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                        "%s: RGXWaitForKCCBSlotUpdate timed out. Dump debug information.",
+                        __func__));
+
+               eError = PVRSRV_ERROR_RETRY;
+#if defined(DEBUG)
+               PVRSRVDebugRequest(psDevInfo->psDeviceNode,
+                               DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+#endif
+               goto fail_poll;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               goto fail_poll;
+       }
+
+#if defined(PDUMP)
+       /*
+        * The cleanup request to the firmware will tell us if a given resource is busy or not.
+        * If the RGXFWIF_KCCB_RTN_SLOT_CLEANUP_BUSY flag is set, this means that the resource is
+        * still in use. In this case we return a PVRSRV_ERROR_RETRY error to the client drivers
+        * and they will re-issue the cleanup request until it succeed.
+        *
+        * Since this retry mechanism doesn't work for pdumps, client drivers should ensure
+        * that cleanup requests are only submitted if the resource is unused.
+        * If this is not the case, the following poll will block infinitely, making sure
+        * the issue doesn't go unnoticed.
+        */
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                       "Cleanup: If this poll fails, the following resource is still in use (DM=%u, type=%u, address=0x%08x), which is incorrect in pdumps",
+                                       eDM,
+                                       psKCCBCmd->uCmdData.sCleanupData.eCleanupType,
+                                       psKCCBCmd->uCmdData.sCleanupData.uCleanupData.psContext.ui32Addr);
+       eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBRtnSlotsMemDesc,
+                                                                       ui32kCCBCommandSlot * sizeof(IMG_UINT32),
+                                                                       0,
+                                                                       RGXFWIF_KCCB_RTN_SLOT_CLEANUP_BUSY,
+                                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                                       ui32PDumpFlags);
+       PVR_LOG_IF_ERROR(eError, "DevmemPDumpDevmemPol32");
+#endif
+
+       /*
+               If the command has was run but a resource was busy, then the request
+               will need to be retried.
+       */
+       if (unlikely(psDevInfo->pui32KernelCCBRtnSlots[ui32kCCBCommandSlot] & RGXFWIF_KCCB_RTN_SLOT_CLEANUP_BUSY))
+       {
+               if (psDevInfo->pui32KernelCCBRtnSlots[ui32kCCBCommandSlot] & RGXFWIF_KCCB_RTN_SLOT_POLL_FAILURE)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: FW poll on a HW operation failed", __func__));
+               }
+               eError = PVRSRV_ERROR_RETRY;
+               goto fail_requestbusy;
+       }
+
+       return PVRSRV_OK;
+
+fail_requestbusy:
+fail_poll:
+fail_command:
+       PVR_ASSERT(eError != PVRSRV_OK);
+
+       return eError;
+}
+
+/*
+       RGXRequestCommonContextCleanUp
+*/
+PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                         RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                                                                         RGXFWIF_DM eDM,
+                                                                                         IMG_UINT32 ui32PDumpFlags)
+{
+       RGXFWIF_KCCB_CMD                        sRCCleanUpCmd = {0};
+       PVRSRV_ERROR                            eError;
+       PRGXFWIF_FWCOMMONCONTEXT        psFWCommonContextFWAddr;
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+
+       /* Force retry if this context's CCB is currently being dumped
+        * as part of the stalled CCB debug */
+       if (psDevInfo->pvEarliestStalledClientCCB == (void*)psServerCommonContext->psClientCCB)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                        "%s: Forcing retry as psDevInfo->pvEarliestStalledClientCCB = psServerCommonContext->psClientCCB <%p>",
+                        __func__,
+                        (void*)psServerCommonContext->psClientCCB));
+               return PVRSRV_ERROR_RETRY;
+       }
+
+       psFWCommonContextFWAddr = FWCommonContextGetFWAddress(psServerCommonContext);
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Common ctx cleanup Request DM%d [context = 0x%08x]",
+                    eDM, psFWCommonContextFWAddr.ui32Addr);
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Wait for CCB to be empty before common ctx cleanup");
+
+       RGXCCBPDumpDrainCCB(FWCommonContextGetClientCCB(psServerCommonContext), ui32PDumpFlags);
+#endif
+
+       /* Setup our command data, the cleanup call will fill in the rest */
+       sRCCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psContext = psFWCommonContextFWAddr;
+
+       /* Request cleanup of the firmware resource */
+       eError = RGXScheduleCleanupCommand(psDeviceNode->pvDevice,
+                                                                          eDM,
+                                                                          &sRCCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_FWCOMMONCONTEXT,
+                                                                          ui32PDumpFlags);
+
+       if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to schedule a memory context cleanup with error (%u)",
+                        __func__, eError));
+       }
+
+       return eError;
+}
+
+/*
+ * RGXFWRequestHWRTDataCleanUp
+ */
+
+PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                         PRGXFWIF_HWRTDATA psHWRTData)
+{
+       RGXFWIF_KCCB_CMD                        sHWRTDataCleanUpCmd = {0};
+       PVRSRV_ERROR                            eError;
+
+       PDUMPCOMMENT(psDeviceNode, "HW RTData cleanup Request [HWRTData = 0x%08x]", psHWRTData.ui32Addr);
+
+       sHWRTDataCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psHWRTData = psHWRTData;
+
+       eError = RGXScheduleCleanupCommand(psDeviceNode->pvDevice,
+                                          RGXFWIF_DM_GP,
+                                          &sHWRTDataCleanUpCmd,
+                                          RGXFWIF_CLEANUP_HWRTDATA,
+                                          PDUMP_FLAGS_NONE);
+
+       if (eError != PVRSRV_OK)
+       {
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to schedule a HWRTData cleanup with error (%u)",
+                                __func__, eError));
+               }
+       }
+
+       return eError;
+}
+
+/*
+       RGXFWRequestFreeListCleanUp
+*/
+PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                PRGXFWIF_FREELIST psFWFreeList)
+{
+       RGXFWIF_KCCB_CMD                        sFLCleanUpCmd = {0};
+       PVRSRV_ERROR                            eError;
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "Free list cleanup Request [FreeList = 0x%08x]", psFWFreeList.ui32Addr);
+
+       /* Setup our command data, the cleanup call will fill in the rest */
+       sFLCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psFreelist = psFWFreeList;
+
+       /* Request cleanup of the firmware resource */
+       eError = RGXScheduleCleanupCommand(psDevInfo,
+                                                                          RGXFWIF_DM_GP,
+                                                                          &sFLCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_FREELIST,
+                                                                          PDUMP_FLAGS_NONE);
+
+       if (eError != PVRSRV_OK)
+       {
+               /* If caller may retry, fail with no error message */
+               if ((eError != PVRSRV_ERROR_RETRY) &&
+                   (eError != PVRSRV_ERROR_KERNEL_CCB_FULL))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to schedule a memory context cleanup with error (%u)",
+                                __func__, eError));
+               }
+       }
+
+       return eError;
+}
+
+/*
+       RGXFWRequestZSBufferCleanUp
+*/
+PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                PRGXFWIF_ZSBUFFER psFWZSBuffer)
+{
+       RGXFWIF_KCCB_CMD                        sZSBufferCleanUpCmd = {0};
+       PVRSRV_ERROR                            eError;
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode, "ZS Buffer cleanup Request [ZS Buffer = 0x%08x]", psFWZSBuffer.ui32Addr);
+
+       /* Setup our command data, the cleanup call will fill in the rest */
+       sZSBufferCleanUpCmd.uCmdData.sCleanupData.uCleanupData.psZSBuffer = psFWZSBuffer;
+
+       /* Request cleanup of the firmware resource */
+       eError = RGXScheduleCleanupCommand(psDevInfo,
+                                                                          RGXFWIF_DM_3D,
+                                                                          &sZSBufferCleanUpCmd,
+                                                                          RGXFWIF_CLEANUP_ZSBUFFER,
+                                                                          PDUMP_FLAGS_NONE);
+
+       if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to schedule a memory context cleanup with error (%u)",
+                        __func__, eError));
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXFWSetHCSDeadline(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32HCSDeadlineMs)
+{
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS = ui32HCSDeadlineMs;
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32HCSDeadlineMS);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the Hard Context Switching deadline inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32HCSDeadlineMS),
+                                                         ui32HCSDeadlineMs,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXFWHealthCheckCmd(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_KCCB_CMD        sCmpKCCBCmd;
+
+       sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_HEALTH_CHECK;
+
+       return  RGXScheduleCommand(psDevInfo,
+                                                          RGXFWIF_DM_GP,
+                                                          &sCmpKCCBCmd,
+                                                          PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32OSid,
+                                                               RGXFWIF_OS_STATE_CHANGE eOSOnlineState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       RGXFWIF_KCCB_CMD sOSOnlineStateCmd = { 0 };
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+       sOSOnlineStateCmd.eCmdType = RGXFWIF_KCCB_CMD_OS_ONLINE_STATE_CONFIGURE;
+       sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.ui32OSid = ui32OSid;
+       sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = eOSOnlineState;
+
+#if defined(SUPPORT_AUTOVZ)
+       {
+               IMG_BOOL bConnectionDown = IMG_FALSE;
+
+               PVR_UNREFERENCED_PARAMETER(psFwSysData);
+               sOSOnlineStateCmd.uCmdData.sCmdOSOnlineStateData.eNewOSState = RGXFWIF_OS_OFFLINE;
+
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       /* Send the offline command regardless if power lock is held or not.
+                        * Under AutoVz this is done during regular driver deinit, store-to-ram suspend
+                        * or (optionally) from a kernel panic callback. Deinit and suspend operations
+                        * take the lock in the rgx pre/post power functions as expected.
+                        * The kernel panic callback is a last resort way of letting the firmware know that
+                        * the VM is unrecoverable and the vz connection must be disabled. It cannot wait
+                        * on other kernel threads to finish and release the lock. */
+                       eError = RGXSendCommand(psDevInfo,
+                                                                       &sOSOnlineStateCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                       if (eError != PVRSRV_ERROR_RETRY)
+                       {
+                               break;
+                       }
+
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               /* Guests and Host going offline should wait for confirmation
+                * from the Firmware of the state change. If this fails, break
+                * the connection on the OS Driver's end as backup. */
+               if (PVRSRV_VZ_MODE_IS(GUEST) || (ui32OSid == RGXFW_HOST_OS))
+               {
+                       LOOP_UNTIL_TIMEOUT(SECONDS_TO_MICROSECONDS/2)
+                       {
+                               if (KM_FW_CONNECTION_IS(READY, psDevInfo))
+                               {
+                                       bConnectionDown = IMG_TRUE;
+                                       break;
+                               }
+                       } END_LOOP_UNTIL_TIMEOUT();
+
+                       if (!bConnectionDown)
+                       {
+                               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+                       }
+               }
+       }
+#else
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               /* no reason for Guests to update their state or any other VM's.
+                * This is the Hypervisor and Host driver's responsibility. */
+               return PVRSRV_OK;
+       }
+       else if (eOSOnlineState == RGXFWIF_OS_ONLINE)
+       {
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       eError = RGXScheduleCommand(psDevInfo,
+                                                                               RGXFWIF_DM_GP,
+                                                                               &sOSOnlineStateCmd,
+                                                                               PDUMP_FLAGS_CONTINUOUS);
+                       if (eError != PVRSRV_ERROR_RETRY) break;
+
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+       }
+       else if (psFwSysData)
+       {
+               const volatile RGXFWIF_OS_RUNTIME_FLAGS *psFwRunFlags =
+                        (const volatile RGXFWIF_OS_RUNTIME_FLAGS*) &psFwSysData->asOsRuntimeFlagsMirror[ui32OSid];
+
+               /* Attempt several times until the FW manages to offload the OS */
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       IMG_UINT32 ui32kCCBCommandSlot;
+
+                       /* Send request */
+                       eError = RGXScheduleCommandAndGetKCCBSlot(psDevInfo,
+                                                                                                         RGXFWIF_DM_GP,
+                                                                                                         &sOSOnlineStateCmd,
+                                                                                                         PDUMP_FLAGS_CONTINUOUS,
+                                                                                                         &ui32kCCBCommandSlot);
+                       if (unlikely(eError == PVRSRV_ERROR_RETRY)) continue;
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommand", return_);
+
+                       /* Wait for FW to process the cmd */
+                       eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate", return_);
+
+                       /* read the OS state */
+                       OSMemoryBarrier(NULL);
+                       /* check if FW finished offloading the OSID and is stopped */
+                       if (psFwRunFlags->bfOsState == RGXFW_CONNECTION_FW_OFFLINE)
+                       {
+                               eError = PVRSRV_OK;
+                               break;
+                       }
+                       else
+                       {
+                               eError = PVRSRV_ERROR_TIMEOUT;
+                       }
+
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+       }
+       else
+       {
+               eError = PVRSRV_ERROR_NOT_INITIALISED;
+       }
+
+return_ :
+#endif
+       return eError;
+}
+
+PVRSRV_ERROR RGXFWChangeOSidPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32OSid,
+                                                               IMG_UINT32 ui32Priority)
+{
+       PVRSRV_ERROR eError;
+       RGXFWIF_KCCB_CMD        sOSidPriorityCmd = { 0 };
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       sOSidPriorityCmd.eCmdType = RGXFWIF_KCCB_CMD_OSID_PRIORITY_CHANGE;
+       psDevInfo->psRGXFWIfRuntimeCfg->aui32OSidPriority[ui32OSid] = ui32Priority;
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->aui32OSidPriority[ui32OSid]);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the priority of OSID%u inside RGXFWIfRuntimeCfg", ui32OSid);
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, aui32OSidPriority) + (ui32OSid * sizeof(ui32Priority)),
+                                                         ui32Priority ,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                                                       RGXFWIF_DM_GP,
+                                                                       &sOSidPriorityCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       return eError;
+}
+
+PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
+                                                               CONNECTION_DATA *psConnection,
+                                                               PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32Priority,
+                                                               RGXFWIF_DM eDM)
+{
+       IMG_UINT32                              ui32CmdSize;
+       IMG_UINT8                               *pui8CmdPtr;
+       RGXFWIF_KCCB_CMD                sPriorityCmd = { 0 };
+       RGXFWIF_CCB_CMD_HEADER  *psCmdHeader;
+       RGXFWIF_CMD_PRIORITY    *psCmd;
+       PVRSRV_ERROR                    eError;
+       IMG_INT32 i32Priority = (IMG_INT32)ui32Priority;
+       RGX_CLIENT_CCB *psClientCCB = FWCommonContextGetClientCCB(psContext);
+
+       eError = _CheckPriority(psDevInfo, i32Priority, psContext->eRequestor);
+       PVR_LOG_GOTO_IF_ERROR(eError, "_CheckPriority", fail_checkpriority);
+
+       /*
+               Get space for command
+       */
+       ui32CmdSize = RGX_CCB_FWALLOC_ALIGN(sizeof(RGXFWIF_CCB_CMD_HEADER) + sizeof(RGXFWIF_CMD_PRIORITY));
+
+       eError = RGXAcquireCCB(psClientCCB,
+                                                  ui32CmdSize,
+                                                  (void **) &pui8CmdPtr,
+                                                  PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to acquire space for client CCB", __func__));
+               }
+               goto fail_ccbacquire;
+       }
+
+       /*
+               Write the command header and command
+       */
+       psCmdHeader = (RGXFWIF_CCB_CMD_HEADER *) pui8CmdPtr;
+       psCmdHeader->eCmdType = RGXFWIF_CCB_CMD_TYPE_PRIORITY;
+       psCmdHeader->ui32CmdSize = RGX_CCB_FWALLOC_ALIGN(sizeof(RGXFWIF_CMD_PRIORITY));
+       pui8CmdPtr += sizeof(*psCmdHeader);
+
+       psCmd = (RGXFWIF_CMD_PRIORITY *) pui8CmdPtr;
+       psCmd->i32Priority = i32Priority;
+       pui8CmdPtr += sizeof(*psCmd);
+
+       /*
+               We should reserve space in the kernel CCB here and fill in the command
+               directly.
+               This is so if there isn't space in the kernel CCB we can return with
+               retry back to services client before we take any operations
+       */
+
+       /*
+               Submit the command
+       */
+       RGXReleaseCCB(psClientCCB,
+                                 ui32CmdSize,
+                                 PDUMP_FLAGS_CONTINUOUS);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to release space in client CCB", __func__));
+               return eError;
+       }
+
+       /* Construct the priority command. */
+       sPriorityCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+       sPriorityCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psContext);
+       sPriorityCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+       sPriorityCmd.uCmdData.sCmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+       sPriorityCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+       sPriorityCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                                                       eDM,
+                                                                       &sPriorityCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to submit set priority command with error (%u)",
+                               __func__,
+                               eError));
+       }
+
+       psContext->i32Priority = i32Priority;
+
+       return PVRSRV_OK;
+
+fail_ccbacquire:
+fail_checkpriority:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+PVRSRV_ERROR RGXFWConfigPHR(PVRSRV_RGXDEV_INFO *psDevInfo,
+                            IMG_UINT32 ui32PHRMode)
+{
+       PVRSRV_ERROR eError;
+       RGXFWIF_KCCB_CMD sCfgPHRCmd = { 0 };
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       sCfgPHRCmd.eCmdType = RGXFWIF_KCCB_CMD_PHR_CFG;
+       psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode = ui32PHRMode;
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32PHRMode);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the Periodic Hardware Reset Mode inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32PHRMode),
+                                                         ui32PHRMode,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                           RGXFWIF_DM_GP,
+                                           &sCfgPHRCmd,
+                                           PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXFWConfigWdg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                       IMG_UINT32 ui32WdgPeriodUs)
+{
+       PVRSRV_ERROR eError;
+       RGXFWIF_KCCB_CMD sCfgWdgCmd = { 0 };
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       sCfgWdgCmd.eCmdType = RGXFWIF_KCCB_CMD_WDG_CFG;
+       psDevInfo->psRGXFWIfRuntimeCfg->ui32WdgPeriodUs = ui32WdgPeriodUs;
+       OSWriteMemoryBarrier(&psDevInfo->psRGXFWIfRuntimeCfg->ui32WdgPeriodUs);
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                                "Updating the firmware watchdog period inside RGXFWIfRuntimeCfg");
+       DevmemPDumpLoadMemValue32(psDevInfo->psRGXFWIfRuntimeCfgMemDesc,
+                                                         offsetof(RGXFWIF_RUNTIME_CFG, ui32WdgPeriodUs),
+                                                         ui32WdgPeriodUs,
+                                                         PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                                                       RGXFWIF_DM_GP,
+                                                                       &sCfgWdgCmd,
+                                                                       PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       return eError;
+}
+
+
+void RGXCheckForStalledClientContexts(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bIgnorePrevious)
+{
+       /* Attempt to detect and deal with any stalled client contexts.
+        * bIgnorePrevious may be set by the caller if they know a context to be
+        * stalled, as otherwise this function will only identify stalled
+        * contexts which have not been previously reported.
+        */
+
+       IMG_UINT32 ui32StalledClientMask = 0;
+
+       if (!(OSTryLockAcquire(psDevInfo->hCCBStallCheckLock)))
+       {
+               PVR_LOG(("RGXCheckForStalledClientContexts: Failed to acquire hCCBStallCheckLock, returning..."));
+               return;
+       }
+
+       ui32StalledClientMask |= CheckForStalledClientTDMTransferCtxt(psDevInfo);
+
+       ui32StalledClientMask |= CheckForStalledClientRenderCtxt(psDevInfo);
+
+       ui32StalledClientMask |= CheckForStalledClientComputeCtxt(psDevInfo);
+
+       ui32StalledClientMask |= CheckForStalledClientKickSyncCtxt(psDevInfo);
+
+       /* If at least one DM stalled bit is different than before */
+       if (bIgnorePrevious || (psDevInfo->ui32StalledClientMask != ui32StalledClientMask))
+       {
+               if (ui32StalledClientMask > 0)
+               {
+                       static __maybe_unused const char *pszStalledAction =
+#if defined(PVRSRV_STALLED_CCB_ACTION)
+                                       "force";
+#else
+                                       "warn";
+#endif
+                       /* Print all the stalled DMs */
+                       PVR_LOG(("Possible stalled client RGX contexts detected: %s%s%s%s%s%s%s",
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_GP),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TDM_2D),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TA),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_3D),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_CDM),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TQ2D),
+                                        RGX_STRINGIFY_KICK_TYPE_DM_IF_SET(ui32StalledClientMask, RGX_KICK_TYPE_DM_TQ3D)));
+
+                       PVR_LOG(("Trying to identify stalled context...(%s) [%d]",
+                                pszStalledAction, bIgnorePrevious));
+
+                       DumpStalledContextInfo(psDevInfo);
+               }
+               else
+               {
+                       if (psDevInfo->ui32StalledClientMask> 0)
+                       {
+                               /* Indicate there are no stalled DMs */
+                               PVR_LOG(("No further stalled client contexts exist"));
+                       }
+               }
+               psDevInfo->ui32StalledClientMask = ui32StalledClientMask;
+               psDevInfo->pvEarliestStalledClientCCB = NULL;
+       }
+       OSLockRelease(psDevInfo->hCCBStallCheckLock);
+}
+
+/*
+       RGXUpdateHealthStatus
+*/
+PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
+                                   IMG_BOOL bCheckAfterTimePassed)
+{
+       const PVRSRV_DATA*           psPVRSRVData = PVRSRVGetPVRSRVData();
+       PVRSRV_DEVICE_HEALTH_STATUS  eNewStatus   = PVRSRV_DEVICE_HEALTH_STATUS_OK;
+       PVRSRV_DEVICE_HEALTH_REASON  eNewReason   = PVRSRV_DEVICE_HEALTH_REASON_NONE;
+       PVRSRV_RGXDEV_INFO*          psDevInfo;
+       const RGXFWIF_TRACEBUF*      psRGXFWIfTraceBufCtl;
+       const RGXFWIF_SYSDATA*       psFwSysData;
+       const RGXFWIF_OSDATA*        psFwOsData;
+       const RGXFWIF_CCB_CTL*       psKCCBCtl;
+       IMG_UINT32                   ui32ThreadCount;
+       IMG_BOOL                     bKCCBCmdsWaiting;
+
+       PVR_ASSERT(psDevNode != NULL);
+       psDevInfo = psDevNode->pvDevice;
+
+       /* If the firmware is not yet initialised or has already deinitialised, stop here */
+       if (psDevInfo  == NULL || !psDevInfo->bFirmwareInitialised || psDevInfo->pvRegsBaseKM == NULL ||
+               psDevInfo->psDeviceNode == NULL || psDevInfo->psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_DEINIT)
+       {
+               return PVRSRV_OK;
+       }
+
+       psRGXFWIfTraceBufCtl = psDevInfo->psRGXFWIfTraceBufCtl;
+       psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       psFwOsData = psDevInfo->psRGXFWIfFwOsData;
+
+       /* If this is a quick update, then include the last current value... */
+       if (!bCheckAfterTimePassed)
+       {
+               eNewStatus = OSAtomicRead(&psDevNode->eHealthStatus);
+               eNewReason = OSAtomicRead(&psDevNode->eHealthReason);
+       }
+
+       /* Decrement the SLR holdoff counter (if non-zero) */
+       if (psDevInfo->ui32SLRHoldoffCounter > 0)
+       {
+               psDevInfo->ui32SLRHoldoffCounter--;
+       }
+
+
+
+       /* If Rogue is not powered on, just skip ahead and check for stalled client CCBs */
+       if (PVRSRVIsDevicePowered(psDevNode))
+       {
+               /*
+                  Firmware thread checks...
+               */
+               if (psRGXFWIfTraceBufCtl != NULL)
+               {
+                       for (ui32ThreadCount = 0; ui32ThreadCount < RGXFW_THREAD_NUM; ui32ThreadCount++)
+                       {
+                               const IMG_CHAR* pszTraceAssertInfo = psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szInfo;
+
+                               /*
+                               Check if the FW has hit an assert...
+                               */
+                               if (*pszTraceAssertInfo != '\0')
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "%s: Firmware thread %d has asserted: %s (%s:%d)",
+                                                       __func__, ui32ThreadCount, pszTraceAssertInfo,
+                                                       psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.szPath,
+                                                       psRGXFWIfTraceBufCtl->sTraceBuf[ui32ThreadCount].sAssertBuf.ui32LineNum));
+                                       eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_DEAD;
+                                       eNewReason = PVRSRV_DEVICE_HEALTH_REASON_ASSERTED;
+                                       goto _RGXUpdateHealthStatus_Exit;
+                               }
+
+                               /*
+                                  Check the threads to see if they are in the same poll locations as last time...
+                               */
+                               if (bCheckAfterTimePassed)
+                               {
+                                       if (psFwSysData->aui32CrPollAddr[ui32ThreadCount] != 0  &&
+                                               psFwSysData->aui32CrPollCount[ui32ThreadCount] == psDevInfo->aui32CrLastPollCount[ui32ThreadCount])
+                                       {
+                                               PVR_DPF((PVR_DBG_WARNING, "%s: Firmware stuck on CR poll: T%u polling %s (reg:0x%08X mask:0x%08X)",
+                                                               __func__, ui32ThreadCount,
+                                                               ((psFwSysData->aui32CrPollAddr[ui32ThreadCount] & RGXFW_POLL_TYPE_SET)?("set"):("unset")),
+                                                               psFwSysData->aui32CrPollAddr[ui32ThreadCount] & ~RGXFW_POLL_TYPE_SET,
+                                                               psFwSysData->aui32CrPollMask[ui32ThreadCount]));
+                                               eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+                                               eNewReason = PVRSRV_DEVICE_HEALTH_REASON_POLL_FAILING;
+                                               goto _RGXUpdateHealthStatus_Exit;
+                                       }
+                                       psDevInfo->aui32CrLastPollCount[ui32ThreadCount] = psFwSysData->aui32CrPollCount[ui32ThreadCount];
+                               }
+                       }
+
+                       /*
+                       Check if the FW has faulted...
+                       */
+                       if (psFwSysData->ui32HWRStateFlags & RGXFWIF_HWR_FW_FAULT)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING,
+                                               "%s: Firmware has faulted and needs to restart",
+                                               __func__));
+                               eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_FAULT;
+                               if (psFwSysData->ui32HWRStateFlags & RGXFWIF_HWR_RESTART_REQUESTED)
+                               {
+                                       eNewReason = PVRSRV_DEVICE_HEALTH_REASON_RESTARTING;
+                               }
+                               else
+                               {
+                                       eNewReason = PVRSRV_DEVICE_HEALTH_REASON_IDLING;
+                               }
+                               goto _RGXUpdateHealthStatus_Exit;
+                       }
+               }
+
+               /*
+                  Event Object Timeouts check...
+               */
+               if (!bCheckAfterTimePassed)
+               {
+                       if (psDevInfo->ui32GEOTimeoutsLastTime > 1 && psPVRSRVData->ui32GEOConsecutiveTimeouts > psDevInfo->ui32GEOTimeoutsLastTime)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Global Event Object Timeouts have risen (from %d to %d)",
+                                        __func__,
+                                        psDevInfo->ui32GEOTimeoutsLastTime, psPVRSRVData->ui32GEOConsecutiveTimeouts));
+                               eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+                               eNewReason = PVRSRV_DEVICE_HEALTH_REASON_TIMEOUTS;
+                       }
+                       psDevInfo->ui32GEOTimeoutsLastTime = psPVRSRVData->ui32GEOConsecutiveTimeouts;
+               }
+
+               /*
+                  Check the Kernel CCB pointer is valid. If any commands were waiting last time, then check
+                  that some have executed since then.
+               */
+               bKCCBCmdsWaiting = IMG_FALSE;
+               psKCCBCtl = psDevInfo->psKernelCCBCtl;
+
+               if (psKCCBCtl != NULL)
+               {
+                       if (psKCCBCtl->ui32ReadOffset > psKCCBCtl->ui32WrapMask  ||
+                               psKCCBCtl->ui32WriteOffset > psKCCBCtl->ui32WrapMask)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: KCCB has invalid offset (ROFF=%d WOFF=%d)",
+                                               __func__, psKCCBCtl->ui32ReadOffset, psKCCBCtl->ui32WriteOffset));
+                               eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_DEAD;
+                               eNewReason = PVRSRV_DEVICE_HEALTH_REASON_QUEUE_CORRUPT;
+                       }
+
+                       if (psKCCBCtl->ui32ReadOffset != psKCCBCtl->ui32WriteOffset)
+                       {
+                               bKCCBCmdsWaiting = IMG_TRUE;
+                       }
+               }
+
+               if (bCheckAfterTimePassed && psFwOsData != NULL)
+               {
+                       IMG_UINT32 ui32KCCBCmdsExecuted = psFwOsData->ui32KCCBCmdsExecuted;
+
+                       if (psDevInfo->ui32KCCBCmdsExecutedLastTime == ui32KCCBCmdsExecuted)
+                       {
+                               /*
+                                  If something was waiting last time then the Firmware has stopped processing commands.
+                               */
+                               if (psDevInfo->bKCCBCmdsWaitingLastTime)
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "%s: No KCCB commands executed since check!",
+                                                       __func__));
+                                       eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+                                       eNewReason = PVRSRV_DEVICE_HEALTH_REASON_QUEUE_STALLED;
+                               }
+
+                               /*
+                                  If no commands are currently pending and nothing happened since the last poll, then
+                                  schedule a dummy command to ping the firmware so we know it is alive and processing.
+                               */
+                               if (!bKCCBCmdsWaiting)
+                               {
+                                       PVRSRV_ERROR eError = RGXFWHealthCheckCmd(psDevNode->pvDevice);
+
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_WARNING, "%s: Cannot schedule Health Check command! (0x%x)",
+                                                               __func__, eError));
+                                       }
+                                       else
+                                       {
+                                               bKCCBCmdsWaiting = IMG_TRUE;
+                                       }
+                               }
+                       }
+
+                       psDevInfo->bKCCBCmdsWaitingLastTime     = bKCCBCmdsWaiting;
+                       psDevInfo->ui32KCCBCmdsExecutedLastTime = ui32KCCBCmdsExecuted;
+               }
+       }
+
+       /*
+          Interrupt counts check...
+       */
+       if (bCheckAfterTimePassed  &&  psFwOsData != NULL)
+       {
+               IMG_UINT32  ui32LISRCount   = 0;
+               IMG_UINT32  ui32FWCount     = 0;
+               IMG_UINT32  ui32MissingInts = 0;
+               IMG_UINT32  ui32Index;
+
+               /* Add up the total number of interrupts issued, sampled/received and missed... */
+               for (ui32Index = 0;  ui32Index < RGXFW_THREAD_NUM;  ui32Index++)
+               {
+                       ui32LISRCount += psDevInfo->aui32SampleIRQCount[ui32Index];
+                       ui32FWCount   += psFwOsData->aui32InterruptCount[ui32Index];
+               }
+
+               if (ui32LISRCount < ui32FWCount)
+               {
+                       ui32MissingInts = (ui32FWCount-ui32LISRCount);
+               }
+
+               if (ui32LISRCount == psDevInfo->ui32InterruptCountLastTime  &&
+                   ui32MissingInts >= psDevInfo->ui32MissingInterruptsLastTime  &&
+                   psDevInfo->ui32MissingInterruptsLastTime > 1)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: LISR has not received the last %d interrupts",
+                                       __func__, ui32MissingInts));
+                       eNewStatus = PVRSRV_DEVICE_HEALTH_STATUS_NOT_RESPONDING;
+                       eNewReason = PVRSRV_DEVICE_HEALTH_REASON_MISSING_INTERRUPTS;
+
+                       /* Schedule the MISRs to help mitigate the problems of missing interrupts. */
+                       OSScheduleMISR(psDevInfo->pvMISRData);
+                       if (psDevInfo->pvAPMISRData != NULL)
+                       {
+                               OSScheduleMISR(psDevInfo->pvAPMISRData);
+                       }
+               }
+               psDevInfo->ui32InterruptCountLastTime    = ui32LISRCount;
+               psDevInfo->ui32MissingInterruptsLastTime = ui32MissingInts;
+       }
+
+       /*
+          Stalled CCB check...
+       */
+       if (bCheckAfterTimePassed && (PVRSRV_DEVICE_HEALTH_STATUS_OK==eNewStatus))
+       {
+               RGXCheckForStalledClientContexts(psDevInfo, IMG_FALSE);
+       }
+
+       /* Notify client driver and system layer of any eNewStatus errors */
+       if (eNewStatus > PVRSRV_DEVICE_HEALTH_STATUS_OK)
+       {
+               /* Client notification of device error will be achieved by
+                * clients calling UM function RGXGetLastDeviceError() */
+               psDevInfo->eLastDeviceError = RGX_CONTEXT_RESET_REASON_HOST_WDG_FW_ERR;
+
+               /* Notify system layer */
+               {
+                       PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
+                       PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+
+                       if (psDevConfig->pfnSysDevErrorNotify)
+                       {
+                               PVRSRV_ROBUSTNESS_NOTIFY_DATA sErrorData = {0};
+
+                               sErrorData.eResetReason = RGX_CONTEXT_RESET_REASON_HOST_WDG_FW_ERR;
+                               sErrorData.uErrData.sHostWdgData.ui32Status = (IMG_UINT32)eNewStatus;
+                               sErrorData.uErrData.sHostWdgData.ui32Reason = (IMG_UINT32)eNewReason;
+
+                               psDevConfig->pfnSysDevErrorNotify(psDevConfig,
+                                                                 &sErrorData);
+                       }
+               }
+       }
+
+       /*
+          Finished, save the new status...
+       */
+_RGXUpdateHealthStatus_Exit:
+       OSAtomicWrite(&psDevNode->eHealthStatus, eNewStatus);
+       OSAtomicWrite(&psDevNode->eHealthReason, eNewReason);
+       RGXSRV_HWPERF_DEVICE_INFO(psDevInfo, RGX_HWPERF_DEV_INFO_EV_HEALTH, eNewStatus, eNewReason);
+
+       /*
+        * Attempt to service the HWPerf buffer to regularly transport idle/periodic
+        * packets to host buffer.
+        */
+       if (psDevNode->pfnServiceHWPerf != NULL)
+       {
+               PVRSRV_ERROR eError = psDevNode->pfnServiceHWPerf(psDevNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: "
+                                "Error occurred when servicing HWPerf buffer (%d)",
+                                __func__, eError));
+               }
+       }
+
+       /* Attempt to refresh timer correlation data */
+       RGXTimeCorrRestartPeriodic(psDevNode);
+
+       return PVRSRV_OK;
+} /* RGXUpdateHealthStatus */
+
+#if defined(SUPPORT_AUTOVZ)
+void RGXUpdateAutoVzWdgToken(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       if (likely(KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) && KM_OS_CONNECTION_IS(ACTIVE, psDevInfo)))
+       {
+               /* read and write back the alive token value to confirm to the
+                * virtualisation watchdog that this connection is healthy */
+               KM_SET_OS_ALIVE_TOKEN(KM_GET_FW_ALIVE_TOKEN(psDevInfo), psDevInfo);
+       }
+}
+
+/*
+       RGXUpdateAutoVzWatchdog
+*/
+void RGXUpdateAutoVzWatchdog(PVRSRV_DEVICE_NODE* psDevNode)
+{
+       if (likely(psDevNode != NULL))
+       {
+               PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
+
+               if (unlikely((psDevInfo  == NULL || !psDevInfo->bFirmwareInitialised || !psDevInfo->bRGXPowered ||
+                       psDevInfo->pvRegsBaseKM == NULL || psDevNode->eDevState == PVRSRV_DEVICE_STATE_DEINIT)))
+               {
+                       /* If the firmware is not initialised, stop here */
+                       return;
+               }
+               else
+               {
+                       PVRSRV_ERROR eError = PVRSRVPowerLock(psDevNode);
+                       PVR_LOG_RETURN_VOID_IF_ERROR(eError, "PVRSRVPowerLock");
+
+                       RGXUpdateAutoVzWdgToken(psDevInfo);
+                       PVRSRVPowerUnlock(psDevNode);
+               }
+       }
+}
+#endif /* SUPPORT_AUTOVZ */
+
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext, RGX_KICK_TYPE_DM eKickTypeDM)
+{
+       if (psCurrentServerCommonContext == NULL)
+       {
+               /* the context has already been freed so there is nothing to do here */
+               return PVRSRV_OK;
+       }
+
+       return CheckForStalledCCB(psCurrentServerCommonContext->psDevInfo->psDeviceNode,
+                                 psCurrentServerCommonContext->psClientCCB,
+                                 eKickTypeDM);
+}
+
+void DumpFWCommonContextInfo(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
+                             DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                             void *pvDumpDebugFile,
+                             IMG_UINT32 ui32VerbLevel)
+{
+       if (psCurrentServerCommonContext == NULL)
+       {
+               /* the context has already been freed so there is nothing to do here */
+               return;
+       }
+
+       if (DD_VERB_LVL_ENABLED(ui32VerbLevel, DEBUG_REQUEST_VERBOSITY_HIGH))
+       {
+               /* If high verbosity requested, dump whole CCB */
+               DumpCCB(psCurrentServerCommonContext->psDevInfo,
+                       psCurrentServerCommonContext->sFWCommonContextFWAddr,
+                       psCurrentServerCommonContext->psClientCCB,
+                       pfnDumpDebugPrintf,
+                       pvDumpDebugFile);
+       }
+       else
+       {
+               /* Otherwise, only dump first stalled command in the CCB */
+               DumpStalledCCBCommand(psCurrentServerCommonContext->sFWCommonContextFWAddr,
+                                     psCurrentServerCommonContext->psClientCCB,
+                                     pfnDumpDebugPrintf,
+                                     pvDumpDebugFile);
+       }
+}
+
+PVRSRV_ERROR AttachKickResourcesCleanupCtls(PRGXFWIF_CLEANUP_CTL *apsCleanupCtl,
+                                                                       IMG_UINT32 *pui32NumCleanupCtl,
+                                                                       RGXFWIF_DM eDM,
+                                                                       IMG_BOOL bKick,
+                                                                       RGX_KM_HW_RT_DATASET           *psKMHWRTDataSet,
+                                                                       RGX_ZSBUFFER_DATA              *psZSBuffer,
+                                                                       RGX_ZSBUFFER_DATA              *psMSAAScratchBuffer)
+{
+       PVRSRV_ERROR eError;
+       PRGXFWIF_CLEANUP_CTL *psCleanupCtlWrite = apsCleanupCtl;
+
+       PVR_ASSERT((eDM == RGXFWIF_DM_GEOM) || (eDM == RGXFWIF_DM_3D));
+       PVR_RETURN_IF_INVALID_PARAM((eDM == RGXFWIF_DM_GEOM) || (eDM == RGXFWIF_DM_3D));
+
+       if (bKick)
+       {
+               if (psKMHWRTDataSet)
+               {
+                       PRGXFWIF_CLEANUP_CTL psCleanupCtl;
+
+                       eError = RGXSetFirmwareAddress(&psCleanupCtl, psKMHWRTDataSet->psHWRTDataFwMemDesc,
+                                       offsetof(RGXFWIF_HWRTDATA, sCleanupState),
+                                       RFW_FWADDR_NOREF_FLAG);
+                       PVR_RETURN_IF_ERROR(eError);
+
+                       *(psCleanupCtlWrite++) = psCleanupCtl;
+               }
+
+               if (eDM == RGXFWIF_DM_3D)
+               {
+                       RGXFWIF_PRBUFFER_TYPE eBufferType;
+                       RGX_ZSBUFFER_DATA *psBuffer = NULL;
+
+                       for (eBufferType = RGXFWIF_PRBUFFER_START; eBufferType < RGXFWIF_PRBUFFER_MAXSUPPORTED; eBufferType++)
+                       {
+                               switch (eBufferType)
+                               {
+                               case RGXFWIF_PRBUFFER_ZSBUFFER:
+                                       psBuffer = psZSBuffer;
+                                       break;
+                               case RGXFWIF_PRBUFFER_MSAABUFFER:
+                                       psBuffer = psMSAAScratchBuffer;
+                                       break;
+                               case RGXFWIF_PRBUFFER_MAXSUPPORTED:
+                                       psBuffer = NULL;
+                                       break;
+                               }
+                               if (psBuffer)
+                               {
+                                       (psCleanupCtlWrite++)->ui32Addr = psBuffer->sZSBufferFWDevVAddr.ui32Addr +
+                                                                       offsetof(RGXFWIF_PRBUFFER, sCleanupState);
+                                       psBuffer = NULL;
+                               }
+                       }
+               }
+       }
+
+       *pui32NumCleanupCtl = psCleanupCtlWrite - apsCleanupCtl;
+       PVR_ASSERT(*pui32NumCleanupCtl <= RGXFWIF_KCCB_CMD_KICK_DATA_MAX_NUM_CLEANUP_CTLS);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXResetHWRLogs(PVRSRV_DEVICE_NODE *psDevNode)
+{
+       PVRSRV_RGXDEV_INFO       *psDevInfo;
+       RGXFWIF_HWRINFOBUF       *psHWRInfoBuf;
+       IMG_UINT32               i;
+
+       if (psDevNode->pvDevice == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_DEVINFO;
+       }
+       psDevInfo = psDevNode->pvDevice;
+
+       psHWRInfoBuf = psDevInfo->psRGXFWIfHWRInfoBufCtl;
+
+       for (i = 0 ; i < psDevInfo->sDevFeatureCfg.ui32MAXDMCount ; i++)
+       {
+               /* Reset the HWR numbers */
+               psHWRInfoBuf->aui32HwrDmLockedUpCount[i] = 0;
+               psHWRInfoBuf->aui32HwrDmFalseDetectCount[i] = 0;
+               psHWRInfoBuf->aui32HwrDmRecoveredCount[i] = 0;
+               psHWRInfoBuf->aui32HwrDmOverranCount[i] = 0;
+       }
+
+       for (i = 0 ; i < RGXFWIF_HWINFO_MAX ; i++)
+       {
+               psHWRInfoBuf->sHWRInfo[i].ui32HWRNumber = 0;
+       }
+
+       psHWRInfoBuf->ui32WriteIndex = 0;
+       psHWRInfoBuf->ui32DDReqCount = 0;
+
+       OSWriteMemoryBarrier(&psHWRInfoBuf->ui32DDReqCount);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXGetPhyAddr(PMR *psPMR,
+                                                  IMG_DEV_PHYADDR *psPhyAddr,
+                                                  IMG_UINT32 ui32LogicalOffset,
+                                                  IMG_UINT32 ui32Log2PageSize,
+                                                  IMG_UINT32 ui32NumOfPages,
+                                                  IMG_BOOL *bValid)
+{
+
+       PVRSRV_ERROR eError;
+
+       eError = PMRLockSysPhysAddresses(psPMR);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: PMRLockSysPhysAddresses failed (%u)",
+                        __func__,
+                        eError));
+               return eError;
+       }
+
+       eError = PMR_DevPhysAddr(psPMR,
+                                                                ui32Log2PageSize,
+                                                                ui32NumOfPages,
+                                                                ui32LogicalOffset,
+                                                                psPhyAddr,
+                                                                bValid);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: PMR_DevPhysAddr failed (%u)",
+                        __func__,
+                        eError));
+               return eError;
+       }
+
+
+       eError = PMRUnlockSysPhysAddresses(psPMR);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: PMRUnLockSysPhysAddresses failed (%u)",
+                        __func__,
+                        eError));
+               return eError;
+       }
+
+       return eError;
+}
+
+#if defined(PDUMP)
+PVRSRV_ERROR RGXPdumpDrainKCCB(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32WriteOffset)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       if (psDevInfo->bDumpedKCCBCtlAlready)
+       {
+               /* exiting capture range or pdump block */
+               psDevInfo->bDumpedKCCBCtlAlready = IMG_FALSE;
+
+               /* make sure previous cmd is drained in pdump in case we will 'jump' over some future cmds */
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                              PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER,
+                              "kCCB(%p): Draining rgxfw_roff (0x%x) == woff (0x%x)",
+                              psDevInfo->psKernelCCBCtl,
+                              ui32WriteOffset,
+                              ui32WriteOffset);
+               eError = DevmemPDumpDevmemPol32(psDevInfo->psKernelCCBCtlMemDesc,
+                               offsetof(RGXFWIF_CCB_CTL, ui32ReadOffset),
+                               ui32WriteOffset,
+                               0xffffffff,
+                               PDUMP_POLL_OPERATOR_EQUAL,
+                               PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_POWER);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: problem pdumping POL for kCCBCtl (%d)", __func__, eError));
+               }
+       }
+
+       return eError;
+
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     RGXClientConnectCompatCheck_ClientAgainstFW
+
+ @Description
+
+ Check compatibility of client and firmware (build options)
+ at the connection time.
+
+ @Input psDeviceNode - device node
+ @Input ui32ClientBuildOptions - build options for the client
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
+PVRSRV_ERROR RGXClientConnectCompatCheck_ClientAgainstFW(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT32 ui32ClientBuildOptions)
+{
+#if !defined(NO_HARDWARE) || defined(PDUMP)
+#if !defined(NO_HARDWARE)
+       IMG_UINT32              ui32BuildOptionsMismatch;
+       IMG_UINT32              ui32BuildOptionsFW;
+#endif
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+#endif
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+#if !defined(NO_HARDWARE)
+       if (psDevInfo == NULL || psDevInfo->psRGXFWIfOsInitMemDesc == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Cannot acquire kernel fw compatibility check info, RGXFWIF_OSINIT structure not allocated.",
+                        __func__));
+               return PVRSRV_ERROR_NOT_INITIALISED;
+       }
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               if (*((volatile IMG_BOOL *) &psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated))
+               {
+                       /* No need to wait if the FW has already updated the values */
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+#endif
+
+#if defined(PDUMP)
+       {
+               PVRSRV_ERROR eError;
+
+               PDUMPCOMMENT(psDeviceNode, "Compatibility check: client and FW build options");
+               eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                               offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                               offsetof(RGXFWIF_COMPCHECKS, ui32BuildOptions),
+                               ui32ClientBuildOptions,
+                               0xffffffff,
+                               PDUMP_POLL_OPERATOR_EQUAL,
+                               PDUMP_FLAGS_CONTINUOUS);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)",
+                                       __func__,
+                                       eError));
+                       return eError;
+               }
+       }
+#endif
+
+#if !defined(NO_HARDWARE)
+       ui32BuildOptionsFW = psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.ui32BuildOptions;
+       ui32BuildOptionsMismatch = ui32ClientBuildOptions ^ ui32BuildOptionsFW;
+
+       if (ui32BuildOptionsMismatch != 0)
+       {
+               if ((ui32ClientBuildOptions & ui32BuildOptionsMismatch) != 0)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
+                       "extra options present in client: (0x%x). Please check rgx_options.h",
+                       ui32ClientBuildOptions & ui32BuildOptionsMismatch ));
+               }
+
+               if ((ui32BuildOptionsFW & ui32BuildOptionsMismatch) != 0)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and client build options; "
+                       "extra options present in Firmware: (0x%x). Please check rgx_options.h",
+                       ui32BuildOptionsFW & ui32BuildOptionsMismatch ));
+               }
+
+               return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: Firmware and client build options match. [ OK ]", __func__));
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function     RGXFwRawHeapAllocMap
+
+ @Description Register firmware heap for the specified guest OSID
+
+ @Input psDeviceNode - device node
+ @Input ui32OSID     - Guest OSID
+ @Input sDevPAddr    - Heap address
+ @Input ui64DevPSize - Heap size
+
+ @Return   PVRSRV_ERROR - PVRSRV_OK if heap setup was successful.
+
+******************************************************************************/
+PVRSRV_ERROR RGXFwRawHeapAllocMap(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                 IMG_UINT32 ui32OSID,
+                                                                 IMG_DEV_PHYADDR sDevPAddr,
+                                                                 IMG_UINT64 ui64DevPSize)
+{
+       PVRSRV_ERROR eError;
+       IMG_CHAR szRegionRAName[RA_MAX_NAME_LENGTH];
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_MEMALLOCFLAGS_T uiRawFwHeapAllocFlags = (RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS |
+                                                                                                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_PREMAP0 + ui32OSID));
+       PHYS_HEAP_CONFIG *psFwMainConfig = FindPhysHeapConfig(psDeviceNode->psDevConfig,
+                                                                                                                  PHYS_HEAP_USAGE_FW_MAIN);
+       PHYS_HEAP_CONFIG sFwHeapConfig;
+
+       PVRSRV_VZ_RET_IF_NOT_MODE(HOST, PVRSRV_OK);
+
+       if (psFwMainConfig == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FW_MAIN heap config not found."));
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       OSSNPrintf(szRegionRAName, sizeof(szRegionRAName), RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT, ui32OSID);
+
+       if (!ui64DevPSize ||
+               !sDevPAddr.uiAddr ||
+               ui32OSID >= RGX_NUM_OS_SUPPORTED ||
+               ui64DevPSize != RGX_FIRMWARE_RAW_HEAP_SIZE)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Invalid parameters for %s", szRegionRAName));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       sFwHeapConfig = *psFwMainConfig;
+       sFwHeapConfig.sStartAddr.uiAddr = 0;
+       sFwHeapConfig.sCardBase.uiAddr = sDevPAddr.uiAddr;
+       sFwHeapConfig.uiSize = RGX_FIRMWARE_RAW_HEAP_SIZE;
+
+       eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, szRegionRAName, &psDeviceNode->apsFWPremapPhysHeap[ui32OSID]);
+       PVR_LOG_RETURN_IF_ERROR_VA(eError, "PhysmemCreateHeapLMA:PREMAP [%d]", ui32OSID);
+
+       eError = PhysHeapAcquire(psDeviceNode->apsFWPremapPhysHeap[ui32OSID]);
+       PVR_LOG_RETURN_IF_ERROR_VA(eError, "PhysHeapAcquire:PREMAP [%d]", ui32OSID);
+
+       psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_PREMAP0 + ui32OSID] = psDeviceNode->apsFWPremapPhysHeap[ui32OSID];
+
+       PDUMPCOMMENT(psDeviceNode, "Allocate and map raw firmware heap for OSID: [%d]", ui32OSID);
+
+#if (RGX_NUM_OS_SUPPORTED > 1)
+       /* don't clear the heap of other guests on allocation */
+       uiRawFwHeapAllocFlags &= (ui32OSID > RGXFW_HOST_OS) ? (~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) : (~0ULL);
+#endif
+
+       /* if the firmware is already powered up, consider the firmware heaps are pre-mapped. */
+       if (psDeviceNode->bAutoVzFwIsUp)
+       {
+               uiRawFwHeapAllocFlags &= RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+               DevmemHeapSetPremapStatus(psDevInfo->psGuestFirmwareRawHeap[ui32OSID], IMG_TRUE);
+       }
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         RGX_FIRMWARE_RAW_HEAP_SIZE,
+                                                         uiRawFwHeapAllocFlags,
+                                                         psDevInfo->psGuestFirmwareRawHeap[ui32OSID]->pszName,
+                                                         &psDevInfo->psGuestFirmwareRawMemDesc[ui32OSID]);
+       PVR_LOG_RETURN_IF_ERROR(eError, "DevmemFwAllocate");
+
+       /* Mark this devmem heap as premapped so allocations will not require device mapping. */
+       DevmemHeapSetPremapStatus(psDevInfo->psGuestFirmwareRawHeap[ui32OSID], IMG_TRUE);
+
+       if (ui32OSID == RGXFW_HOST_OS)
+       {
+               /* if the Host's raw fw heap is premapped, mark its main & config sub-heaps accordingly
+                * No memory allocated from these sub-heaps will be individually mapped into the device's
+                * address space so they can remain marked permanently as premapped. */
+               DevmemHeapSetPremapStatus(psDevInfo->psFirmwareMainHeap, IMG_TRUE);
+               DevmemHeapSetPremapStatus(psDevInfo->psFirmwareConfigHeap, IMG_TRUE);
+       }
+
+       return eError;
+}
+
+/*!
+*******************************************************************************
+
+ @Function     RGXFwRawHeapUnmapFree
+
+ @Description Unregister firmware heap for the specified guest OSID
+
+ @Input psDeviceNode - device node
+ @Input ui32OSID     - Guest OSID
+
+******************************************************************************/
+void RGXFwRawHeapUnmapFree(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                  IMG_UINT32 ui32OSID)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       /* remove the premap status, so the heap can be unmapped and freed */
+       if (psDevInfo->psGuestFirmwareRawHeap[ui32OSID])
+       {
+               DevmemHeapSetPremapStatus(psDevInfo->psGuestFirmwareRawHeap[ui32OSID], IMG_FALSE);
+       }
+
+       if (psDevInfo->psGuestFirmwareRawMemDesc[ui32OSID])
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psGuestFirmwareRawMemDesc[ui32OSID]);
+               psDevInfo->psGuestFirmwareRawMemDesc[ui32OSID] = NULL;
+       }
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvHalt
+
+@Description    Halt the RISC-V FW core (required for certain operations
+                done through Debug Module)
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Halt RISC-V FW");
+
+       /* Send halt request (no need to select one or more harts on this RISC-V core) */
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+                  RGX_CR_FWCORE_DMI_DMCONTROL_HALTREQ_EN |
+                  RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until hart is halted */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_DMSTATUS,
+                   RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
+                   RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       /* Clear halt request */
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+                  RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
+                  PDUMP_FLAGS_CONTINUOUS);
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Send halt request (no need to select one or more harts on this RISC-V core) */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMCONTROL,
+                      RGX_CR_FWCORE_DMI_DMCONTROL_HALTREQ_EN |
+                      RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN);
+
+       /* Wait until hart is halted */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_DMSTATUS/sizeof(IMG_UINT32),
+                                RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
+                                RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Hart not halted (0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMSTATUS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Clear halt request */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMCONTROL,
+                      RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN);
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvIsHalted
+
+@Description    Check if the RISC-V FW is halted
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         IMG_BOOL
+******************************************************************************/
+IMG_BOOL RGXRiscvIsHalted(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(NO_HARDWARE)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       /* Assume the core is always halted in nohw */
+       return IMG_TRUE;
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       return (OSReadHWReg32(pui32RegsBase, RGX_CR_FWCORE_DMI_DMSTATUS) &
+               RGX_CR_FWCORE_DMI_DMSTATUS_ALLHALTED_EN) != 0U;
+#endif
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvResume
+
+@Description    Resume the RISC-V FW core
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvResume(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS, "Resume RISC-V FW");
+
+       /* Send resume request (no need to select one or more harts on this RISC-V core) */
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+                  RGX_CR_FWCORE_DMI_DMCONTROL_RESUMEREQ_EN |
+                  RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until hart is resumed */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_DMSTATUS,
+                   RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
+                   RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       /* Clear resume request */
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DMCONTROL,
+                  RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN,
+                  PDUMP_FLAGS_CONTINUOUS);
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Send resume request (no need to select one or more harts on this RISC-V core) */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMCONTROL,
+                      RGX_CR_FWCORE_DMI_DMCONTROL_RESUMEREQ_EN |
+                      RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN);
+
+       /* Wait until hart is resumed */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_DMSTATUS/sizeof(IMG_UINT32),
+                                RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
+                                RGX_CR_FWCORE_DMI_DMSTATUS_ALLRESUMEACK_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Hart not resumed (0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMSTATUS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Clear resume request */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DMCONTROL,
+                      RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN);
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvCheckAbstractCmdError
+
+@Description    Check for RISC-V abstract command errors and clear them
+
+@Input          psDevInfo    Pointer to GPU device info
+
+@Return         RGXRISCVFW_ABSTRACT_CMD_ERR
+******************************************************************************/
+static RGXRISCVFW_ABSTRACT_CMD_ERR RGXRiscvCheckAbstractCmdError(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXRISCVFW_ABSTRACT_CMD_ERR eCmdErr;
+
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       eCmdErr = RISCV_ABSTRACT_CMD_NO_ERROR;
+
+       /* Check error status */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                   RISCV_ABSTRACT_CMD_NO_ERROR << RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_SHIFT,
+                   ~RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_CLRMSK,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+#else
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+
+       /* Check error status */
+       eCmdErr = (OSReadHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)
+                 & ~RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_CLRMSK)
+                 >> RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_SHIFT;
+
+       if (eCmdErr != RISCV_ABSTRACT_CMD_NO_ERROR)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "RISC-V FW abstract command error %u", eCmdErr));
+
+               /* Clear the error (note CMDERR field is write-1-to-clear) */
+               OSWriteHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                              ~RGX_CR_FWCORE_DMI_ABSTRACTCS_CMDERR_CLRMSK);
+       }
+#endif
+
+       return eCmdErr;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvReadReg
+
+@Description    Read a value from the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvReadReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32RegAddr,
+                             IMG_UINT32 *pui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32RegAddr);
+       PVR_UNREFERENCED_PARAMETER(pui32Value);
+
+       /* Reading HW registers is not supported in nohw/pdump */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Send abstract register read command */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_COMMAND,
+                      (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                      RGXRISCVFW_DMI_COMMAND_READ |
+                      RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
+                      ui32RegAddr);
+
+       /* Wait until abstract command is completed */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_ABSTRACTCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Abstract command did not complete in time (abstractcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       if (RGXRiscvCheckAbstractCmdError(psDevInfo) == RISCV_ABSTRACT_CMD_NO_ERROR)
+       {
+               /* Read register value */
+               *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0);
+       }
+       else
+       {
+               *pui32Value = 0U;
+       }
+
+       return PVRSRV_OK;
+#endif
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollReg
+
+@Description    Poll for a value from the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvPollReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32RegAddr,
+                             IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Poll RISC-V register 0x%x (expected 0x%08x)",
+                             ui32RegAddr, ui32Value);
+
+       /* Send abstract register read command */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+                  (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                  RGXRISCVFW_DMI_COMMAND_READ |
+                  RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
+                  ui32RegAddr,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until abstract command is completed */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       RGXRiscvCheckAbstractCmdError(psDevInfo);
+
+       /* Check read value */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_DATA0,
+                   ui32Value,
+                   0xFFFFFFFF,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       return PVRSRV_OK;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32RegAddr);
+       PVR_UNREFERENCED_PARAMETER(ui32Value);
+
+       /* Polling HW registers is currently not required driverlive */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvWriteReg
+
+@Description    Write a value to the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                              IMG_UINT32 ui32RegAddr,
+                              IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Write RISC-V register 0x%x (value 0x%08x)",
+                             ui32RegAddr, ui32Value);
+
+       /* Prepare data to be written to register */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Send abstract register write command */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+                  (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                  RGXRISCVFW_DMI_COMMAND_WRITE |
+                  RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
+                  ui32RegAddr,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until abstract command is completed */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Prepare data to be written to register */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0, ui32Value);
+
+       /* Send abstract register write command */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_COMMAND,
+                      (RGXRISCVFW_DMI_COMMAND_ACCESS_REGISTER << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                      RGXRISCVFW_DMI_COMMAND_WRITE |
+                      RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT |
+                      ui32RegAddr);
+
+       /* Wait until abstract command is completed */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_ABSTRACTCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Abstract command did not complete in time (abstractcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvCheckSysBusError
+
+@Description    Check for RISC-V system bus errors and clear them
+
+@Input          psDevInfo    Pointer to GPU device info
+
+@Return         RGXRISCVFW_SYSBUS_ERR
+******************************************************************************/
+static __maybe_unused RGXRISCVFW_SYSBUS_ERR RGXRiscvCheckSysBusError(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXRISCVFW_SYSBUS_ERR eSBError;
+
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       eSBError = RISCV_SYSBUS_NO_ERROR;
+
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_SBCS,
+                   RISCV_SYSBUS_NO_ERROR << RGX_CR_FWCORE_DMI_SBCS_SBERROR_SHIFT,
+                   ~RGX_CR_FWCORE_DMI_SBCS_SBERROR_CLRMSK,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+#else
+       void __iomem *pvRegsBaseKM = psDevInfo->pvRegsBaseKM;
+
+       eSBError = (OSReadHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBCS)
+                & ~RGX_CR_FWCORE_DMI_SBCS_SBERROR_CLRMSK)
+                >> RGX_CR_FWCORE_DMI_SBCS_SBERROR_SHIFT;
+
+       if (eSBError != RISCV_SYSBUS_NO_ERROR)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "RISC-V FW system bus error %u", eSBError));
+
+               /* Clear the error (note SBERROR field is write-1-to-clear) */
+               OSWriteHWReg32(pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBCS,
+                              ~RGX_CR_FWCORE_DMI_SBCS_SBERROR_CLRMSK);
+       }
+#endif
+
+       return eSBError;
+}
+
+#if !defined(EMULATOR)
+/*!
+*******************************************************************************
+@Function       RGXRiscvReadAbstractMem
+
+@Description    Read a value at the given address in RISC-V memory space
+                using RISC-V abstract memory commands
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvReadAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 *pui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32Addr);
+       PVR_UNREFERENCED_PARAMETER(pui32Value);
+
+       /* Reading memory is not supported in nohw/pdump */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Prepare read address  */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA1, ui32Addr);
+
+       /* Send abstract memory read command */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_COMMAND,
+                      (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                      RGXRISCVFW_DMI_COMMAND_READ |
+                      RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT);
+
+       /* Wait until abstract command is completed */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_ABSTRACTCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Abstract command did not complete in time (abstractcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       if (RGXRiscvCheckAbstractCmdError(psDevInfo) == RISCV_ABSTRACT_CMD_NO_ERROR)
+       {
+               /* Read memory value */
+               *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0);
+       }
+       else
+       {
+               *pui32Value = 0U;
+       }
+
+       return PVRSRV_OK;
+#endif
+}
+#endif /* !defined(EMULATOR) */
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollAbstractMem
+
+@Description    Poll for a value at the given address in RISC-V memory space
+                using RISC-V abstract memory commands
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvPollAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode,
+                             PDUMP_FLAGS_CONTINUOUS,
+                             "Poll RISC-V address 0x%x (expected 0x%08x)",
+                             ui32Addr, ui32Value);
+
+       /* Prepare read address  */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Send abstract memory read command */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+                  (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                  RGXRISCVFW_DMI_COMMAND_READ |
+                  RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until abstract command is completed */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       RGXRiscvCheckAbstractCmdError(psDevInfo);
+
+       /* Check read value */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_DATA0,
+                   ui32Value,
+                   0xFFFFFFFF,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       return PVRSRV_OK;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32Addr);
+       PVR_UNREFERENCED_PARAMETER(ui32Value);
+
+       /* Polling memory is currently not required driverlive */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+#if !defined(EMULATOR)
+/*!
+*******************************************************************************
+@Function       RGXRiscvReadSysBusMem
+
+@Description    Read a value at the given address in RISC-V memory space
+                using the RISC-V system bus
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvReadSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 *pui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32Addr);
+       PVR_UNREFERENCED_PARAMETER(pui32Value);
+
+       /* Reading memory is not supported in nohw/pdump */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Configure system bus to read 32 bit every time a new address is provided */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_SBCS,
+                      (RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT) |
+                      RGX_CR_FWCORE_DMI_SBCS_SBREADONADDR_EN);
+
+       /* Perform read */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBADDRESS0, ui32Addr);
+
+       /* Wait until system bus is idle */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_SBCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: System Bus did not go idle in time (sbcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       if (RGXRiscvCheckSysBusError(psDevInfo) == RISCV_SYSBUS_NO_ERROR)
+       {
+               /* Read value from debug system bus */
+               *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBDATA0);
+       }
+       else
+       {
+               *pui32Value = 0U;
+       }
+
+       return PVRSRV_OK;
+#endif
+}
+#endif /* !defined(EMULATOR) */
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollSysBusMem
+
+@Description    Poll for a value at the given address in RISC-V memory space
+                using the RISC-V system bus
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvPollSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Poll RISC-V address 0x%x (expected 0x%08x)",
+                             ui32Addr, ui32Value);
+
+       /* Configure system bus to read 32 bit every time a new address is provided */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
+                  (RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT) |
+                  RGX_CR_FWCORE_DMI_SBCS_SBREADONADDR_EN,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Perform read */
+       PDUMPREG32(psDevInfo->psDeviceNode,
+                  RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0,
+                  ui32Addr,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until system bus is idle */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_SBCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       RGXRiscvCheckSysBusError(psDevInfo);
+
+       /* Check read value */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_SBDATA0,
+                   ui32Value,
+                   0xFFFFFFFF,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       return PVRSRV_OK;
+#else
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(ui32Addr);
+       PVR_UNREFERENCED_PARAMETER(ui32Value);
+
+       /* Polling memory is currently not required driverlive */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+#if !defined(EMULATOR)
+/*!
+*******************************************************************************
+@Function       RGXRiscvReadMem
+
+@Description    Read a value at the given address in RISC-V memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXRiscvReadMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32Addr,
+                             IMG_UINT32 *pui32Value)
+{
+       if (ui32Addr >= RGXRISCVFW_COREMEM_BASE && ui32Addr <= RGXRISCVFW_COREMEM_END)
+       {
+               return RGXRiscvReadAbstractMem(psDevInfo, ui32Addr, pui32Value);
+       }
+
+       return RGXRiscvReadSysBusMem(psDevInfo, ui32Addr, pui32Value);
+}
+#endif /* !defined(EMULATOR) */
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollMem
+
+@Description    Poll a value at the given address in RISC-V memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32Addr,
+                             IMG_UINT32 ui32Value)
+{
+       if (ui32Addr >= RGXRISCVFW_COREMEM_BASE && ui32Addr <= RGXRISCVFW_COREMEM_END)
+       {
+               return RGXRiscvPollAbstractMem(psDevInfo, ui32Addr, ui32Value);
+       }
+
+       return RGXRiscvPollSysBusMem(psDevInfo, ui32Addr, ui32Value);
+}
+
+#if !defined(EMULATOR)
+/*!
+*******************************************************************************
+@Function       RGXRiscvWriteAbstractMem
+
+@Description    Write a value at the given address in RISC-V memory space
+                using RISC-V abstract memory commands
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvWriteAbstractMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Write RISC-V address 0x%x (value 0x%08x)",
+                             ui32Addr, ui32Value);
+
+       /* Prepare write address */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA1,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Prepare write data */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_DATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Send abstract register write command */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_COMMAND,
+                  (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                  RGXRISCVFW_DMI_COMMAND_WRITE |
+                  RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until abstract command is completed */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Prepare write address */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA1, ui32Addr);
+
+       /* Prepare write data */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_DATA0, ui32Value);
+
+       /* Send abstract memory write command */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_COMMAND,
+                      (RGXRISCVFW_DMI_COMMAND_ACCESS_MEMORY << RGX_CR_FWCORE_DMI_COMMAND_CMDTYPE_SHIFT) |
+                      RGXRISCVFW_DMI_COMMAND_WRITE |
+                      RGXRISCVFW_DMI_COMMAND_AAxSIZE_32BIT);
+
+       /* Wait until abstract command is completed */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_ABSTRACTCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_ABSTRACTCS_BUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Abstract command did not complete in time (abstractcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_ABSTRACTCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvWriteSysBusMem
+
+@Description    Write a value at the given address in RISC-V memory space
+                using the RISC-V system bus
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR
+RGXRiscvWriteSysBusMem(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32Addr, IMG_UINT32 ui32Value)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Write RISC-V address 0x%x (value 0x%08x)",
+                             ui32Addr, ui32Value);
+
+       /* Configure system bus to read 32 bit every time a new address is provided */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBCS,
+                  RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT,
+                  PDUMP_FLAGS_CONTINUOUS);
+
+       /* Prepare write address */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBADDRESS0,
+                  ui32Addr, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Prepare write data and initiate write */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_FWCORE_DMI_SBDATA0,
+                  ui32Value, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Wait until system bus is idle */
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   RGX_CR_FWCORE_DMI_SBCS,
+                   0U,
+                   RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
+                   PDUMP_FLAGS_CONTINUOUS,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+#else
+       IMG_UINT32 __iomem *pui32RegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* Configure system bus for 32 bit accesses */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                      RGX_CR_FWCORE_DMI_SBCS,
+                      RGXRISCVFW_DMI_SBCS_SBACCESS_32BIT << RGX_CR_FWCORE_DMI_SBCS_SBACCESS_SHIFT);
+
+       /* Prepare write address */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBADDRESS0, ui32Addr);
+
+       /* Prepare write data and initiate write */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBDATA0, ui32Value);
+
+       /* Wait until system bus is idle */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                pui32RegsBase + RGX_CR_FWCORE_DMI_SBCS/sizeof(IMG_UINT32),
+                                0U,
+                                RGX_CR_FWCORE_DMI_SBCS_SBBUSY_EN,
+                                POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: System Bus did not go idle in time (sbcs = 0x%x)",
+                        __func__, OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FWCORE_DMI_SBCS)));
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvWriteMem
+
+@Description    Write a value to the given address in RISC-V memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXRiscvWriteMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+                              IMG_UINT32 ui32Addr,
+                              IMG_UINT32 ui32Value)
+{
+       if (ui32Addr >= RGXRISCVFW_COREMEM_BASE && ui32Addr <= RGXRISCVFW_COREMEM_END)
+       {
+               return RGXRiscvWriteAbstractMem(psDevInfo, ui32Addr, ui32Value);
+       }
+
+       return RGXRiscvWriteSysBusMem(psDevInfo, ui32Addr, ui32Value);
+}
+#endif /* !defined(EMULATOR) */
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvDmiOp
+
+@Description    Acquire the powerlock and perform an operation on the RISC-V
+                Debug Module Interface, but only if the GPU is powered on.
+
+@Input          psDevInfo       Pointer to device info
+@InOut          pui64DMI        Encoding of a request for the RISC-V Debug
+                                Module with same format as the 'dmi' register
+                                from the RISC-V debug specification (v0.13+).
+                                On return, this is updated with the result of
+                                the request, encoded the same way.
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvDmiOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                           IMG_UINT64 *pui64DMI)
+{
+#if defined(NO_HARDWARE) && defined(PDUMP)
+       PVR_UNREFERENCED_PARAMETER(psDevInfo);
+       PVR_UNREFERENCED_PARAMETER(pui64DMI);
+
+       /* Accessing DM registers is not supported in nohw/pdump */
+       return PVRSRV_ERROR_NOT_SUPPORTED;
+#else
+#define DMI_BASE     RGX_CR_FWCORE_DMI_RESERVED00
+#define DMI_STRIDE  (RGX_CR_FWCORE_DMI_RESERVED01 - RGX_CR_FWCORE_DMI_RESERVED00)
+#define DMI_REG(r)  ((DMI_BASE) + (DMI_STRIDE) * (r))
+
+#define DMI_OP_SHIFT            0U
+#define DMI_OP_MASK             0x3ULL
+#define DMI_DATA_SHIFT          2U
+#define DMI_DATA_MASK           0x3FFFFFFFCULL
+#define DMI_ADDRESS_SHIFT       34U
+#define DMI_ADDRESS_MASK        0xFC00000000ULL
+
+#define DMI_OP_NOP                 0U
+#define DMI_OP_READ                1U
+#define DMI_OP_WRITE           2U
+#define DMI_OP_RESERVED                3U
+
+#define DMI_OP_STATUS_SUCCESS  0U
+#define DMI_OP_STATUS_RESERVED 1U
+#define DMI_OP_STATUS_FAILED   2U
+#define DMI_OP_STATUS_BUSY         3U
+
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       PVRSRV_DEV_POWER_STATE ePowerState;
+       PVRSRV_ERROR eError;
+       IMG_UINT64 ui64Op, ui64Address, ui64Data;
+
+       ui64Op      = (*pui64DMI & DMI_OP_MASK) >> DMI_OP_SHIFT;
+       ui64Address = (*pui64DMI & DMI_ADDRESS_MASK) >> DMI_ADDRESS_SHIFT;
+       ui64Data    = (*pui64DMI & DMI_DATA_MASK) >> DMI_DATA_SHIFT;
+
+       eError = PVRSRVPowerLock(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to acquire powerlock (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               ui64Op = DMI_OP_STATUS_FAILED;
+               goto dmiop_update;
+       }
+
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to retrieve RGX power state (%s)",
+                               __func__, PVRSRVGetErrorString(eError)));
+               ui64Op = DMI_OP_STATUS_FAILED;
+               goto dmiop_release_lock;
+       }
+
+       if (ePowerState == PVRSRV_DEV_POWER_STATE_ON)
+       {
+               switch (ui64Op)
+               {
+                       case DMI_OP_NOP:
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       case DMI_OP_WRITE:
+                               OSWriteHWReg32(psDevInfo->pvRegsBaseKM,
+                                               DMI_REG(ui64Address),
+                                               (IMG_UINT32)ui64Data);
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       case DMI_OP_READ:
+                               ui64Data = (IMG_UINT64)OSReadHWReg32(psDevInfo->pvRegsBaseKM,
+                                               DMI_REG(ui64Address));
+                               ui64Op = DMI_OP_STATUS_SUCCESS;
+                               break;
+                       default:
+                               PVR_DPF((PVR_DBG_ERROR, "%s: unknown op %u", __func__, (IMG_UINT32)ui64Op));
+                               ui64Op = DMI_OP_STATUS_FAILED;
+                               break;
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: Accessing RISC-V Debug Module is not "
+                                       "possible while the GPU is powered off", __func__));
+
+               ui64Op = DMI_OP_STATUS_FAILED;
+       }
+
+dmiop_release_lock:
+       PVRSRVPowerUnlock(psDeviceNode);
+
+dmiop_update:
+       *pui64DMI = (ui64Op << DMI_OP_SHIFT) |
+               (ui64Address << DMI_ADDRESS_SHIFT) |
+               (ui64Data << DMI_DATA_SHIFT);
+
+       return eError;
+#endif
+}
+
+/*
+       RGXReadMETAAddr
+*/
+static PVRSRV_ERROR RGXReadMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 *pui32Value)
+{
+       IMG_UINT8 __iomem  *pui8RegBase = psDevInfo->pvRegsBaseKM;
+       IMG_UINT32 ui32PollValue;
+       IMG_UINT32 ui32PollMask;
+       IMG_UINT32 ui32PollRegOffset;
+       IMG_UINT32 ui32ReadOffset;
+       IMG_UINT32 ui32WriteOffset;
+       IMG_UINT32 ui32WriteValue;
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+       {
+               ui32PollValue = RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                               | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN;
+               ui32PollMask = RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                               | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN;
+               ui32PollRegOffset = RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES;
+               ui32WriteOffset = RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES;
+               ui32WriteValue = ui32METAAddr | RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES__RD_EN;
+               CHECK_HWBRN_68777(ui32WriteValue);
+               ui32ReadOffset = RGX_CR_META_SP_MSLVDATAX__META_REGISTER_UNPACKED_ACCESSES;
+       }
+       else
+       {
+               ui32PollValue = RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN;
+               ui32PollMask = RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN;
+               ui32PollRegOffset = RGX_CR_META_SP_MSLVCTRL1;
+               ui32WriteOffset = RGX_CR_META_SP_MSLVCTRL0;
+               ui32WriteValue = ui32METAAddr | RGX_CR_META_SP_MSLVCTRL0_RD_EN;
+               ui32ReadOffset = RGX_CR_META_SP_MSLVDATAX;
+       }
+
+       /* Wait for Slave Port to be Ready */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                       (IMG_UINT32 __iomem *) (pui8RegBase + ui32PollRegOffset),
+               ui32PollValue,
+               ui32PollMask,
+               POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Issue the Read */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32WriteOffset, ui32WriteValue);
+       (void)OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32WriteOffset);
+
+       /* Wait for Slave Port to be Ready: read complete */
+       if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                       (IMG_UINT32 __iomem *) (pui8RegBase + ui32PollRegOffset),
+               ui32PollValue,
+               ui32PollMask,
+               POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+       {
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       /* Read the value */
+       *pui32Value = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32ReadOffset);
+
+       return PVRSRV_OK;
+}
+
+/*
+       RGXWriteMETAAddr
+*/
+static PVRSRV_ERROR RGXWriteMETAAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32METAAddr, IMG_UINT32 ui32Value)
+{
+       IMG_UINT8 __iomem *pui8RegBase = psDevInfo->pvRegsBaseKM;
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+       {
+               /* Wait for Slave Port to be Ready */
+               if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                               (IMG_UINT32 __iomem *)(pui8RegBase + RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES),
+                               RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                               | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                               RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                               | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                               POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+               {
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+
+               /* Issue the Write */
+               CHECK_HWBRN_68777(ui32METAAddr);
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0__META_REGISTER_UNPACKED_ACCESSES, ui32METAAddr);
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAT__META_REGISTER_UNPACKED_ACCESSES, ui32Value);
+       }
+       else
+       {
+               /* Wait for Slave Port to be Ready */
+               if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                               (IMG_UINT32 __iomem *)(pui8RegBase + RGX_CR_META_SP_MSLVCTRL1),
+                               RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                               RGX_CR_META_SP_MSLVCTRL1_READY_EN|RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                               POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+               {
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+
+               /* Issue the Write */
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0, ui32METAAddr);
+               (void) OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVCTRL0); /* Fence write */
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAT, ui32Value);
+               (void) OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_META_SP_MSLVDATAT); /* Fence write */
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXReadFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 *pui32Value)
+{
+       PVRSRV_ERROR eError;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               eError = RGXReadMETAAddr(psDevInfo, ui32FWAddr, pui32Value);
+       }
+#if !defined(EMULATOR)
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               eError = RGXRiscvReadMem(psDevInfo, ui32FWAddr, pui32Value);
+       }
+#endif
+       else
+       {
+               eError = PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXWriteFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FWAddr, IMG_UINT32 ui32Value)
+{
+       PVRSRV_ERROR eError;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               eError = RGXWriteMETAAddr(psDevInfo, ui32FWAddr, ui32Value);
+       }
+#if !defined(EMULATOR)
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               eError = RGXRiscvWriteMem(psDevInfo, ui32FWAddr, ui32Value);
+       }
+#endif
+       else
+       {
+               eError = PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       return eError;
+
+}
+
+PVRSRV_ERROR RGXGetFwMapping(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32FwVA,
+                             IMG_CPU_PHYADDR *psCpuPA,
+                             IMG_DEV_PHYADDR *psDevPA,
+                             IMG_UINT64 *pui64RawPTE)
+{
+       PVRSRV_ERROR eError       = PVRSRV_OK;
+       IMG_CPU_PHYADDR sCpuPA    = {0U};
+       IMG_DEV_PHYADDR sDevPA    = {0U};
+       IMG_UINT64 ui64RawPTE     = 0U;
+       MMU_FAULT_DATA sFaultData = {0U};
+       MMU_CONTEXT *psFwMMUCtx   = psDevInfo->psKernelMMUCtx;
+       IMG_UINT32 ui32FwHeapBase = (IMG_UINT32) (RGX_FIRMWARE_RAW_HEAP_BASE & UINT_MAX);
+       IMG_UINT32 ui32FwHeapEnd  = ui32FwHeapBase + (RGX_NUM_OS_SUPPORTED * RGX_FIRMWARE_RAW_HEAP_SIZE);
+       IMG_UINT32 ui32OSID       = (ui32FwVA - ui32FwHeapBase) / RGX_FIRMWARE_RAW_HEAP_SIZE;
+       IMG_UINT32 ui32HeapId;
+       PHYS_HEAP *psPhysHeap;
+       IMG_UINT64 ui64FwDataBaseMask;
+       IMG_DEV_VIRTADDR sDevVAddr;
+
+       /* default to 4K pages */
+       IMG_UINT32 ui32FwPageSize = BIT(RGX_MMUCTRL_PAGE_4KB_RANGE_SHIFT);
+       IMG_UINT32 ui32PageOffset = (ui32FwVA & (ui32FwPageSize - 1));
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM((ui32OSID < RGX_NUM_OS_SUPPORTED),
+                                     eError, ErrorExit);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(((psCpuPA != NULL) ||
+                                      (psDevPA != NULL) ||
+                                      (pui64RawPTE != NULL)),
+                                     eError, ErrorExit);
+
+       PVR_LOG_GOTO_IF_INVALID_PARAM(((ui32FwVA >= ui32FwHeapBase) &&
+                                     (ui32FwVA < ui32FwHeapEnd)),
+                                     eError, ErrorExit);
+
+       ui32HeapId = (ui32OSID == RGXFW_HOST_OS) ?
+                     PVRSRV_PHYS_HEAP_FW_MAIN : (PVRSRV_PHYS_HEAP_FW_PREMAP0 + ui32OSID);
+       psPhysHeap = psDevInfo->psDeviceNode->apsPhysHeap[ui32HeapId];
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               ui64FwDataBaseMask = ~(RGXFW_SEGMMU_DATA_META_CACHE_MASK |
+                                        RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK |
+                                        RGXFW_SEGMMU_DATA_BASE_ADDRESS);
+       }
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               ui64FwDataBaseMask = ~(RGXRISCVFW_GET_REGION_BASE(0xF));
+       }
+       else
+       {
+               PVR_LOG_GOTO_WITH_ERROR("RGXGetFwMapping", eError, PVRSRV_ERROR_NOT_IMPLEMENTED, ErrorExit);
+       }
+
+       sDevVAddr.uiAddr = (ui32FwVA & ui64FwDataBaseMask) | RGX_FIRMWARE_RAW_HEAP_BASE;
+
+       /* Fw CPU shares a subset of the GPU's VA space */
+       MMU_CheckFaultAddress(psFwMMUCtx, &sDevVAddr, &sFaultData);
+
+       ui64RawPTE = sFaultData.sLevelData[MMU_LEVEL_1].ui64Address;
+
+       if (eError == PVRSRV_OK)
+       {
+               if (!BITMASK_HAS(ui64RawPTE, RGX_MMUCTRL_PT_DATA_VALID_EN))
+               {
+                       /* don't report invalid pages */
+                       eError = PVRSRV_ERROR_DEVICEMEM_NO_MAPPING;
+               }
+               else
+               {
+                       sDevPA.uiAddr = ui32PageOffset + (ui64RawPTE & ~RGX_MMUCTRL_PT_DATA_PAGE_CLRMSK);
+
+                       /* Only the Host's Firmware heap is present in the Host's CPU IPA space */
+                       if (ui32OSID == RGXFW_HOST_OS)
+                       {
+                               PhysHeapDevPAddrToCpuPAddr(psPhysHeap, 1, &sCpuPA, &sDevPA);
+                       }
+                       else
+                       {
+                               sCpuPA.uiAddr = 0U;
+                       }
+               }
+       }
+
+       if (psCpuPA != NULL)
+       {
+               *psCpuPA = sCpuPA;
+       }
+
+       if (psDevPA != NULL)
+       {
+               *psDevPA = sDevPA;
+       }
+
+       if (pui64RawPTE != NULL)
+       {
+               *pui64RawPTE = ui64RawPTE;
+       }
+
+ErrorExit:
+       return eError;
+}
+/******************************************************************************
+ End of file (rgxfwutils.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxfwutils.h
new file mode 100644 (file)
index 0000000..dbe723b
--- /dev/null
@@ -0,0 +1,1371 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX firmware utility routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX firmware utility routines
+@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.
+*/ /**************************************************************************/
+
+#ifndef RGXFWUTILS_H
+#define RGXFWUTILS_H
+
+#include "rgx_memallocflags.h"
+#include "rgxdevice.h"
+#include "rgxccb.h"
+#include "devicemem.h"
+#include "device.h"
+#include "pvr_notifier.h"
+#include "pvrsrv.h"
+#include "connection_server.h"
+#include "rgxta3d.h"
+#include "devicemem_utils.h"
+#include "rgxmem.h"
+
+#define RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT   "FwRawOSID%d" /*!< RGX Raw Firmware Heap identifier */
+
+static INLINE PVRSRV_ERROR _SelectDevMemHeap(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                        PVRSRV_MEMALLOCFLAGS_T *puiFlags,
+                                                                                        DEVMEM_HEAP **ppsFwHeap)
+{
+       PVRSRV_PHYS_HEAP ePhysHeap = (PVRSRV_PHYS_HEAP)(PVRSRV_PHYS_HEAP)PVRSRV_GET_PHYS_HEAP_HINT(*puiFlags);
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       switch (ePhysHeap)
+       {
+#if defined(SUPPORT_SECURITY_VALIDATION)
+               /* call with GPU_SECURE from RGXSetupFwSysData */
+               case PVRSRV_PHYS_HEAP_GPU_SECURE:
+#endif
+               case PVRSRV_PHYS_HEAP_FW_CODE:
+               case PVRSRV_PHYS_HEAP_FW_PRIV_DATA:
+               case PVRSRV_PHYS_HEAP_FW_MAIN:
+               {
+                       *ppsFwHeap = psDevInfo->psFirmwareMainHeap;
+                       break;
+               }
+               case PVRSRV_PHYS_HEAP_FW_CONFIG:
+               {
+                       *ppsFwHeap = psDevInfo->psFirmwareConfigHeap;
+                       break;
+               }
+               case PVRSRV_PHYS_HEAP_FW_PREMAP0:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP1:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP2:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP3:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP4:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP5:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP6:
+               case PVRSRV_PHYS_HEAP_FW_PREMAP7:
+               {
+                       IMG_UINT32 ui32OSID = ePhysHeap - PVRSRV_PHYS_HEAP_FW_PREMAP0;
+
+                       PVR_LOG_RETURN_IF_INVALID_PARAM(ui32OSID < RGX_NUM_OS_SUPPORTED, "ui32OSID");
+                       *ppsFwHeap = psDevInfo->psGuestFirmwareRawHeap[ui32OSID];
+                       break;
+               }
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: invalid phys heap", __func__));
+                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                       break;
+               }
+       }
+
+       return eError;
+}
+
+/*
+ * Firmware-only allocation (which are initialised by the host) must be aligned to the SLC cache line size.
+ * This is because firmware-only allocations are GPU_CACHE_INCOHERENT and this causes problems
+ * if two allocations share the same cache line; e.g. the initialisation of the second allocation won't
+ * make it into the SLC cache because it has been already loaded when accessing the content of the first allocation.
+ */
+static INLINE PVRSRV_ERROR DevmemFwAllocate(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                       IMG_DEVMEM_SIZE_T uiSize,
+                                                                                       PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                                                                       const IMG_CHAR *pszText,
+                                                                                       DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+       IMG_DEV_VIRTADDR sTmpDevVAddr;
+       PVRSRV_ERROR eError;
+       DEVMEM_HEAP *psFwHeap;
+       IMG_DEVMEM_ALIGN_T uiAlign;
+
+       PVR_DPF_ENTERED;
+
+       /* Enforce the standard pre-fix naming scheme callers must follow */
+       PVR_ASSERT((pszText != NULL) && (pszText[0] == 'F') && (pszText[1] == 'w'));
+
+       /* Imported from AppHint , flag to poison allocations when freed */
+       uiFlags |= psDevInfo->uiFWPoisonOnFreeFlag;
+
+       eError = _SelectDevMemHeap(psDevInfo, &uiFlags, &psFwHeap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       uiAlign = (psFwHeap == psDevInfo->psFirmwareConfigHeap) ?
+                               (RGX_FIRMWARE_CONFIG_HEAP_ALLOC_GRANULARITY) :
+                               (GET_ROGUE_CACHE_LINE_SIZE(RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS)));
+
+       eError = DevmemAllocateAndMap(psFwHeap,
+                               uiSize,
+                               uiAlign,
+                               uiFlags,
+                               pszText,
+                               ppsMemDescPtr,
+                               &sTmpDevVAddr);
+
+       PVR_DPF_RETURN_RC(eError);
+}
+
+static INLINE PVRSRV_ERROR DevmemFwAllocateExportable(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                                         IMG_DEVMEM_SIZE_T uiSize,
+                                                                                                         IMG_DEVMEM_ALIGN_T uiAlign,
+                                                                                                         PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                                                                                         const IMG_CHAR *pszText,
+                                                                                                         DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+       IMG_DEV_VIRTADDR sTmpDevVAddr;
+       PVRSRV_ERROR eError;
+       DEVMEM_HEAP *psFwHeap;
+
+       PVR_DPF_ENTERED;
+
+       /* Enforce the standard pre-fix naming scheme callers must follow */
+       PVR_ASSERT((pszText != NULL) &&
+                       (pszText[0] == 'F') && (pszText[1] == 'w') &&
+                       (pszText[2] == 'E') && (pszText[3] == 'x'));
+
+       /* Imported from AppHint , flag to poison allocations when freed */
+       uiFlags |= psDevInfo->uiFWPoisonOnFreeFlag;
+
+       eError = _SelectDevMemHeap(psDevInfo, &uiFlags, &psFwHeap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       eError = DevmemAllocateExportable(psDeviceNode,
+                                                                         uiSize,
+                                                                         uiAlign,
+                                                                         DevmemGetHeapLog2PageSize(psFwHeap),
+                                                                         uiFlags,
+                                                                         pszText,
+                                                                         ppsMemDescPtr);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "FW DevmemAllocateExportable failed (%u)", eError));
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       /*
+               We need to map it so the heap for this allocation
+               is set
+       */
+       eError = DevmemMapToDevice(*ppsMemDescPtr,
+                                                          psDevInfo->psFirmwareMainHeap,
+                                                          &sTmpDevVAddr);
+       if (eError != PVRSRV_OK)
+       {
+               DevmemFree(*ppsMemDescPtr);
+               PVR_DPF((PVR_DBG_ERROR, "FW DevmemMapToDevice failed (%u)", eError));
+       }
+
+       PVR_DPF_RETURN_RC1(eError, *ppsMemDescPtr);
+}
+
+static INLINE PVRSRV_ERROR DevmemFwAllocateSparse(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                               IMG_DEVMEM_SIZE_T uiSize,
+                                                                                               IMG_DEVMEM_SIZE_T uiChunkSize,
+                                                                                               IMG_UINT32 ui32NumPhysChunks,
+                                                                                               IMG_UINT32 ui32NumVirtChunks,
+                                                                                               IMG_UINT32 *pui32MappingTable,
+                                                                                               PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                                                                                               const IMG_CHAR *pszText,
+                                                                                               DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+       IMG_DEV_VIRTADDR sTmpDevVAddr;
+       PVRSRV_ERROR eError;
+       DEVMEM_HEAP *psFwHeap;
+       IMG_UINT32 ui32Align;
+
+       PVR_DPF_ENTERED;
+
+       /* Enforce the standard pre-fix naming scheme callers must follow */
+       PVR_ASSERT((pszText != NULL) && (pszText[0] == 'F') && (pszText[1] == 'w'));
+       ui32Align = GET_ROGUE_CACHE_LINE_SIZE(RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS));
+
+       /* Imported from AppHint , flag to poison allocations when freed */
+       uiFlags |= psDevInfo->uiFWPoisonOnFreeFlag;
+
+       eError = _SelectDevMemHeap(psDevInfo, &uiFlags, &psFwHeap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       eError = DevmemAllocateSparse(psDevInfo->psDeviceNode,
+                                                               uiSize,
+                                                               uiChunkSize,
+                                                               ui32NumPhysChunks,
+                                                               ui32NumVirtChunks,
+                                                               pui32MappingTable,
+                                                               ui32Align,
+                                                               DevmemGetHeapLog2PageSize(psFwHeap),
+                                                               uiFlags | PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING,
+                                                               pszText,
+                                                               ppsMemDescPtr);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF_RETURN_RC(eError);
+       }
+       /*
+               We need to map it so the heap for this allocation
+               is set
+       */
+       eError = DevmemMapToDevice(*ppsMemDescPtr,
+                                  psFwHeap,
+                                  &sTmpDevVAddr);
+       if (eError != PVRSRV_OK)
+       {
+               DevmemFree(*ppsMemDescPtr);
+               PVR_DPF_RETURN_RC(eError);
+       }
+
+       PVR_DPF_RETURN_RC(eError);
+}
+
+
+static INLINE void DevmemFwUnmapAndFree(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               DEVMEM_MEMDESC *psMemDesc)
+{
+       PVR_DPF_ENTERED1(psMemDesc);
+
+       DevmemReleaseDevVirtAddr(psMemDesc);
+       DevmemFree(psMemDesc);
+
+       PVR_DPF_RETURN;
+}
+
+
+/*
+ * This function returns the value of the hardware register RGX_CR_TIMER
+ * which is a timer counting in ticks.
+ */
+
+static INLINE IMG_UINT64 RGXReadHWTimerReg(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_UINT64 ui64Time = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TIMER);
+
+       /*
+       *  In order to avoid having to issue three 32-bit reads to detect the
+       *  lower 32-bits wrapping, the MSB of the low 32-bit word is duplicated
+       *  in the MSB of the high 32-bit word. If the wrap happens, we just read
+       *  the register again (it will not wrap again so soon).
+       */
+       if ((ui64Time ^ (ui64Time << 32)) & ~RGX_CR_TIMER_BIT31_CLRMSK)
+       {
+               ui64Time = OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_TIMER);
+       }
+
+       return (ui64Time & ~RGX_CR_TIMER_VALUE_CLRMSK) >> RGX_CR_TIMER_VALUE_SHIFT;
+}
+
+/*
+ * This FW Common Context is only mapped into kernel for initialisation and cleanup purposes.
+ * Otherwise this allocation is only used by the FW.
+ * Therefore the GPU cache doesn't need coherency, and write-combine will
+ * suffice on the CPU side (WC buffer will be flushed at the first kick)
+ */
+#define RGX_FWCOMCTX_ALLOCFLAGS      (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                      PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED)| \
+                                      PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                      PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                      PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT | \
+                                      PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                      PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                      PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                      PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                      PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                      PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
+
+#define RGX_FWSHAREDMEM_MAIN_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                         PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                         PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                         PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                         PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                         PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
+
+#define RGX_FWSHAREDMEM_CONFIG_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                           PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                           PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                           PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CONFIG))
+
+#define RGX_FWSHAREDMEM_GPU_RO_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                           PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                           PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC | \
+                                           PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN))
+
+/* Firmware memory that is not accessible by the CPU. */
+#define RGX_FWSHAREDMEM_GPU_ONLY_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                             PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                             PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+
+/* Firmware shared memory that is supposed to be read-only to the CPU.
+ * In reality it isn't due to ZERO_ON_ALLOC which enforces CPU_WRITEABLE
+ * flag on the allocations. */
+#define RGX_FWSHAREDMEM_CPU_RO_ALLOCFLAGS (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) | \
+                                           PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
+                                           PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE | \
+                                           PVRSRV_MEMALLOCFLAG_GPU_UNCACHED | \
+                                           PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC | \
+                                           PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC)
+
+/* data content being kept from previous boot cycles from physical memory must not be cleared during allocation */
+#define RGX_AUTOVZ_KEEP_FW_DATA_MASK(bKeepMem) ((bKeepMem) ? (~PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) : (~0ULL))
+
+/******************************************************************************
+ * RGXSetFirmwareAddress Flags
+ *****************************************************************************/
+#define RFW_FWADDR_FLAG_NONE           (0)                     /*!< Void flag */
+#define RFW_FWADDR_NOREF_FLAG          (1U << 0)       /*!< It is safe to immediately release the reference to the pointer,
+                                                                                                 otherwise RGXUnsetFirmwareAddress() must be call when finished. */
+
+IMG_BOOL RGXTraceBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo);
+PVRSRV_ERROR RGXTraceBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO* psDevInfo, PVRSRV_MEMALLOCFLAGS_T uiAllocFlags);
+
+#if defined(SUPPORT_POWMON_COMPONENT) && defined(SUPPORT_POWER_VALIDATION_VIA_DEBUGFS)
+IMG_BOOL RGXPowmonBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo);
+PVRSRV_ERROR RGXPowmonBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+#if defined(SUPPORT_TBI_INTERFACE)
+IMG_BOOL RGXTBIBufferIsInitRequired(PVRSRV_RGXDEV_INFO *psDevInfo);
+PVRSRV_ERROR RGXTBIBufferInitOnDemandResources(PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+PVRSRV_ERROR RGXSetupFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                              IMG_BOOL                 bEnableSignatureChecks,
+                              IMG_UINT32               ui32SignatureChecksBufSize,
+                              IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                              IMG_UINT64               ui64HWPerfFilter,
+                              IMG_UINT32               ui32ConfigFlags,
+                              IMG_UINT32               ui32ConfigFlagsExt,
+                              IMG_UINT32               ui32FwOsCfgFlags,
+                              IMG_UINT32               ui32LogType,
+                              IMG_UINT32               ui32FilterFlags,
+                              IMG_UINT32               ui32JonesDisableMask,
+                              IMG_UINT32               ui32HWRDebugDumpLimit,
+                              IMG_UINT32               ui32HWPerfCountersDataSize,
+                              IMG_UINT32               ui32RenderKillingCtl,
+                              IMG_UINT32               ui32CDMTDMKillingCtl,
+                              IMG_UINT32               *pui32TPUTrilinearFracMask,
+                              IMG_UINT32               *pui32USRMNumRegions,
+                              IMG_UINT64               *pui64UVBRMNumRegions,
+                              RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf,
+                              FW_PERF_CONF             eFirmwarePerf,
+                              IMG_UINT32               ui32KCCBSizeLog2,
+                              IMG_UINT32               ui32AvailableSPUMask,
+                                                         IMG_UINT32               ui32AvailableRACMask);
+
+
+
+void RGXFreeFirmware(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*************************************************************************/ /*!
+@Function       RGXSetupFwAllocation
+
+@Description    Sets a pointer in a firmware data structure.
+
+@Input          psDevInfo       Device Info struct
+@Input          uiAllocFlags    Flags determining type of memory allocation
+@Input          ui32Size        Size of memory allocation
+@Input          pszName         Allocation label
+@Input          psFwPtr         Address of the firmware pointer to set
+@Input          ppvCpuPtr       Address of the cpu pointer to set
+@Input          ui32DevVAFlags  Any combination of  RFW_FWADDR_*_FLAG
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSetupFwAllocation(PVRSRV_RGXDEV_INFO   *psDevInfo,
+                                                                 PVRSRV_MEMALLOCFLAGS_T uiAllocFlags,
+                                                                 IMG_UINT32           ui32Size,
+                                                                 const IMG_CHAR       *pszName,
+                                                                 DEVMEM_MEMDESC       **ppsMemDesc,
+                                                                 RGXFWIF_DEV_VIRTADDR *psFwPtr,
+                                                                 void                 **ppvCpuPtr,
+                                                                 IMG_UINT32           ui32DevVAFlags);
+
+/*************************************************************************/ /*!
+@Function       RGXSetFirmwareAddress
+
+@Description    Sets a pointer in a firmware data structure.
+
+@Input          ppDest          Address of the pointer to set
+@Input          psSrc           MemDesc describing the pointer
+@Input          ui32Flags       Any combination of RFW_FWADDR_*_FLAG
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSetFirmwareAddress(RGXFWIF_DEV_VIRTADDR        *ppDest,
+                                                                  DEVMEM_MEMDESC               *psSrc,
+                                                                  IMG_UINT32                   uiOffset,
+                                                                  IMG_UINT32                   ui32Flags);
+
+
+/*************************************************************************/ /*!
+@Function       RGXSetMetaDMAAddress
+
+@Description    Fills a Firmware structure used to setup the Meta DMA with two
+                pointers to the same data, one on 40 bit and one on 32 bit
+                (pointer in the FW memory space).
+
+@Input          ppDest          Address of the structure to set
+@Input          psSrcMemDesc    MemDesc describing the pointer
+@Input          psSrcFWDevVAddr Firmware memory space pointer
+
+@Return         void
+*/ /**************************************************************************/
+void RGXSetMetaDMAAddress(RGXFWIF_DMA_ADDR             *psDest,
+                                                 DEVMEM_MEMDESC                *psSrcMemDesc,
+                                                 RGXFWIF_DEV_VIRTADDR  *psSrcFWDevVAddr,
+                                                 IMG_UINT32                    uiOffset);
+
+
+/*************************************************************************/ /*!
+@Function       RGXUnsetFirmwareAddress
+
+@Description    Unsets a pointer in a firmware data structure
+
+@Input          psSrc           MemDesc describing the pointer
+
+@Return         void
+*/ /**************************************************************************/
+void RGXUnsetFirmwareAddress(DEVMEM_MEMDESC *psSrc);
+
+PVRSRV_ERROR RGXWriteMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue);
+PVRSRV_ERROR RGXReadMetaRegThroughSP(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32* ui32RegValue);
+
+/*************************************************************************/ /*!
+@Function       FWCommonContextAllocate
+
+@Description    Allocate a FW common context. This allocates the HW memory
+                for the context, the CCB and wires it all together.
+
+@Input          psConnection            Connection this context is being created on
+@Input          psDeviceNode            Device node to create the FW context on
+                                        (must be RGX device node)
+@Input          eRGXCCBRequestor        RGX_CCB_REQUESTOR_TYPE enum constant which
+                                        which represents the requestor of this FWCC
+@Input          eDM                     Data Master type
+@Input          psServerMMUContext      Server MMU memory context.
+@Input          psAllocatedMemDesc      Pointer to pre-allocated MemDesc to use
+                                        as the FW context or NULL if this function
+                                        should allocate it
+@Input          ui32AllocatedOffset     Offset into pre-allocate MemDesc to use
+                                        as the FW context. If psAllocatedMemDesc
+                                        is NULL then this parameter is ignored
+@Input          psFWMemContextMemDesc   MemDesc of the FW memory context this
+                                        common context resides on
+@Input          psContextStateMemDesc   FW context state (context switch) MemDesc
+@Input          ui32CCBAllocSizeLog2    Size of the CCB for this context
+@Input          ui32CCBMaxAllocSizeLog2 Maximum size to which CCB can grow for this context
+@Input          ui32ContextFlags        Flags which specify properties of the context
+@Input          ui32Priority            Priority of the context
+@Input          ui32MaxDeadlineMS       Max deadline limit in MS that the workload can run
+@Input          ui64RobustnessAddress   Address for FW to signal a context reset
+@Input          psInfo                  Structure that contains extra info
+                                        required for the creation of the context
+                                        (elements might change from core to core)
+@Return         PVRSRV_OK if the context was successfully created
+*/ /**************************************************************************/
+PVRSRV_ERROR FWCommonContextAllocate(CONNECTION_DATA *psConnection,
+                                                                        PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                        RGX_CCB_REQUESTOR_TYPE eRGXCCBRequestor,
+                                                                        RGXFWIF_DM eDM,
+                                                                        SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                                        DEVMEM_MEMDESC *psAllocatedMemDesc,
+                                                                        IMG_UINT32 ui32AllocatedOffset,
+                                                                        DEVMEM_MEMDESC *psFWMemContextMemDesc,
+                                                                        DEVMEM_MEMDESC *psContextStateMemDesc,
+                                                                        IMG_UINT32 ui32CCBAllocSizeLog2,
+                                                                        IMG_UINT32 ui32CCBMaxAllocSizeLog2,
+                                                                        IMG_UINT32 ui32ContextFlags,
+                                                                        IMG_UINT32 ui32Priority,
+                                                                        IMG_UINT32 ui32MaxDeadlineMS,
+                                                                        IMG_UINT64 ui64RobustnessAddress,
+                                                                        RGX_COMMON_CONTEXT_INFO *psInfo,
+                                                                        RGX_SERVER_COMMON_CONTEXT **ppsServerCommonContext);
+
+void FWCommonContextFree(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+PRGXFWIF_FWCOMMONCONTEXT FWCommonContextGetFWAddress(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+RGX_CLIENT_CCB *FWCommonContextGetClientCCB(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+SERVER_MMU_CONTEXT *FWCommonContextGetServerMMUCtx(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+RGX_CONTEXT_RESET_REASON FWCommonContextGetLastResetReason(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                                           IMG_UINT32 *pui32LastResetJobRef);
+
+PVRSRV_RGXDEV_INFO* FWCommonContextGetRGXDevInfo(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext);
+
+PVRSRV_ERROR RGXGetFWCommonContextAddrFromServerMMUCtx(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                          SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                                                                          PRGXFWIF_FWCOMMONCONTEXT *psFWCommonContextFWAddr);
+
+PVRSRV_ERROR FWCommonContextSetFlags(RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                     IMG_UINT32 ui32ContextFlags);
+
+/*!
+*******************************************************************************
+@Function       RGXScheduleProcessQueuesKM
+
+@Description    Software command complete handler
+                (sends uncounted kicks for all the DMs through the MISR)
+
+@Input          hCmdCompHandle  RGX device node
+
+@Return         None
+******************************************************************************/
+void RGXScheduleProcessQueuesKM(PVRSRV_CMDCOMP_HANDLE hCmdCompHandle);
+
+#if defined(SUPPORT_VALIDATION)
+/*!
+*******************************************************************************
+@Function       RGXScheduleRgxRegCommand
+
+@Input          psDevInfo       Device Info struct
+@Input          ui64RegVal      Value to write into FW register
+@Input          ui64Size        Register size
+@Input          ui32Offset      Register Offset
+@Input          bWriteOp        Register Write or Read toggle
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXScheduleRgxRegCommand(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                         IMG_UINT64 ui64RegVal,
+                                                                         IMG_UINT64 ui64Size,
+                                                                         IMG_UINT32 ui32Offset,
+                                                                         IMG_BOOL bWriteOp);
+
+#endif
+
+/*!
+*******************************************************************************
+
+@Function       RGXInstallProcessQueuesMISR
+
+@Description    Installs the MISR to handle Process Queues operations
+
+@Input          phMISR          Pointer to the MISR handler
+@Input          psDeviceNode    RGX Device node
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXInstallProcessQueuesMISR(IMG_HANDLE *phMISR, PVRSRV_DEVICE_NODE *psDeviceNode);
+
+PVRSRV_ERROR RGXSendCommandsFromDeferredList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bPoll);
+
+/*************************************************************************/ /*!
+@Function       RGXSendCommandWithPowLockAndGetKCCBSlot
+
+@Description    Sends a command to a particular DM without honouring
+                pending cache operations but taking the power lock.
+
+@Input          psDevInfo       Device Info
+@Input          psKCCBCmd       The cmd to send.
+@Input          ui32PDumpFlags  Pdump flags
+@Output         pui32CmdKCCBSlot   When non-NULL:
+                                   - Pointer on return contains the kCCB slot
+                                     number in which the command was enqueued.
+                                   - Resets the value of the allotted slot to
+                                     RGXFWIF_KCCB_RTN_SLOT_RST
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSendCommandWithPowLockAndGetKCCBSlot(PVRSRV_RGXDEV_INFO        *psDevInfo,
+                                                                                                        RGXFWIF_KCCB_CMD       *psKCCBCmd,
+                                                                                                        IMG_UINT32                     ui32PDumpFlags,
+                                                                                                        IMG_UINT32                     *pui32CmdKCCBSlot);
+
+#define RGXSendCommandWithPowLock(psDevInfo, psKCCBCmd, ui32PDumpFlags) \
+  RGXSendCommandWithPowLockAndGetKCCBSlot(psDevInfo, psKCCBCmd, ui32PDumpFlags, NULL)
+
+/*************************************************************************/ /*!
+@Function       RGXSendCommandAndGetKCCBSlot
+
+@Description    Sends a command to a particular DM without honouring
+                pending cache operations or the power lock.
+                The function flushes any deferred KCCB commands first.
+
+@Input          psDevInfo       Device Info
+@Input          psKCCBCmd       The cmd to send.
+@Input          uiPdumpFlags    PDump flags.
+@Output         pui32CmdKCCBSlot   When non-NULL:
+                                   - Pointer on return contains the kCCB slot
+                                     number in which the command was enqueued.
+                                   - Resets the value of the allotted slot to
+                                     RGXFWIF_KCCB_RTN_SLOT_RST
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXSendCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                 RGXFWIF_KCCB_CMD   *psKCCBCmd,
+                                                                                 PDUMP_FLAGS_T      uiPdumpFlags,
+                                                                                 IMG_UINT32         *pui32CmdKCCBSlot);
+
+#define RGXSendCommand(psDevInfo, psKCCBCmd, ui32PDumpFlags) \
+  RGXSendCommandAndGetKCCBSlot(psDevInfo, psKCCBCmd, ui32PDumpFlags, NULL)
+
+/*************************************************************************/ /*!
+@Function       RGXScheduleCommandAndGetKCCBSlot
+
+@Description    Sends a command to a particular DM and kicks the firmware but
+                first schedules any commands which have to happen before
+                handle
+
+@Input          psDevInfo           Device Info
+@Input          eDM                 To which DM the cmd is sent.
+@Input          psKCCBCmd           The cmd to send.
+@Input          ui32PDumpFlags      PDump flags
+@Output         pui32CmdKCCBSlot    When non-NULL:
+                                    - Pointer on return contains the kCCB slot
+                                      number in which the command was enqueued.
+                                    - Resets the value of the allotted slot to
+                                      RGXFWIF_KCCB_RTN_SLOT_RST
+
+@Return                        PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXScheduleCommandAndGetKCCBSlot(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               RGXFWIF_DM         eKCCBType,
+                                                               RGXFWIF_KCCB_CMD   *psKCCBCmd,
+                                                               IMG_UINT32         ui32PDumpFlags,
+                                                               IMG_UINT32         *pui32CmdKCCBSlot);
+#define RGXScheduleCommand(psDevInfo, eKCCBType, psKCCBCmd, ui32PDumpFlags) \
+  RGXScheduleCommandAndGetKCCBSlot(psDevInfo, eKCCBType, psKCCBCmd, ui32PDumpFlags, NULL)
+
+/*************************************************************************/ /*!
+@Function       RGXWaitForKCCBSlotUpdate
+
+@Description    Waits until the required kCCB slot value is updated by the FW
+                (signifies command completion). Additionally, dumps a relevant
+                PDump poll command.
+
+@Input          psDevInfo       Device Info
+@Input          ui32SlotNum     The kCCB slot number to wait for an update on
+@Input          ui32PDumpFlags
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXWaitForKCCBSlotUpdate(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                      IMG_UINT32 ui32SlotNum,
+                                                                         IMG_UINT32 ui32PDumpFlags);
+
+PVRSRV_ERROR RGXFirmwareUnittests(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVRGXFrameworkCopyCommand
+
+@Description    Copy framework command into FW addressable buffer
+
+@param          psDeviceNode
+@param          psFWFrameworkMemDesc
+@param          pbyGPUFRegisterList
+@param          ui32FrameworkRegisterSize
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR PVRSRVRGXFrameworkCopyCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                  DEVMEM_MEMDESC *psFWFrameworkMemDesc,
+                                                                                  IMG_PBYTE pbyGPUFRegisterList,
+                                                                                  IMG_UINT32 ui32FrameworkRegisterSize);
+
+
+/*************************************************************************/ /*!
+@Function       PVRSRVRGXFrameworkCreateKM
+
+@Description    Create FW addressable buffer for framework
+
+@param          psDeviceNode
+@param          ppsFWFrameworkMemDesc
+@param          ui32FrameworkRegisterSize
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR PVRSRVRGXFrameworkCreateKM(PVRSRV_DEVICE_NODE * psDeviceNode,
+                                                       DEVMEM_MEMDESC ** ppsFWFrameworkMemDesc,
+                                                       IMG_UINT32 ui32FrameworkRegisterSize);
+
+
+/*************************************************************************/ /*!
+@Function       RGXPollForGPCommandCompletion
+
+@Description    Polls for completion of a submitted GP command. Poll is done
+                on a value matching a masked read from the address.
+
+@Input          psDevNode       Pointer to device node struct
+@Input          pui32LinMemAddr CPU linear address to poll
+@Input          ui32Value       Required value
+@Input          ui32Mask        Mask
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXPollForGPCommandCompletion(PVRSRV_DEVICE_NODE *psDevNode,
+                                                                       volatile IMG_UINT32 __iomem *pui32LinMemAddr,
+                                                                       IMG_UINT32                   ui32Value,
+                                                                       IMG_UINT32                   ui32Mask);
+
+/*************************************************************************/ /*!
+@Function       RGXStateFlagCtrl
+
+@Description    Set and return FW internal state flags.
+
+@Input          psDevInfo       Device Info
+@Input          ui32Config      AppHint config flags
+@Output         pui32State      Current AppHint state flag configuration
+@Input          bSetNotClear    Set or clear the provided config flags
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXStateFlagCtrl(PVRSRV_RGXDEV_INFO *psDevInfo,
+                               IMG_UINT32 ui32Config,
+                               IMG_UINT32 *pui32State,
+                               IMG_BOOL bSetNotClear);
+
+/*!
+*******************************************************************************
+@Function       RGXFWRequestCommonContextCleanUp
+
+@Description    Schedules a FW common context cleanup. The firmware doesn't
+                block waiting for the resource to become idle but rather
+                notifies the host that the resources is busy.
+
+@Input          psDeviceNode    pointer to device node
+@Input          psServerCommonContext context to be cleaned up
+@Input          eDM             Data master, to which the cleanup command should
+                                be sent
+@Input          ui32PDumpFlags  PDump continuous flag
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWRequestCommonContextCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                         RGX_SERVER_COMMON_CONTEXT *psServerCommonContext,
+                                                                                         RGXFWIF_DM eDM,
+                                                                                         IMG_UINT32 ui32PDumpFlags);
+
+/*!
+*******************************************************************************
+@Function       RGXFWRequestHWRTDataCleanUp
+
+@Description    Schedules a FW HWRTData memory cleanup. The firmware doesn't
+                block waiting for the resource to become idle but rather
+                notifies the host that the resources is busy.
+
+@Input          psDeviceNode    pointer to device node
+@Input          psHWRTData      firmware address of the HWRTData for clean-up
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWRequestHWRTDataCleanUp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                                PRGXFWIF_HWRTDATA psHWRTData);
+
+/*!
+*******************************************************************************
+@Function       RGXFWRequestFreeListCleanUp
+
+@Description    Schedules a FW FreeList cleanup. The firmware doesn't block
+                waiting for the resource to become idle but rather notifies the
+                host that the resources is busy.
+
+@Input          psDeviceNode    pointer to device node
+@Input          psFWFreeList    firmware address of the FreeList for clean-up
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWRequestFreeListCleanUp(PVRSRV_RGXDEV_INFO *psDeviceNode,
+                                                                                PRGXFWIF_FREELIST psFWFreeList);
+
+/*!
+*******************************************************************************
+@Function       RGXFWRequestZSBufferCleanUp
+
+@Description    Schedules a FW ZS Buffer cleanup. The firmware doesn't block
+                waiting for the resource to become idle but rather notifies the
+                host that the resources is busy.
+
+@Input          psDevInfo       pointer to device node
+@Input          psFWZSBuffer    firmware address of the ZS Buffer for clean-up
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWRequestZSBufferCleanUp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                PRGXFWIF_ZSBUFFER psFWZSBuffer);
+
+PVRSRV_ERROR ContextSetPriority(RGX_SERVER_COMMON_CONTEXT *psContext,
+                                                               CONNECTION_DATA *psConnection,
+                                                               PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32Priority,
+                                                               RGXFWIF_DM eDM);
+
+/*!
+*******************************************************************************
+@Function       RGXFWSetHCSDeadline
+
+@Description    Requests the Firmware to set a new Hard Context Switch timeout
+                deadline. Context switches that surpass that deadline cause the
+                system to kill the currently running workloads.
+
+@Input          psDeviceNode    pointer to device node
+@Input          ui32HCSDeadlineMs  The deadline in milliseconds.
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWSetHCSDeadline(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32HCSDeadlineMs);
+
+/*!
+*******************************************************************************
+@Function       RGXFWChangeOSidPriority
+
+@Description    Requests the Firmware to change the priority of an operating
+                system. Higher priority number equals higher priority on the
+                scheduling system.
+
+@Input          psDevInfo       pointer to device info
+@Input          ui32OSid        The OSid whose priority is to be altered
+@Input          ui32Priority    The new priority number for the specified OSid
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWChangeOSidPriority(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                        IMG_UINT32 ui32OSid,
+                                                                        IMG_UINT32 ui32Priority);
+
+/*!
+*******************************************************************************
+@Function       RGXFWHealthCheckCmd
+
+@Description    Ping the firmware to check if it is responsive.
+
+@Input          psDevInfo       pointer to device info
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWHealthCheckCmd(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+@Function       RGXFWSetFwOsState
+
+@Description    Requests the Firmware to change the guest OS Online states.
+                This should be initiated by the VMM when a guest VM comes
+                online or goes offline. If offline, the FW offloads any current
+                resource from that OSID. The request is repeated until the FW
+                has had time to free all the resources or has waited for
+                workloads to finish.
+
+@Input          psDevInfo       pointer to device info
+@Input          ui32OSid        The Guest OSid whose state is being altered
+@Input          eOSOnlineState  The new state (Online or Offline)
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWSetFwOsState(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                               IMG_UINT32 ui32OSid,
+                                                               RGXFWIF_OS_STATE_CHANGE eOSOnlineState);
+
+#if defined(SUPPORT_AUTOVZ)
+/*!
+*******************************************************************************
+@Function       RGXUpdateAutoVzWdgToken
+
+@Description    If the driver-firmware connection is active, read the
+                firmware's watchdog token and copy its value back into the OS
+                token. This indicates to the firmware that this driver is alive
+                and responsive.
+
+@Input          psDevInfo       pointer to device info
+******************************************************************************/
+void RGXUpdateAutoVzWdgToken(PVRSRV_RGXDEV_INFO *psDevInfo);
+#endif
+
+/*!
+*******************************************************************************
+@Function       RGXFWConfigPHR
+
+@Description    Configure the Periodic Hardware Reset functionality
+
+@Input          psDevInfo       pointer to device info
+@Input          ui32PHRMode     desired PHR mode
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWConfigPHR(PVRSRV_RGXDEV_INFO *psDevInfo,
+                            IMG_UINT32 ui32PHRMode);
+/*!
+*******************************************************************************
+@Function       RGXFWConfigWdg
+
+@Description    Configure the Safety watchdog trigger period
+
+@Input          psDevInfo        pointer to device info
+@Input          ui32WdgPeriodUs  requested period in microseconds
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXFWConfigWdg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                            IMG_UINT32 ui32WdgPeriod);
+
+/*!
+*******************************************************************************
+@Function       RGXCheckFirmwareCCB
+
+@Description    Processes all commands that are found in the Firmware CCB.
+
+@Input          psDevInfo       pointer to device
+
+@Return         None
+******************************************************************************/
+void RGXCheckFirmwareCCB(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+@Function       RGXCheckForStalledClientContexts
+
+@Description    Checks all client contexts, for the device with device info
+                provided, to see if any are waiting for a fence to signal and
+                optionally force signalling of the fence for the context which
+                has been waiting the longest.
+                This function is called by RGXUpdateHealthStatus() and also
+                may be invoked from other trigger points.
+
+@Input          psDevInfo       pointer to device info
+@Input          bIgnorePrevious If IMG_TRUE, any stalled contexts will be
+                                indicated immediately, rather than only
+                                checking against any previous stalled contexts
+
+@Return         None
+******************************************************************************/
+void RGXCheckForStalledClientContexts(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_BOOL bIgnorePrevious);
+
+/*!
+*******************************************************************************
+@Function       RGXUpdateHealthStatus
+
+@Description    Tests a number of conditions which might indicate a fatal error
+                has occurred in the firmware. The result is stored in the
+                device node eHealthStatus.
+
+@Input         psDevNode        Pointer to device node structure.
+@Input         bCheckAfterTimePassed  When TRUE, the function will also test
+                                for firmware queues and polls not changing
+                                since the previous test.
+
+                                Note: if not enough time has passed since the
+                                last call, false positives may occur.
+
+@Return        PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXUpdateHealthStatus(PVRSRV_DEVICE_NODE* psDevNode,
+                                   IMG_BOOL bCheckAfterTimePassed);
+
+#if defined(SUPPORT_AUTOVZ)
+/*!
+*******************************************************************************
+@Function       RGXUpdateAutoVzWatchdog
+
+@Description    Updates AutoVz watchdog that maintains the fw-driver connection
+
+@Input         psDevNode        Pointer to device node structure.
+******************************************************************************/
+void RGXUpdateAutoVzWatchdog(PVRSRV_DEVICE_NODE* psDevNode);
+#endif /* SUPPORT_AUTOVZ */
+
+PVRSRV_ERROR CheckStalledClientCommonContext(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext, RGX_KICK_TYPE_DM eKickTypeDM);
+
+void DumpFWCommonContextInfo(RGX_SERVER_COMMON_CONTEXT *psCurrentServerCommonContext,
+                             DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                             void *pvDumpDebugFile,
+                             IMG_UINT32 ui32VerbLevel);
+
+/*!
+*******************************************************************************
+@Function       AttachKickResourcesCleanupCtls
+
+@Description    Attaches the cleanup structures to a kick command so that
+                submission reference counting can be performed when the
+                firmware processes the command
+
+@Output         apsCleanupCtl   Array of CleanupCtl structure pointers to populate.
+@Output         pui32NumCleanupCtl  Number of CleanupCtl structure pointers written out.
+@Input          eDM             Which data master is the subject of the command.
+@Input          bKick           TRUE if the client originally wanted to kick this DM.
+@Input          psRTDataCleanup Optional RTData cleanup associated with the command.
+@Input          psZBuffer       Optional ZSBuffer associated with the command.
+
+@Return        PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR AttachKickResourcesCleanupCtls(PRGXFWIF_CLEANUP_CTL *apsCleanupCtl,
+                                                                       IMG_UINT32 *pui32NumCleanupCtl,
+                                                                       RGXFWIF_DM eDM,
+                                                                       IMG_BOOL bKick,
+                                                                       RGX_KM_HW_RT_DATASET           *psKMHWRTDataSet,
+                                                                       RGX_ZSBUFFER_DATA              *psZSBuffer,
+                                                                       RGX_ZSBUFFER_DATA              *psMSAAScratchBuffer);
+
+/*!
+*******************************************************************************
+@Function       RGXResetHWRLogs
+
+@Description    Resets the HWR Logs buffer
+                (the hardware recovery count is not reset)
+
+@Input          psDevNode       Pointer to the device
+
+@Return         PVRSRV_ERROR    PVRSRV_OK on success.
+                                Otherwise, a PVRSRV error code
+******************************************************************************/
+PVRSRV_ERROR RGXResetHWRLogs(PVRSRV_DEVICE_NODE *psDevNode);
+
+/*!
+*******************************************************************************
+@Function       RGXGetPhyAddr
+
+@Description    Get the physical address of a PMR at an offset within it
+
+@Input          psPMR           PMR of the allocation
+@Input          ui32LogicalOffset  Logical offset
+
+@Output         psPhyAddr       Physical address of the allocation
+
+@Return         PVRSRV_ERROR    PVRSRV_OK on success.
+                                Otherwise, a PVRSRV error code
+******************************************************************************/
+PVRSRV_ERROR RGXGetPhyAddr(PMR *psPMR,
+                                                  IMG_DEV_PHYADDR *psPhyAddr,
+                                                  IMG_UINT32 ui32LogicalOffset,
+                                                  IMG_UINT32 ui32Log2PageSize,
+                                                  IMG_UINT32 ui32NumOfPages,
+                                                  IMG_BOOL *bValid);
+
+#if defined(PDUMP)
+/*!
+*******************************************************************************
+@Function       RGXPdumpDrainKCCB
+
+@Description    Wait for the firmware to execute all the commands in the kCCB
+
+@Input          psDevInfo       Pointer to the device
+@Input          ui32WriteOffset Woff we have to POL for the Roff to be equal to
+
+@Return         PVRSRV_ERROR    PVRSRV_OK on success.
+                                Otherwise, a PVRSRV error code
+******************************************************************************/
+PVRSRV_ERROR RGXPdumpDrainKCCB(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                          IMG_UINT32 ui32WriteOffset);
+#endif /* PDUMP */
+
+/*!
+*******************************************************************************
+@Function       RGXFwRawHeapAllocMap
+
+@Description    Register and maps to device, a raw firmware physheap
+
+@Return         PVRSRV_ERROR    PVRSRV_OK on success.
+                                Otherwise, a PVRSRV error code
+******************************************************************************/
+PVRSRV_ERROR RGXFwRawHeapAllocMap(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                 IMG_UINT32 ui32OSID,
+                                                                 IMG_DEV_PHYADDR sDevPAddr,
+                                                                 IMG_UINT64 ui64DevPSize);
+
+/*!
+*******************************************************************************
+@Function       RGXFwRawHeapUnmapFree
+
+@Description    Unregister and unmap from device, a raw firmware physheap
+
+******************************************************************************/
+void RGXFwRawHeapUnmapFree(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                  IMG_UINT32 ui32OSID);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvHalt
+
+@Description    Halt the RISC-V FW core (required for certain operations
+                done through Debug Module)
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvHalt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvIsHalted
+
+@Description    Check if the RISC-V FW is halted
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         IMG_BOOL
+******************************************************************************/
+IMG_BOOL RGXRiscvIsHalted(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvResume
+
+@Description    Resume the RISC-V FW core
+
+@Input          psDevInfo       Pointer to device info
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvResume(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvReadReg
+
+@Description    Read a value from the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvReadReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32RegAddr,
+                             IMG_UINT32 *pui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollReg
+
+@Description    Poll for a value from the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvPollReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32RegAddr,
+                             IMG_UINT32 ui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvWriteReg
+
+@Description    Write a value to the given RISC-V register (GPR or CSR)
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32RegAddr     RISC-V register address
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvWriteReg(PVRSRV_RGXDEV_INFO *psDevInfo,
+                              IMG_UINT32 ui32RegAddr,
+                              IMG_UINT32 ui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvPollMem
+
+@Description    Poll for a value at the given address in RISC-V memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Expected value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvPollMem(PVRSRV_RGXDEV_INFO *psDevInfo,
+                             IMG_UINT32 ui32Addr,
+                             IMG_UINT32 ui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXRiscvDmiOp
+
+@Description    Acquire the powerlock and perform an operation on the RISC-V
+                Debug Module Interface, but only if the GPU is powered on.
+
+@Input          psDevInfo       Pointer to device info
+@InOut          pui64DMI        Encoding of a request for the RISC-V Debug
+                                Module with same format as the 'dmi' register
+                                from the RISC-V debug specification (v0.13+).
+                                On return, this is updated with the result of
+                                the request, encoded the same way.
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXRiscvDmiOp(PVRSRV_RGXDEV_INFO *psDevInfo,
+                           IMG_UINT64 *pui64DMI);
+
+/*!
+*******************************************************************************
+@Function       RGXReadFWModuleAddr
+
+@Description    Read a value at the given address in META or RISCV memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in META or RISCV memory space
+
+@Output         pui32Value      Read value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXReadFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                 IMG_UINT32 ui32Addr,
+                                 IMG_UINT32 *pui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXWriteFWModuleAddr
+
+@Description    Write a value to the given address in META or RISC memory space
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32Addr        Address in RISC-V memory space
+@Input          ui32Value       Write value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXWriteFWModuleAddr(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                  IMG_UINT32 ui32MemAddr,
+                                  IMG_UINT32 ui32Value);
+
+/*!
+*******************************************************************************
+@Function       RGXGetFwMapping
+
+@Description    Retrieve any of the CPU Physical Address, Device Physical
+                Address or the raw value of the page table entry associated
+                with the firmware virtual address given.
+
+@Input          psDevInfo       Pointer to device info
+@Input          ui32FwVA        The Fw VA that needs decoding
+@Output         psCpuPA         Pointer to the resulting CPU PA
+@Output         psDevPA         Pointer to the resulting Dev PA
+@Output         pui64RawPTE     Pointer to  the raw Page Table Entry value
+
+@Return         PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR RGXGetFwMapping(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                    IMG_UINT32 ui32FwVA,
+                                    IMG_CPU_PHYADDR *psCpuPA,
+                                    IMG_DEV_PHYADDR *psDevPA,
+                                    IMG_UINT64 *pui64RawPTE);
+
+#if defined(SUPPORT_AUTOVZ_HW_REGS) && !defined(SUPPORT_AUTOVZ)
+#error "VZ build configuration error: use of OS scratch registers supported only in AutoVz drivers."
+#endif
+
+#if defined(SUPPORT_AUTOVZ_HW_REGS)
+/* AutoVz with hw support */
+#define KM_GET_FW_CONNECTION(psDevInfo)                                OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH3)
+#define KM_GET_OS_CONNECTION(psDevInfo)                                OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH2)
+#define KM_SET_OS_CONNECTION(val, psDevInfo)           OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH2, RGXFW_CONNECTION_OS_##val)
+
+#define KM_GET_FW_ALIVE_TOKEN(psDevInfo)                       OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH1)
+#define KM_GET_OS_ALIVE_TOKEN(psDevInfo)                       OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH0)
+#define KM_SET_OS_ALIVE_TOKEN(val, psDevInfo)          OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_OS0_SCRATCH0, val)
+#else
+
+#if defined(SUPPORT_AUTOVZ)
+#define KM_GET_FW_ALIVE_TOKEN(psDevInfo)                       (psDevInfo->psRGXFWIfConnectionCtl->ui32AliveFwToken)
+#define KM_GET_OS_ALIVE_TOKEN(psDevInfo)                       (psDevInfo->psRGXFWIfConnectionCtl->ui32AliveOsToken)
+#define KM_SET_OS_ALIVE_TOKEN(val, psDevInfo)          OSWriteDeviceMem32WithWMB(&psDevInfo->psRGXFWIfConnectionCtl->ui32AliveOsToken, val)
+#endif /* defined(SUPPORT_AUTOVZ) */
+
+#if !defined(NO_HARDWARE) && (defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) || (defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED == 1)))
+/* native, static-vz and AutoVz using shared memory */
+#define KM_GET_FW_CONNECTION(psDevInfo)                        (psDevInfo->psRGXFWIfConnectionCtl->eConnectionFwState)
+#define KM_GET_OS_CONNECTION(psDevInfo)                        (psDevInfo->psRGXFWIfConnectionCtl->eConnectionOsState)
+#define KM_SET_OS_CONNECTION(val, psDevInfo)   OSWriteDeviceMem32WithWMB(&psDevInfo->psRGXFWIfConnectionCtl->eConnectionOsState, RGXFW_CONNECTION_OS_##val)
+#else
+/* dynamic-vz & nohw */
+#define KM_GET_FW_CONNECTION(psDevInfo)                        (RGXFW_CONNECTION_FW_ACTIVE)
+#define KM_GET_OS_CONNECTION(psDevInfo)                        (RGXFW_CONNECTION_OS_ACTIVE)
+#define KM_SET_OS_CONNECTION(val, psDevInfo)
+#endif /* defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) || (RGX_NUM_OS_SUPPORTED == 1) */
+#endif /* defined(SUPPORT_AUTOVZ_HW_REGS) */
+
+#if defined(SUPPORT_AUTOVZ)
+#define RGX_FIRST_RAW_HEAP_OSID                RGXFW_HOST_OS
+#else
+#define RGX_FIRST_RAW_HEAP_OSID                RGXFW_GUEST_OSID_START
+#endif
+
+#define KM_OS_CONNECTION_IS(val, psDevInfo)            (KM_GET_OS_CONNECTION(psDevInfo) == RGXFW_CONNECTION_OS_##val)
+#define KM_FW_CONNECTION_IS(val, psDevInfo)            (KM_GET_FW_CONNECTION(psDevInfo) == RGXFW_CONNECTION_FW_##val)
+
+#endif /* RGXFWUTILS_H */
+/******************************************************************************
+ End of file (rgxfwutils.h)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxhwperf.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxhwperf.c
new file mode 100644 (file)
index 0000000..2c0a53c
--- /dev/null
@@ -0,0 +1,415 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX HW Performance implementation
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX HW Performance implementation
+@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.
+ */ /**************************************************************************/
+
+//#define PVR_DPF_FUNCTION_TRACE_ON 1
+#undef PVR_DPF_FUNCTION_TRACE_ON
+
+#include "img_defs.h"
+#include "pvr_debug.h"
+#include "rgxdevice.h"
+#include "pvrsrv_error.h"
+#include "pvr_notifier.h"
+#include "osfunc.h"
+#include "allocmem.h"
+
+#include "pvrsrv.h"
+#include "pvrsrv_tlstreams.h"
+#include "pvrsrv_tlcommon.h"
+#include "tlclient.h"
+#include "tlstream.h"
+
+#include "rgxhwperf.h"
+#include "rgxapi_km.h"
+#include "rgxfwutils.h"
+#include "rgxtimecorr.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "pdump_km.h"
+#include "pvrsrv_apphint.h"
+#include "process_stats.h"
+#include "rgx_hwperf_table.h"
+#include "rgxinit.h"
+
+#include "info_page_defs.h"
+
+/* Maximum enum value to prevent access to RGX_HWPERF_STREAM_ID2_CLIENT stream */
+#define RGX_HWPERF_MAX_STREAM_ID (RGX_HWPERF_STREAM_ID2_CLIENT)
+
+
+IMG_INTERNAL /*static inline*/ IMG_UINT32 RGXGetHWPerfBlockConfig(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL **);
+
+static IMG_BOOL RGXServerFeatureFlagsToHWPerfFlagsAddBlock(
+       RGX_HWPERF_BVNC_BLOCK   * const psBlocks,
+       IMG_UINT16                              * const pui16Count,
+       const IMG_UINT16                ui16BlockID, /* see RGX_HWPERF_CNTBLK_ID */
+       const IMG_UINT16                ui16NumCounters,
+       const IMG_UINT16                ui16NumBlocks)
+{
+       const IMG_UINT16 ui16Count = *pui16Count;
+
+       if (ui16Count < RGX_HWPERF_MAX_BVNC_BLOCK_LEN)
+       {
+               RGX_HWPERF_BVNC_BLOCK * const psBlock = &psBlocks[ui16Count];
+
+               /* If the GROUP is non-zero, convert from e.g. RGX_CNTBLK_ID_USC0 to
+                * RGX_CNTBLK_ID_USC_ALL. The table stores the former (plus the
+                * number of blocks and counters) but PVRScopeServices expects the
+                * latter (plus the number of blocks and counters). The conversion
+                * could always be moved to PVRScopeServices, but it's less code this
+                * way.
+                * For SLC0 we generate a single SLCBANK_ALL which has NUM_MEMBUS
+                * instances.
+                * This replaces the SLC0 .. SLC3 entries.
+                */
+               if ((ui16BlockID == RGX_CNTBLK_ID_SLCBANK0) || (ui16BlockID & RGX_CNTBLK_ID_GROUP_MASK))
+               {
+                       psBlock->ui16BlockID    = ui16BlockID | RGX_CNTBLK_ID_UNIT_ALL_MASK;
+               }
+               else
+               {
+                       psBlock->ui16BlockID    = ui16BlockID;
+               }
+               psBlock->ui16NumCounters        = ui16NumCounters;
+               psBlock->ui16NumBlocks          = ui16NumBlocks;
+
+               *pui16Count = ui16Count + 1;
+               return IMG_TRUE;
+       }
+       return IMG_FALSE;
+}
+
+PVRSRV_ERROR RGXServerFeatureFlagsToHWPerfFlags(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_HWPERF_BVNC *psBVNC)
+{
+       IMG_PCHAR pszBVNC;
+       PVR_LOG_RETURN_IF_FALSE((NULL != psDevInfo), "psDevInfo invalid", PVRSRV_ERROR_INVALID_PARAMS);
+
+       if ((pszBVNC = RGXDevBVNCString(psDevInfo)))
+       {
+               size_t uiStringLength = OSStringNLength(pszBVNC, RGX_HWPERF_MAX_BVNC_LEN - 1);
+               OSStringLCopy(psBVNC->aszBvncString, pszBVNC, uiStringLength + 1);
+               memset(&psBVNC->aszBvncString[uiStringLength], 0, RGX_HWPERF_MAX_BVNC_LEN - uiStringLength);
+       }
+       else
+       {
+               *psBVNC->aszBvncString = 0;
+       }
+
+       psBVNC->ui32BvncKmFeatureFlags = 0x0;
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, PERFBUS))
+       {
+               psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_PERFBUS_FLAG;
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_MULTICORE_SUPPORT))
+       {
+               psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_MULTICORE_FLAG;
+       }
+
+       /* Determine if we've got the new RAY_TRACING feature supported. This is
+        * only determined by comparing the RAY_TRACING_ARCHITECTURE value */
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH))
+       {
+               psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_RAYTRACING_FLAG;
+       }
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, CATURIX_TOP_INFRASTRUCTURE))
+       {
+               psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_CXT_TOP_INFRASTRUCTURE_FLAG;
+       }
+
+#ifdef SUPPORT_WORKLOAD_ESTIMATION
+       /* Not a part of BVNC feature line and so doesn't need the feature supported check */
+       psBVNC->ui32BvncKmFeatureFlags |= RGX_HWPERF_FEATURE_WORKLOAD_ESTIMATION;
+#endif
+
+       /* Define the HW counter block counts. */
+       {
+               RGX_HWPERF_BVNC_BLOCK                                   * const psBlocks        = psBVNC->aBvncBlocks;
+               IMG_UINT16                                                              * const pui16Count      = &psBVNC->ui16BvncBlocks;
+               const RGXFW_HWPERF_CNTBLK_TYPE_MODEL    *asCntBlkTypeModel;
+               const IMG_UINT32                                                ui32CntBlkModelLen      = RGXGetHWPerfBlockConfig(&asCntBlkTypeModel);
+               IMG_UINT32                                                              ui32BlkCfgIdx;
+               size_t                                                                  uiCount;
+               IMG_BOOL                                                                bOk                                     = IMG_TRUE;
+
+               // Initialise to zero blocks
+               *pui16Count = 0;
+
+               // Add all the blocks
+               for (ui32BlkCfgIdx = 0; ui32BlkCfgIdx < ui32CntBlkModelLen; ui32BlkCfgIdx++)
+               {
+                       const RGXFW_HWPERF_CNTBLK_TYPE_MODEL    * const psCntBlkInfo = &asCntBlkTypeModel[ui32BlkCfgIdx];
+                       RGX_HWPERF_CNTBLK_RT_INFO                               sCntBlkRtInfo;
+                       /* psCntBlkInfo->uiNumUnits gives compile-time info. For BVNC agnosticism, we use this: */
+                       if (psCntBlkInfo->pfnIsBlkPresent(psCntBlkInfo, psDevInfo, &sCntBlkRtInfo))
+                       {
+                               IMG_UINT32      uiNumUnits;
+
+                               switch (psCntBlkInfo->uiCntBlkIdBase)
+                               {
+                                       case RGX_CNTBLK_ID_SLCBANK0:
+                                               /* Generate the SLCBANK_ALL block for SLC0..SLC3
+                                                * we have to special-case this as the iteration will
+                                                * generate entries starting at SLC0 and we need to
+                                                * defer until we are processing the last 'present'
+                                                * entry.
+                                                * The SLC_BLKID_ALL is keyed from SLC0. Need to access
+                                                * the NUM_MEMBUS feature to see how many are physically
+                                                * present.
+                                                * For CXT_TOP_INFRASTRUCTURE systems we present a
+                                                * singleton SLCBANK - this provides accumulated counts
+                                                * for all registers within the physical SLCBANK instances.
+                                                */
+                                               if (psBVNC->ui32BvncKmFeatureFlags &
+                                                   RGX_HWPERF_FEATURE_CXT_TOP_INFRASTRUCTURE_FLAG)
+                                               {
+                                                       uiNumUnits = 1U;
+                                               }
+                                               else
+                                               {
+                                                       uiNumUnits = RGX_GET_FEATURE_VALUE(psDevInfo,
+                                                                                          NUM_MEMBUS);
+                                               }
+                                               break;
+                                       case RGX_CNTBLK_ID_SLCBANK1:
+                                       case RGX_CNTBLK_ID_SLCBANK2:
+                                       case RGX_CNTBLK_ID_SLCBANK3:
+                                               /* These are contained within SLCBANK_ALL block */
+                                               continue;
+                                       default:
+                                               uiNumUnits = sCntBlkRtInfo.uiNumUnits;
+                                               break;
+                               }
+                               bOk &= RGXServerFeatureFlagsToHWPerfFlagsAddBlock(psBlocks, pui16Count, psCntBlkInfo->uiCntBlkIdBase, RGX_CNTBLK_COUNTERS_MAX, uiNumUnits);
+                       }
+               }
+
+               /* If this fails, consider why the static_assert didn't fail, and consider increasing RGX_HWPERF_MAX_BVNC_BLOCK_LEN */
+               PVR_ASSERT(bOk);
+
+               // Zero the remaining entries
+               uiCount = *pui16Count;
+               OSDeviceMemSet(&psBlocks[uiCount], 0, (RGX_HWPERF_MAX_BVNC_BLOCK_LEN - uiCount) * sizeof(*psBlocks));
+       }
+
+       return PVRSRV_OK;
+}
+
+/*
+       PVRSRVRGXConfigureHWPerfBlocksKM
+ */
+PVRSRV_ERROR PVRSRVRGXConfigureHWPerfBlocksKM(
+               CONNECTION_DATA          * psConnection,
+               PVRSRV_DEVICE_NODE       * psDeviceNode,
+               IMG_UINT32                 ui32CtrlWord,
+               IMG_UINT32                 ui32ArrayLen,
+               RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs)
+{
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       RGXFWIF_KCCB_CMD        sKccbCmd;
+       DEVMEM_MEMDESC*         psFwBlkConfigsMemDesc;
+       RGX_HWPERF_CONFIG_CNTBLK* psFwArray;
+       IMG_UINT32                      ui32kCCBCommandSlot;
+       PVRSRV_RGXDEV_INFO      *psDevice;
+
+       PVR_LOG_RETURN_IF_FALSE(psDeviceNode != NULL, "psDeviceNode is NULL",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+
+       psDevice = psDeviceNode->pvDevice;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       PVR_LOG_RETURN_IF_FALSE(ui32ArrayLen > 0, "ui32ArrayLen is 0",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+       PVR_LOG_RETURN_IF_FALSE(psBlockConfigs != NULL, "psBlockConfigs is NULL",
+                               PVRSRV_ERROR_INVALID_PARAMS);
+
+       PVR_DPF_ENTERED;
+
+       /* Fill in the command structure with the parameters needed
+        */
+       sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_BLKS;
+       sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.ui32CtrlWord = ui32CtrlWord;
+       sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.ui32NumBlocks = ui32ArrayLen;
+
+       /* used for passing counters config to the Firmware, write-only for the CPU */
+       eError = DevmemFwAllocate(psDevice,
+                                 sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+                                 PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                 PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                 PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                 PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                 PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                 PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                 PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                 PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                 "FwHWPerfCountersConfigBlock",
+                                 &psFwBlkConfigsMemDesc);
+       PVR_LOG_RETURN_IF_ERROR(eError, "DevmemFwAllocate");
+
+       eError = RGXSetFirmwareAddress(&sKccbCmd.uCmdData.sHWPerfCfgEnableBlks.sBlockConfigs,
+                             psFwBlkConfigsMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", fail1);
+
+       eError = DevmemAcquireCpuVirtAddr(psFwBlkConfigsMemDesc, (void **)&psFwArray);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", fail2);
+
+       OSCachedMemCopyWMB(psFwArray, psBlockConfigs, sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen);
+       DevmemPDumpLoadMem(psFwBlkConfigsMemDesc,
+                          0,
+                          sizeof(RGX_HWPERF_CONFIG_CNTBLK)*ui32ArrayLen,
+                          PDUMP_FLAGS_CONTINUOUS);
+
+       /* Ask the FW to carry out the HWPerf configuration command
+        */
+       eError = RGXScheduleCommandAndGetKCCBSlot(psDevice,
+                                                                                         RGXFWIF_DM_GP,
+                                                                                         &sKccbCmd,
+                                                                                         PDUMP_FLAGS_CONTINUOUS,
+                                                                                         &ui32kCCBCommandSlot);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXScheduleCommandAndGetKCCBSlot", fail2);
+
+       /* Wait for FW to complete */
+       eError = RGXWaitForKCCBSlotUpdate(psDevice, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXWaitForKCCBSlotUpdate", fail3);
+
+       /* Release temporary memory used for block configuration
+        */
+       RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+       DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+       DevmemFwUnmapAndFree(psDevice, psFwBlkConfigsMemDesc);
+
+       PVR_DPF((PVR_DBG_WARNING, "HWPerf %d counter blocks configured and ENABLED", ui32ArrayLen));
+
+       PVR_DPF_RETURN_OK;
+
+fail3:
+       DevmemReleaseCpuVirtAddr(psFwBlkConfigsMemDesc);
+fail2:
+       RGXUnsetFirmwareAddress(psFwBlkConfigsMemDesc);
+fail1:
+       DevmemFwUnmapAndFree(psDevice, psFwBlkConfigsMemDesc);
+
+       PVR_DPF_RETURN_RC(eError);
+}
+
+/******************************************************************************
+ * Currently only implemented on Linux. Feature can be enabled to provide
+ * an interface to 3rd-party kernel modules that wish to access the
+ * HWPerf data. The API is documented in the rgxapi_km.h header and
+ * the rgx_hwperf* headers.
+ *****************************************************************************/
+
+/* Internal HWPerf kernel connection/device data object to track the state
+ * of a client session.
+ */
+typedef struct
+{
+       PVRSRV_DEVICE_NODE* psRgxDevNode;
+       PVRSRV_RGXDEV_INFO* psRgxDevInfo;
+
+       /* TL Open/close state */
+       IMG_HANDLE          hSD[RGX_HWPERF_MAX_STREAM_ID];
+
+       /* TL Acquire/release state */
+       IMG_PBYTE                       pHwpBuf[RGX_HWPERF_MAX_STREAM_ID];                      /*!< buffer returned to user in acquire call */
+       IMG_PBYTE                       pHwpBufEnd[RGX_HWPERF_MAX_STREAM_ID];           /*!< pointer to end of HwpBuf */
+       IMG_PBYTE                       pTlBuf[RGX_HWPERF_MAX_STREAM_ID];                       /*!< buffer obtained via TlAcquireData */
+       IMG_PBYTE                       pTlBufPos[RGX_HWPERF_MAX_STREAM_ID];            /*!< initial position in TlBuf to acquire packets */
+       IMG_PBYTE                       pTlBufRead[RGX_HWPERF_MAX_STREAM_ID];           /*!< pointer to the last packet read */
+       IMG_UINT32                      ui32AcqDataLen[RGX_HWPERF_MAX_STREAM_ID];       /*!< length of acquired TlBuf */
+       IMG_BOOL                        bRelease[RGX_HWPERF_MAX_STREAM_ID];             /*!< used to determine whether or not to release currently held TlBuf */
+
+
+} RGX_KM_HWPERF_DEVDATA;
+
+PVRSRV_ERROR RGXHWPerfConfigureCounters(
+               RGX_HWPERF_CONNECTION *psHWPerfConnection,
+               IMG_UINT32                                      ui32CtrlWord,
+               IMG_UINT32                                      ui32NumBlocks,
+               RGX_HWPERF_CONFIG_CNTBLK*       asBlockConfigs)
+{
+       PVRSRV_ERROR           eError;
+       RGX_KM_HWPERF_DEVDATA* psDevData;
+       RGX_HWPERF_DEVICE *psHWPerfDev;
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_IMPLEMENTED);
+
+       /* Validate input argument values supplied by the caller */
+       if (!psHWPerfConnection || ui32NumBlocks==0 || !asBlockConfigs)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32NumBlocks > RGXFWIF_HWPERF_CTRL_BLKS_MAX)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psHWPerfDev = psHWPerfConnection->psHWPerfDevList;
+
+       while (psHWPerfDev)
+       {
+               psDevData = (RGX_KM_HWPERF_DEVDATA *) psHWPerfDev->hDevData;
+
+               /* Call the internal server API */
+               eError = PVRSRVRGXConfigureHWPerfBlocksKM(NULL,
+                                                         psDevData->psRgxDevNode,
+                                                         ui32CtrlWord,
+                                                         ui32NumBlocks,
+                                                         asBlockConfigs);
+
+               PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVRGXConfigureHWPerfBlocksKM");
+
+               psHWPerfDev = psHWPerfDev->psNext;
+       }
+
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (rgxhwperf.c)
+ ******************************************************************************/
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          System Description Header
+@Title          RGX HW Performance header file
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header provides system-specific declarations and macros
+@Description    Header for the RGX HWPerf functions
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,18 +41,20 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 
-#include "pvrsrv_device.h"
-#include "rgxdevice.h"
+#ifndef RGXHWPERF_H_
+#define RGXHWPERF_H_
 
-#if !defined(SYSCCONFIG_H)
-#define SYSCCONFIG_H
+#include "rgxhwperf_common.h"
 
-
-#define RGX_NOHW_CORE_CLOCK_SPEED 100000000
-#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (0)
-
-/*****************************************************************************
- * system specific data structures
+/******************************************************************************
+ * RGX HW Performance Profiling API(s) - Volcanic specific
  *****************************************************************************/
 
-#endif /* SYSCCONFIG_H */
+PVRSRV_ERROR PVRSRVRGXConfigureHWPerfBlocksKM(
+       CONNECTION_DATA       * psConnection,
+       PVRSRV_DEVICE_NODE    * psDeviceNode,
+       IMG_UINT32            ui32CtrlWord,
+       IMG_UINT32            ui32ArrayLen,
+       RGX_HWPERF_CONFIG_CNTBLK * psBlockConfigs);
+
+#endif /* RGXHWPERF_H_ */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.c
new file mode 100644 (file)
index 0000000..4e8980b
--- /dev/null
@@ -0,0 +1,4597 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@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(__linux__)
+#include <linux/stddef.h>
+#else
+#include <stddef.h>
+#endif
+
+#include "log2.h"
+#include "img_defs.h"
+#include "pvr_notifier.h"
+#include "pvrsrv.h"
+#include "pvrsrv_bridge_init.h"
+#include "rgx_bridge_init.h"
+#include "syscommon.h"
+#include "rgx_heaps.h"
+#include "rgxheapconfig.h"
+#include "rgxdefs_km.h"
+#include "rgxpower.h"
+#include "tlstream.h"
+#include "pvrsrv_tlstreams.h"
+
+#include "rgxinit.h"
+#include "rgxbvnc.h"
+#include "rgxmulticore.h"
+
+#include "pdump_km.h"
+#include "handle.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "rgxmem.h"
+#include "sync_internal.h"
+#include "pvrsrv_apphint.h"
+#include "oskm_apphint.h"
+#include "rgxfwdbg.h"
+#include "info_page.h"
+
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgx_fwif_km.h"
+
+#include "rgxmmuinit.h"
+#include "devicemem_utils.h"
+#include "devicemem_server.h"
+#include "physmem_osmem.h"
+#include "physmem_lma.h"
+
+#include "rgxdebug.h"
+#include "rgxhwperf.h"
+#include "htbserver.h"
+
+#include "rgx_options.h"
+#include "pvrversion.h"
+
+#include "rgx_compat_bvnc.h"
+
+#include "rgx_heaps.h"
+
+#include "rgxta3d.h"
+#include "rgxtimecorr.h"
+#include "rgxshader.h"
+
+#if defined(PDUMP)
+#include "rgxstartstop.h"
+#endif
+
+#include "rgx_fwif_alignchecks.h"
+#include "vmm_pvz_client.h"
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+#include "rgxsoctimer.h"
+#endif
+
+#if defined(PDUMP) && defined(SUPPORT_SECURITY_VALIDATION)
+#include "pdump_physmem.h"
+#endif
+
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
+static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_CHAR **ppszVersionString);
+static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_PUINT32 pui32RGXClockSpeed);
+static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_UINT64 ui64ResetValue, IMG_UINT64 ui64SPUResetValue);
+static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode);
+static void DevPart2DeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#if (RGX_NUM_OS_SUPPORTED > 1)
+static PVRSRV_ERROR RGXInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap, IMG_UINT32 ui32OSid);
+static void RGXDeInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap);
+#endif
+
+/* Services internal heap identification used in this file only */
+#define RGX_FIRMWARE_MAIN_HEAP_IDENT   "FwMain"   /*!< RGX Main Firmware Heap identifier */
+#define RGX_FIRMWARE_CONFIG_HEAP_IDENT "FwConfig" /*!< RGX Config firmware Heap identifier */
+
+#define RGX_MMU_PAGE_SIZE_4KB   (   4 * 1024)
+#define RGX_MMU_PAGE_SIZE_16KB  (  16 * 1024)
+#define RGX_MMU_PAGE_SIZE_64KB  (  64 * 1024)
+#define RGX_MMU_PAGE_SIZE_256KB ( 256 * 1024)
+#define RGX_MMU_PAGE_SIZE_1MB   (1024 * 1024)
+#define RGX_MMU_PAGE_SIZE_2MB   (2048 * 1024)
+#define RGX_MMU_PAGE_SIZE_MIN RGX_MMU_PAGE_SIZE_4KB
+#define RGX_MMU_PAGE_SIZE_MAX RGX_MMU_PAGE_SIZE_2MB
+
+#define VAR(x) #x
+
+#define MAX_BVNC_LEN (12)
+#define RGXBVNC_BUFFER_SIZE (((PVRSRV_MAX_DEVICES)*(MAX_BVNC_LEN))+1)
+
+static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo);
+
+#if !defined(NO_HARDWARE)
+/*************************************************************************/ /*!
+@Function       SampleIRQCount
+@Description    Utility function taking snapshots of RGX FW interrupt count.
+@Input          paui32Input  A pointer to RGX FW IRQ count array.
+                             Size of the array should be equal to RGX FW thread
+                             count.
+@Input          paui32Output A pointer to array containing sampled RGX FW
+                             IRQ counts
+@Return         IMG_BOOL     Returns IMG_TRUE, if RGX FW IRQ is not equal to
+                             sampled RGX FW IRQ count for any RGX FW thread.
+*/ /**************************************************************************/
+static INLINE IMG_BOOL SampleIRQCount(const volatile IMG_UINT32 *paui32Input,
+                                                                         volatile IMG_UINT32 *paui32Output)
+{
+       IMG_UINT32 ui32TID;
+       IMG_BOOL bReturnVal = IMG_FALSE;
+
+       for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+       {
+               if (paui32Output[ui32TID] != paui32Input[ui32TID])
+               {
+                       /**
+                        * we are handling any unhandled interrupts here so align the host
+                        * count with the FW count
+                        */
+
+                       /* Sample the current count from the FW _after_ we've cleared the interrupt. */
+                       paui32Output[ui32TID] = paui32Input[ui32TID];
+                       bReturnVal = IMG_TRUE;
+               }
+       }
+
+       return bReturnVal;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXHostSafetyEvents
+@Description    Returns the event status masked to keep only the safety
+                events handled by the Host
+@Input          psDevInfo    Device Info structure
+@Return         IMG_UINT32   Status of Host-handled safety events
+ */ /**************************************************************************/
+static INLINE IMG_UINT32 RGXHostSafetyEvents(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       if (PVRSRV_VZ_MODE_IS(GUEST) || (psDevInfo->ui32HostSafetyEventMask == 0))
+       {
+               return 0;
+       }
+       else
+       {
+               IMG_UINT32 ui32EventStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_STATUS);
+
+               return (ui32EventStatus & psDevInfo->ui32HostSafetyEventMask);
+       }
+}
+
+/*************************************************************************/ /*!
+@Function       RGXSafetyEventHandler
+@Description    Handles the Safety Events that the Host is responsible for
+@Input          psDevInfo    Device Info structure
+ */ /**************************************************************************/
+static void RGXSafetyEventHandler(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_UINT32 ui32HostSafetyStatus = RGXHostSafetyEvents(psDevInfo);
+       RGX_CONTEXT_RESET_REASON eResetReason = RGX_CONTEXT_RESET_REASON_NONE;
+
+       if (ui32HostSafetyStatus != 0)
+       {
+               /* clear the safety bus events handled by the Host */
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_EVENT_CLEAR, ui32HostSafetyStatus);
+
+               if (BIT_ISSET(ui32HostSafetyStatus, RGX_CR_EVENT_STATUS_FAULT_FW_SHIFT))
+               {
+                       IMG_UINT32 ui32FaultFlag;
+                       IMG_UINT32 ui32FaultFW = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FAULT_FW_STATUS);
+                       IMG_UINT32 ui32CorrectedBitOffset = RGX_CR_FAULT_FW_STATUS_MMU_CORRECT_SHIFT -
+                                                                                               RGX_CR_FAULT_FW_STATUS_MMU_DETECT_SHIFT;
+
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Firmware safety fault status: 0x%X", __func__, ui32FaultFW));
+
+                       for (ui32FaultFlag = 0; ui32FaultFlag < ui32CorrectedBitOffset; ui32FaultFlag++)
+                       {
+                               if (BIT_ISSET(ui32FaultFW, ui32FaultFlag))
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s: Firmware safety hardware fault detected (0x%lX).",
+                                                __func__, BIT(ui32FaultFlag)));
+                                       eResetReason = RGX_CONTEXT_RESET_REASON_FW_ECC_ERR;
+                               }
+                               else if BIT_ISSET(ui32FaultFW, ui32FaultFlag + ui32CorrectedBitOffset)
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "%s: Firmware safety hardware fault corrected.(0x%lX).",
+                                                __func__, BIT(ui32FaultFlag)));
+
+                                       /* Only report this if we haven't detected a more serious error */
+                                       if (eResetReason != RGX_CONTEXT_RESET_REASON_FW_ECC_ERR)
+                                       {
+                                               eResetReason = RGX_CONTEXT_RESET_REASON_FW_ECC_OK;
+                                       }
+                               }
+                       }
+
+                       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_FAULT_FW_CLEAR, ui32FaultFW);
+               }
+
+               if (BIT_ISSET(ui32HostSafetyStatus, RGX_CR_EVENT_STATUS_WDT_TIMEOUT_SHIFT))
+               {
+                       volatile RGXFWIF_POW_STATE ePowState = psDevInfo->psRGXFWIfFwSysData->ePowState;
+
+                       if (ePowState == RGXFWIF_POW_ON)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Safety Watchdog Trigger !", __func__));
+
+                               /* Only report this if we haven't detected a more serious error */
+                               if (eResetReason != RGX_CONTEXT_RESET_REASON_FW_ECC_ERR)
+                               {
+                                       eResetReason = RGX_CONTEXT_RESET_REASON_FW_WATCHDOG;
+                               }
+                       }
+               }
+
+               /* Notify client and system layer of any error */
+               if (eResetReason != RGX_CONTEXT_RESET_REASON_NONE)
+               {
+                       PVRSRV_DEVICE_NODE *psDevNode = psDevInfo->psDeviceNode;
+                       PVRSRV_DEVICE_CONFIG *psDevConfig = psDevNode->psDevConfig;
+
+                       /* Client notification of device error will be achieved by
+                        * clients calling UM function RGXGetLastDeviceError() */
+                       psDevInfo->eLastDeviceError = eResetReason;
+
+                       /* Notify system layer of any error */
+                       if (psDevConfig->pfnSysDevErrorNotify)
+                       {
+                               PVRSRV_ROBUSTNESS_NOTIFY_DATA sErrorData = {0};
+
+                               sErrorData.eResetReason = eResetReason;
+
+                               psDevConfig->pfnSysDevErrorNotify(psDevConfig,
+                                                                 &sErrorData);
+                       }
+               }
+       }
+}
+
+static IMG_BOOL _WaitForInterruptsTimeoutCheck(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevInfo->psDeviceNode;
+       IMG_UINT32 ui32TID;
+#endif
+
+       RGXDEBUG_PRINT_IRQ_COUNT(psDevInfo);
+
+#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+       PVR_DPF((PVR_DBG_ERROR,
+               "Last RGX_LISRHandler State (DevID %u): 0x%08X Clock: %llu",
+                        psDeviceNode->sDevId.ui32InternalID,
+                        psDeviceNode->sLISRExecutionInfo.ui32Status,
+                        psDeviceNode->sLISRExecutionInfo.ui64Clockns));
+
+       for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "RGX FW thread %u: InterruptCountSnapshot: 0x%X",
+                                ui32TID, psDeviceNode->sLISRExecutionInfo.aui32InterruptCountSnapshot[ui32TID]));
+       }
+#else
+       PVR_DPF((PVR_DBG_ERROR, "No further information available. Please enable PVRSRV_DEBUG_LISR_EXECUTION"));
+#endif
+
+       return SampleIRQCount(psDevInfo->psRGXFWIfFwOsData->aui32InterruptCount,
+                                                 psDevInfo->aui32SampleIRQCount);
+}
+
+void RGX_WaitForInterruptsTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_BOOL bScheduleMISR;
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               bScheduleMISR = IMG_TRUE;
+       }
+       else
+       {
+               bScheduleMISR = _WaitForInterruptsTimeoutCheck(psDevInfo);
+       }
+
+       if (bScheduleMISR)
+       {
+               OSScheduleMISR(psDevInfo->pvMISRData);
+
+               if (psDevInfo->pvAPMISRData != NULL)
+               {
+                       OSScheduleMISR(psDevInfo->pvAPMISRData);
+               }
+       }
+}
+
+static inline IMG_BOOL RGXAckHwIrq(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                  IMG_UINT32 ui32IRQStatusReg,
+                                                                  IMG_UINT32 ui32IRQStatusEventMsk,
+                                                                  IMG_UINT32 ui32IRQClearReg,
+                                                                  IMG_UINT32 ui32IRQClearMask)
+{
+       IMG_UINT32 ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32IRQStatusReg);
+
+       /* clear only the pending bit of the thread that triggered this interrupt */
+       ui32IRQClearMask &= ui32IRQStatus;
+
+       if (ui32IRQStatus & ui32IRQStatusEventMsk)
+       {
+               /* acknowledge and clear the interrupt */
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32IRQClearReg, ui32IRQClearMask);
+               return IMG_TRUE;
+       }
+       else
+       {
+               /* spurious interrupt */
+               return IMG_FALSE;
+       }
+}
+
+static IMG_BOOL RGXAckIrqDedicated(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+               /* status & clearing registers are available on both Host and Guests
+                * and are agnostic of the Fw CPU type. Due to the remappings done by
+                * the 2nd stage device MMU, all drivers assume they are accessing
+                * register bank 0 */
+       return RGXAckHwIrq(psDevInfo,
+                                          RGX_CR_IRQ_OS0_EVENT_STATUS,
+                                          ~RGX_CR_IRQ_OS0_EVENT_STATUS_SOURCE_CLRMSK,
+                                          RGX_CR_IRQ_OS0_EVENT_CLEAR,
+                                          ~RGX_CR_IRQ_OS0_EVENT_CLEAR_SOURCE_CLRMSK);
+}
+
+static IMG_BOOL RGX_LISRHandler(void *pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGXFWIF_OSDATA *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
+       IMG_BOOL bIrqAcknowledged = IMG_FALSE;
+
+#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+       IMG_UINT32 ui32TID;
+
+       for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+       {
+               UPDATE_LISR_DBG_SNAPSHOT(ui32TID, psFwOsData->aui32InterruptCount[ui32TID]);
+       }
+
+       UPDATE_LISR_DBG_STATUS(RGX_LISR_INIT);
+       UPDATE_LISR_DBG_TIMESTAMP();
+#endif
+
+       UPDATE_LISR_DBG_COUNTER();
+
+       if (psDevInfo->bRGXPowered)
+       {
+               IMG_BOOL bSafetyEvent = (RGXHostSafetyEvents(psDevInfo) != 0);
+
+               if ((psDevInfo->pfnRGXAckIrq == NULL) || psDevInfo->pfnRGXAckIrq(psDevInfo) || bSafetyEvent)
+               {
+                       bIrqAcknowledged = IMG_TRUE;
+
+                       if (SampleIRQCount(psFwOsData->aui32InterruptCount,
+                                                          psDevInfo->aui32SampleIRQCount) || bSafetyEvent)
+                       {
+                               UPDATE_LISR_DBG_STATUS(RGX_LISR_PROCESSED);
+                               UPDATE_MISR_DBG_COUNTER();
+
+                               OSScheduleMISR(psDevInfo->pvMISRData);
+
+#if defined(SUPPORT_AUTOVZ)
+                               RGXUpdateAutoVzWdgToken(psDevInfo);
+#endif
+                               if (psDevInfo->pvAPMISRData != NULL)
+                               {
+                                       OSScheduleMISR(psDevInfo->pvAPMISRData);
+                               }
+                       }
+                       else
+                       {
+                               UPDATE_LISR_DBG_STATUS(RGX_LISR_FW_IRQ_COUNTER_NOT_UPDATED);
+                       }
+               }
+               else
+               {
+                       UPDATE_LISR_DBG_STATUS(RGX_LISR_NOT_TRIGGERED_BY_HW);
+               }
+       }
+       else
+       {
+               /* AutoVz drivers rebooting while the firmware is active must acknowledge
+                * and clear the hw IRQ line before the RGXInit() has finished. */
+               if (!(psDevInfo->psDeviceNode->bAutoVzFwIsUp &&
+                         (psDevInfo->pfnRGXAckIrq != NULL) &&
+                         psDevInfo->pfnRGXAckIrq(psDevInfo)))
+               {
+                       UPDATE_LISR_DBG_STATUS(RGX_LISR_DEVICE_NOT_POWERED);
+               }
+       }
+
+       return bIrqAcknowledged;
+}
+
+static void RGX_MISR_ProcessKCCBDeferredList(PVRSRV_DEVICE_NODE        *psDeviceNode)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       OS_SPINLOCK_FLAGS uiFlags;
+
+       /* First check whether there are pending commands in Deferred KCCB List */
+       OSSpinLockAcquire(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+       if (dllist_is_empty(&psDevInfo->sKCCBDeferredCommandsListHead))
+       {
+               OSSpinLockRelease(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+               return;
+       }
+       OSSpinLockRelease(psDevInfo->hLockKCCBDeferredCommandsList, uiFlags);
+
+       /* Powerlock to avoid further Power transition requests
+          while KCCB deferred list is being processed */
+       eError = PVRSRVPowerLock(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to acquire PowerLock (device: %p, error: %s)",
+                                __func__, psDeviceNode, PVRSRVGetErrorString(eError)));
+               return;
+       }
+
+       /* Try to send deferred KCCB commands Do not Poll from here*/
+       eError = RGXSendCommandsFromDeferredList(psDevInfo, IMG_FALSE);
+
+       PVRSRVPowerUnlock(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE,
+                                "%s could not flush Deferred KCCB list, KCCB is full.",
+                                __func__));
+       }
+}
+
+static void RGX_MISRHandler_CheckFWActivePowerState(void *psDevice)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = psDevice;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (psFwSysData->ePowState == RGXFWIF_POW_ON || psFwSysData->ePowState == RGXFWIF_POW_IDLE)
+       {
+               RGX_MISR_ProcessKCCBDeferredList(psDeviceNode);
+       }
+
+       if (psFwSysData->ePowState == RGXFWIF_POW_IDLE)
+       {
+               /* The FW is IDLE and therefore could be shut down */
+               eError = RGXActivePowerRequest(psDeviceNode);
+
+               if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED))
+               {
+                       if (eError != PVRSRV_ERROR_RETRY)
+                       {
+                               PVR_DPF((PVR_DBG_WARNING,
+                                       "%s: Failed RGXActivePowerRequest call (device: %p) with %s",
+                                       __func__, psDeviceNode, PVRSRVGetErrorString(eError)));
+                               PVRSRVDebugRequest(psDeviceNode, DEBUG_REQUEST_VERBOSITY_MAX, NULL, NULL);
+                       }
+                       else
+                       {
+                               /* Re-schedule the power down request as it was deferred. */
+                               OSScheduleMISR(psDevInfo->pvAPMISRData);
+                       }
+               }
+       }
+
+}
+
+/* Shorter defines to keep the code a bit shorter */
+#define GPU_IDLE       RGXFWIF_GPU_UTIL_STATE_IDLE
+#define GPU_ACTIVE     RGXFWIF_GPU_UTIL_STATE_ACTIVE
+#define GPU_BLOCKED    RGXFWIF_GPU_UTIL_STATE_BLOCKED
+#define MAX_ITERATIONS 64
+
+static PVRSRV_ERROR RGXGetGpuUtilStats(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       IMG_HANDLE hGpuUtilUser,
+                                       RGXFWIF_GPU_UTIL_STATS *psReturnStats)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       volatile RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+       RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
+       IMG_UINT64 ui64TimeNow;
+       IMG_UINT32 ui32Attempts;
+       IMG_UINT32 ui32Remainder;
+
+
+       /***** (1) Initialise return stats *****/
+
+       psReturnStats->bValid = IMG_FALSE;
+       psReturnStats->ui64GpuStatIdle       = 0;
+       psReturnStats->ui64GpuStatActive     = 0;
+       psReturnStats->ui64GpuStatBlocked    = 0;
+       psReturnStats->ui64GpuStatCumulative = 0;
+
+       if (hGpuUtilUser == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psAggregateStats = hGpuUtilUser;
+
+
+       /* Try to acquire GPU utilisation counters and repeat if the FW is in the middle of an update */
+       for (ui32Attempts = 0; ui32Attempts < 4; ui32Attempts++)
+       {
+               IMG_UINT64 aui64TmpCounters[RGXFWIF_GPU_UTIL_STATE_NUM] = {0};
+               IMG_UINT64 ui64LastPeriod = 0, ui64LastWord = 0, ui64LastState = 0, ui64LastTime = 0;
+               IMG_UINT32 i = 0;
+
+
+               /***** (2) Get latest data from shared area *****/
+
+               OSLockAcquire(psDevInfo->hGPUUtilLock);
+
+               /*
+                * First attempt at detecting if the FW is in the middle of an update.
+                * This should also help if the FW is in the middle of a 64 bit variable update.
+                */
+               while (((ui64LastWord != psUtilFWCb->ui64LastWord) ||
+                               (aui64TmpCounters[ui64LastState] !=
+                                psUtilFWCb->aui64StatsCounters[ui64LastState])) &&
+                          (i < MAX_ITERATIONS))
+               {
+                       ui64LastWord  = psUtilFWCb->ui64LastWord;
+                       ui64LastState = RGXFWIF_GPU_UTIL_GET_STATE(ui64LastWord);
+                       aui64TmpCounters[GPU_IDLE]    = psUtilFWCb->aui64StatsCounters[GPU_IDLE];
+                       aui64TmpCounters[GPU_ACTIVE]  = psUtilFWCb->aui64StatsCounters[GPU_ACTIVE];
+                       aui64TmpCounters[GPU_BLOCKED] = psUtilFWCb->aui64StatsCounters[GPU_BLOCKED];
+                       i++;
+               }
+
+               OSLockRelease(psDevInfo->hGPUUtilLock);
+
+               if (i == MAX_ITERATIONS)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                "RGXGetGpuUtilStats could not get reliable data after trying %u times", i));
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+
+
+               /***** (3) Compute return stats *****/
+
+               /* Update temp counters to account for the time since the last update to the shared ones */
+               OSMemoryBarrier(NULL); /* Ensure the current time is read after the loop above */
+               ui64TimeNow    = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64(psDeviceNode));
+               ui64LastTime   = RGXFWIF_GPU_UTIL_GET_TIME(ui64LastWord);
+               ui64LastPeriod = RGXFWIF_GPU_UTIL_GET_PERIOD(ui64TimeNow, ui64LastTime);
+               aui64TmpCounters[ui64LastState] += ui64LastPeriod;
+
+               /* Get statistics for a user since its last request */
+               psReturnStats->ui64GpuStatIdle = RGXFWIF_GPU_UTIL_GET_PERIOD(aui64TmpCounters[GPU_IDLE],
+                                                                            psAggregateStats->ui64GpuStatIdle);
+               psReturnStats->ui64GpuStatActive = RGXFWIF_GPU_UTIL_GET_PERIOD(aui64TmpCounters[GPU_ACTIVE],
+                                                                              psAggregateStats->ui64GpuStatActive);
+               psReturnStats->ui64GpuStatBlocked = RGXFWIF_GPU_UTIL_GET_PERIOD(aui64TmpCounters[GPU_BLOCKED],
+                                                                               psAggregateStats->ui64GpuStatBlocked);
+               psReturnStats->ui64GpuStatCumulative = psReturnStats->ui64GpuStatIdle +
+                                                      psReturnStats->ui64GpuStatActive +
+                                                      psReturnStats->ui64GpuStatBlocked;
+
+               if (psAggregateStats->ui64TimeStamp != 0)
+               {
+                       IMG_UINT64 ui64TimeSinceLastCall = ui64TimeNow - psAggregateStats->ui64TimeStamp;
+                       /* We expect to return at least 75% of the time since the last call in GPU stats */
+                       IMG_UINT64 ui64MinReturnedStats = ui64TimeSinceLastCall - (ui64TimeSinceLastCall / 4);
+
+                       /*
+                        * If the returned stats are substantially lower than the time since
+                        * the last call, then the Host might have read a partial update from the FW.
+                        * If this happens, try sampling the shared counters again.
+                        */
+                       if (psReturnStats->ui64GpuStatCumulative < ui64MinReturnedStats)
+                       {
+                               PVR_DPF((PVR_DBG_MESSAGE,
+                                        "%s: Return stats (%" IMG_UINT64_FMTSPEC ") too low "
+                                        "(call period %" IMG_UINT64_FMTSPEC ")",
+                                        __func__, psReturnStats->ui64GpuStatCumulative, ui64TimeSinceLastCall));
+                               PVR_DPF((PVR_DBG_MESSAGE, "%s: Attempt #%u has failed, trying again",
+                                        __func__, ui32Attempts));
+                               continue;
+                       }
+               }
+
+               break;
+       }
+
+
+       /***** (4) Update aggregate stats for the current user *****/
+
+       psAggregateStats->ui64GpuStatIdle    += psReturnStats->ui64GpuStatIdle;
+       psAggregateStats->ui64GpuStatActive  += psReturnStats->ui64GpuStatActive;
+       psAggregateStats->ui64GpuStatBlocked += psReturnStats->ui64GpuStatBlocked;
+       psAggregateStats->ui64TimeStamp       = ui64TimeNow;
+
+
+       /***** (5) Convert return stats to microseconds *****/
+
+       psReturnStats->ui64GpuStatIdle       = OSDivide64(psReturnStats->ui64GpuStatIdle, 1000, &ui32Remainder);
+       psReturnStats->ui64GpuStatActive     = OSDivide64(psReturnStats->ui64GpuStatActive, 1000, &ui32Remainder);
+       psReturnStats->ui64GpuStatBlocked    = OSDivide64(psReturnStats->ui64GpuStatBlocked, 1000, &ui32Remainder);
+       psReturnStats->ui64GpuStatCumulative = OSDivide64(psReturnStats->ui64GpuStatCumulative, 1000, &ui32Remainder);
+
+       /* Check that the return stats make sense */
+       if (psReturnStats->ui64GpuStatCumulative == 0)
+       {
+               /* We can enter here only if all the RGXFWIF_GPU_UTIL_GET_PERIOD
+                * returned 0. This could happen if the GPU frequency value
+                * is not well calibrated and the FW is updating the GPU state
+                * while the Host is reading it.
+                * When such an event happens frequently, timers or the aggregate
+                * stats might not be accurate...
+                */
+               PVR_DPF((PVR_DBG_WARNING, "RGXGetGpuUtilStats could not get reliable data."));
+               return PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
+       }
+
+       psReturnStats->bValid = IMG_TRUE;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SORgxGpuUtilStatsRegister(IMG_HANDLE *phGpuUtilUser)
+{
+       RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
+
+       /* NoStats used since this may be called outside of the register/de-register
+        * process calls which track memory use. */
+       psAggregateStats = OSAllocMemNoStats(sizeof(RGXFWIF_GPU_UTIL_STATS));
+       if (psAggregateStats == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psAggregateStats->ui64GpuStatIdle    = 0;
+       psAggregateStats->ui64GpuStatActive  = 0;
+       psAggregateStats->ui64GpuStatBlocked = 0;
+       psAggregateStats->ui64TimeStamp      = 0;
+
+       /* Not used */
+       psAggregateStats->bValid = IMG_FALSE;
+       psAggregateStats->ui64GpuStatCumulative = 0;
+
+       *phGpuUtilUser = psAggregateStats;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR SORgxGpuUtilStatsUnregister(IMG_HANDLE hGpuUtilUser)
+{
+       RGXFWIF_GPU_UTIL_STATS *psAggregateStats;
+
+       if (hGpuUtilUser == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psAggregateStats = hGpuUtilUser;
+       OSFreeMemNoStats(psAggregateStats);
+
+       return PVRSRV_OK;
+}
+
+/*
+       RGX MISR Handler
+*/
+static void RGX_MISRHandler_Main (void *pvData)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       /* Give the HWPerf service a chance to transfer some data from the FW
+        * buffer to the host driver transport layer buffer.
+        */
+       RGXHWPerfDataStoreCB(psDeviceNode);
+
+       /* Inform other services devices that we have finished an operation */
+       PVRSRVNotifyCommandCompletion(psDeviceNode);
+
+#if defined(SUPPORT_PDVFS) && defined(RGXFW_META_SUPPORT_2ND_THREAD)
+       /*
+        * Firmware CCB only exists for primary FW thread. Only requirement for
+        * non primary FW thread(s) to communicate with host driver is in the case
+        * of PDVFS running on non primary FW thread.
+        * This requirement is directly handled by the below
+        */
+       RGXPDVFSCheckCoreClkRateChange(psDeviceNode->pvDevice);
+#endif
+
+       /* Handle Safety events if necessary */
+       RGXSafetyEventHandler(psDeviceNode->pvDevice);
+
+       /* Signal the global event object */
+       PVRSRVSignalGlobalEO();
+
+       /* Process the Firmware CCB for pending commands */
+       RGXCheckFirmwareCCB(psDeviceNode->pvDevice);
+
+       /* Calibrate the GPU frequency and recorrelate Host and GPU timers (done every few seconds) */
+       RGXTimeCorrRestartPeriodic(psDeviceNode);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Process Workload Estimation Specific commands from the FW */
+       WorkEstCheckFirmwareCCB(psDeviceNode->pvDevice);
+#endif
+
+       if (psDevInfo->pvAPMISRData == NULL)
+       {
+               RGX_MISR_ProcessKCCBDeferredList(psDeviceNode);
+       }
+}
+#endif /* !defined(NO_HARDWARE) */
+
+static PVRSRV_ERROR RGXSetPowerParams(PVRSRV_RGXDEV_INFO   *psDevInfo,
+                                      PVRSRV_DEVICE_CONFIG *psDevConfig)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       /* Save information used on power transitions for later
+        * (when RGXStart and RGXStop are executed)
+        */
+       psDevInfo->sLayerParams.psDevInfo = psDevInfo;
+       psDevInfo->sLayerParams.psDevConfig = psDevConfig;
+#if defined(PDUMP)
+       psDevInfo->sLayerParams.ui32PdumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
+           RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               IMG_DEV_PHYADDR sKernelMMUCtxPCAddr;
+
+               if (psDevInfo->psDeviceNode->bAutoVzFwIsUp)
+               {
+                       /* If AutoVz firmware is up at this stage, the driver initialised it
+                        * during a previous life-cycle. The firmware's memory is already pre-mapped
+                        * and the MMU page tables reside in the predetermined memory carveout.
+                        * The Kernel MMU Context created in this life-cycle is a dummy structure
+                        * that is not used for mapping.
+                        * To program the Device's BIF with the correct PC address, use the base
+                        * address of the carveout reserved for MMU mappings as Kernel MMU PC Address */
+#if defined(PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR)
+                       sKernelMMUCtxPCAddr.uiAddr = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
+#else
+                       PHYS_HEAP_CONFIG *psFwHeapCfg = FindPhysHeapConfig(psDevConfig,
+                                                                                                                          PHYS_HEAP_USAGE_FW_MAIN);
+                       eError = (psFwHeapCfg != NULL) ? PVRSRV_OK : PVRSRV_ERROR_PHYSHEAP_CONFIG;
+                       PVR_LOG_RETURN_IF_ERROR(eError, "FindPhysHeapConfig(PHYS_HEAP_USAGE_FW_MAIN)");
+
+                       sKernelMMUCtxPCAddr.uiAddr = psFwHeapCfg->sCardBase.uiAddr +
+                                                                                (RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED);
+#endif /* PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR */
+               }
+               else
+               {
+                       eError = MMU_AcquireBaseAddr(psDevInfo->psKernelMMUCtx,
+                                                    &sKernelMMUCtxPCAddr);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: Failed to acquire Kernel MMU Ctx page catalog"));
+                               return eError;
+                       }
+               }
+
+               psDevInfo->sLayerParams.sPCAddr = sKernelMMUCtxPCAddr;
+       }
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       /* Send information used on power transitions to the trusted device as
+        * in this setup the driver cannot start/stop the GPU and perform resets
+        */
+       if (psDevConfig->pfnTDSetPowerParams)
+       {
+               PVRSRV_TD_POWER_PARAMS sTDPowerParams;
+
+               if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META) ||
+                   RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+               {
+                       sTDPowerParams.sPCAddr = psDevInfo->sLayerParams.sPCAddr;
+               }
+
+               eError = psDevConfig->pfnTDSetPowerParams(psDevConfig->hSysData,
+                                                                                                 &sTDPowerParams);
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXSetPowerParams: TDSetPowerParams not implemented!"));
+               eError = PVRSRV_ERROR_NOT_IMPLEMENTED;
+       }
+#endif
+
+       return eError;
+}
+
+/*
+       RGXSystemGetFabricCoherency
+*/
+PVRSRV_ERROR RGXSystemGetFabricCoherency(PVRSRV_DEVICE_CONFIG *psDevConfig,
+                                                                                IMG_CPU_PHYADDR sRegsCpuPBase,
+                                                                                IMG_UINT32 ui32RegsSize,
+                                                                                PVRSRV_DEVICE_FABRIC_TYPE *peDevFabricType,
+                                                                                PVRSRV_DEVICE_SNOOP_MODE *peCacheSnoopingMode)
+{
+       IMG_CHAR *aszLabels[] = {"none", "acelite", "fullace", "unknown"};
+       PVRSRV_DEVICE_SNOOP_MODE eAppHintCacheSnoopingMode;
+       PVRSRV_DEVICE_SNOOP_MODE eDeviceCacheSnoopingMode;
+       IMG_UINT32 ui32AppHintFabricCoherency;
+       IMG_UINT32 ui32DeviceFabricCoherency;
+       void *pvAppHintState = NULL;
+       IMG_UINT32 ui32AppHintDefault;
+#if !defined(NO_HARDWARE)
+       void *pvRegsBaseKM;
+       IMG_BOOL bPowerDown = IMG_TRUE;
+       PVRSRV_ERROR eError;
+#endif
+
+       if (!sRegsCpuPBase.uiAddr || !ui32RegsSize)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "RGXSystemGetFabricCoherency: Invalid RGX register base/size parameters"));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#if !defined(NO_HARDWARE)
+       pvRegsBaseKM = OSMapPhysToLin(sRegsCpuPBase, ui32RegsSize, PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+       if (!pvRegsBaseKM)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "RGXSystemGetFabricCoherency: Failed to create RGX register mapping"));
+               return PVRSRV_ERROR_BAD_MAPPING;
+       }
+
+       if (psDevConfig->psDevNode != NULL)
+       {
+               bPowerDown = (psDevConfig->psDevNode->eCurrentSysPowerState == PVRSRV_SYS_POWER_STATE_OFF);
+       }
+
+       /* Power-up the device as required to read the registers */
+       if (bPowerDown)
+       {
+               eError = PVRSRVSetSystemPowerState(psDevConfig, PVRSRV_SYS_POWER_STATE_ON);
+               PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVSetSystemPowerState ON");
+       }
+
+       /* AXI support within the SoC, bitfield COHERENCY_SUPPORT [1 .. 0]
+               value NO_COHERENCY        0x0 {SoC does not support any form of Coherency}
+               value ACE_LITE_COHERENCY  0x1 {SoC supports ACE-Lite or I/O Coherency}
+               value FULL_ACE_COHERENCY  0x2 {SoC supports full ACE or 2-Way Coherency} */
+       ui32DeviceFabricCoherency = OSReadHWReg32(pvRegsBaseKM, RGX_CR_SOC_AXI);
+       PVR_LOG(("AXI fabric coherency (RGX_CR_SOC_AXI): 0x%x", ui32DeviceFabricCoherency));
+#if defined(DEBUG)
+       if (ui32DeviceFabricCoherency & ~((IMG_UINT32)RGX_CR_SOC_AXI_MASKFULL))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Invalid RGX_CR_SOC_AXI value.", __func__));
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
+#endif
+       ui32DeviceFabricCoherency &= ~((IMG_UINT32)RGX_CR_SOC_AXI_COHERENCY_SUPPORT_CLRMSK);
+       ui32DeviceFabricCoherency >>= RGX_CR_SOC_AXI_COHERENCY_SUPPORT_SHIFT;
+
+       if (bPowerDown)
+       {
+               eError = PVRSRVSetSystemPowerState(psDevConfig, PVRSRV_SYS_POWER_STATE_OFF);
+               PVR_LOG_RETURN_IF_ERROR(eError, "PVRSRVSetSystemPowerState OFF");
+       }
+
+       /* UnMap Regs */
+       OSUnMapPhysToLin(pvRegsBaseKM, ui32RegsSize);
+
+       switch (ui32DeviceFabricCoherency)
+       {
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_FULL_ACE_COHERENCY:
+               eDeviceCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CROSS;
+               *peDevFabricType = PVRSRV_DEVICE_FABRIC_FULLACE;
+               break;
+
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_ACE_LITE_COHERENCY:
+               eDeviceCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CPU_ONLY;
+               *peDevFabricType = PVRSRV_DEVICE_FABRIC_ACELITE;
+               break;
+
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_NO_COHERENCY:
+       default:
+               eDeviceCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_NONE;
+               *peDevFabricType = PVRSRV_DEVICE_FABRIC_NONE;
+               break;
+       }
+#else /* !defined(NO_HARDWARE) */
+#if defined(RGX_FEATURE_GPU_CPU_COHERENCY)
+       *peDevFabricType = PVRSRV_DEVICE_FABRIC_FULLACE;
+       eDeviceCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CROSS;
+       ui32DeviceFabricCoherency = RGX_CR_SOC_AXI_COHERENCY_SUPPORT_FULL_ACE_COHERENCY;
+#else
+       *peDevFabricType = PVRSRV_DEVICE_FABRIC_ACELITE;
+       eDeviceCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CPU_ONLY;
+       ui32DeviceFabricCoherency = RGX_CR_SOC_AXI_COHERENCY_SUPPORT_ACE_LITE_COHERENCY;
+#endif
+#endif /* !defined(NO_HARDWARE) */
+
+       OSCreateKMAppHintState(&pvAppHintState);
+       ui32AppHintDefault = RGX_CR_SOC_AXI_COHERENCY_SUPPORT_FULL_ACE_COHERENCY;
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, FabricCoherencyOverride,
+                                                &ui32AppHintDefault, &ui32AppHintFabricCoherency);
+       OSFreeKMAppHintState(pvAppHintState);
+
+#if defined(SUPPORT_SECURITY_VALIDATION)
+       /* Temporarily disable coherency */
+       ui32AppHintFabricCoherency = RGX_CR_SOC_AXI_COHERENCY_SUPPORT_NO_COHERENCY;
+#endif
+
+       /* Suppress invalid AppHint value */
+       switch (ui32AppHintFabricCoherency)
+       {
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_NO_COHERENCY:
+               eAppHintCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_NONE;
+               break;
+
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_ACE_LITE_COHERENCY:
+               eAppHintCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CPU_ONLY;
+               break;
+
+       case RGX_CR_SOC_AXI_COHERENCY_SUPPORT_FULL_ACE_COHERENCY:
+               eAppHintCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CROSS;
+               break;
+
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                               "Invalid FabricCoherencyOverride AppHint %d, ignoring",
+                               ui32AppHintFabricCoherency));
+               eAppHintCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_CROSS;
+               ui32AppHintFabricCoherency = RGX_CR_SOC_AXI_COHERENCY_SUPPORT_FULL_ACE_COHERENCY;
+               break;
+       }
+
+       if (ui32AppHintFabricCoherency < ui32DeviceFabricCoherency)
+       {
+               PVR_LOG(("Downgrading device fabric coherency from %s to %s",
+                               aszLabels[ui32DeviceFabricCoherency],
+                               aszLabels[ui32AppHintFabricCoherency]));
+               eDeviceCacheSnoopingMode = eAppHintCacheSnoopingMode;
+       }
+       else if (ui32AppHintFabricCoherency > ui32DeviceFabricCoherency)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                               "Cannot upgrade device fabric coherency from %s to %s, not supported by device!",
+                               aszLabels[ui32DeviceFabricCoherency],
+                               aszLabels[ui32AppHintFabricCoherency]));
+
+               /* Override requested-for app-hint with actual app-hint value being used */
+               ui32AppHintFabricCoherency = ui32DeviceFabricCoherency;
+       }
+
+       *peCacheSnoopingMode = eDeviceCacheSnoopingMode;
+       return PVRSRV_OK;
+}
+
+/*
+       RGXSystemHasFBCDCVersion31
+*/
+static IMG_BOOL RGXSystemHasFBCDCVersion31(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+#if defined(SUPPORT_VALIDATION)
+       IMG_UINT32 ui32FBCDCVersionOverride = 0;
+#endif
+
+       {
+
+#if defined(SUPPORT_VALIDATION)
+               if (ui32FBCDCVersionOverride == 2)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                "%s: FBCDCVersionOverride forces FBC3.1 but this core doesn't support it!",
+                                __func__));
+               }
+#endif
+
+#if !defined(NO_HARDWARE)
+               if (psDeviceNode->psDevConfig->bHasFBCDCVersion31)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: System uses FBCDC3.1 but GPU doesn't support it!",
+                                __func__));
+               }
+#endif
+       }
+
+       return IMG_FALSE;
+}
+
+/*
+       RGXDevMMUAttributes
+*/
+static MMU_DEVICEATTRIBS *RGXDevMMUAttributes(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                              IMG_BOOL bKernelMemoryCtx)
+{
+       MMU_DEVICEATTRIBS *psMMUDevAttrs = NULL;
+
+       /* bKernelMemoryCtx is only used for rogue cores */
+       PVR_UNREFERENCED_PARAMETER(bKernelMemoryCtx);
+
+       if (psDeviceNode->pfnCheckDeviceFeature)
+       {
+               psMMUDevAttrs = psDeviceNode->psMMUDevAttrs;
+       }
+
+       return psMMUDevAttrs;
+}
+
+/*
+ * RGXInitDevPart2
+ */
+PVRSRV_ERROR RGXInitDevPart2 (PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                         IMG_UINT32                    ui32DeviceFlags,
+                                                         IMG_UINT32                    ui32HWPerfHostFilter,
+                                                         RGX_ACTIVEPM_CONF             eActivePMConf,
+                                                         IMG_UINT32                    ui32AvailablePowUnitsMask,
+                                                         IMG_UINT32                    ui32AvailableRACMask)
+{
+       PVRSRV_ERROR                    eError;
+       PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_DEV_POWER_STATE  eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
+       PVRSRV_DEVICE_CONFIG    *psDevConfig = psDeviceNode->psDevConfig;
+       IMG_UINT32                      ui32AllPowUnitsMask = (1 << psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount) - 1;
+       IMG_UINT32                      ui32AllRACMask = (1 << psDevInfo->sDevFeatureCfg.ui32MAXRACCount) - 1;
+
+       /* Assume system layer has turned power on by this point, required before powering device */
+       psDeviceNode->eCurrentSysPowerState = PVRSRV_SYS_POWER_STATE_ON;
+
+       PDUMPCOMMENT(psDeviceNode, "RGX Initialisation Part 2");
+
+#if defined(TIMING) || defined(DEBUG)
+       OSUserModeAccessToPerfCountersEn();
+#endif
+
+       /* Initialise Device Flags */
+       psDevInfo->ui32DeviceFlags = 0;
+       RGXSetDeviceFlags(psDevInfo, ui32DeviceFlags, IMG_TRUE);
+
+       /* Allocate DVFS Table (needs to be allocated before GPU trace events
+        *  component is initialised because there is a dependency between them) */
+       psDevInfo->psGpuDVFSTable = OSAllocZMem(sizeof(*(psDevInfo->psGpuDVFSTable)));
+       PVR_LOG_GOTO_IF_NOMEM(psDevInfo->psGpuDVFSTable, eError, ErrorExit);
+
+
+       if (psDevInfo->ui32HWPerfHostFilter == 0)
+       {
+               RGXHWPerfHostSetEventFilter(psDevInfo, ui32HWPerfHostFilter);
+       }
+
+       /* If HWPerf enabled allocate all resources for the host side buffer. */
+       if (psDevInfo->ui32HWPerfHostFilter != 0)
+       {
+               if (RGXHWPerfHostInitOnDemandResources(psDevInfo) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "HWPerfHost buffer on demand"
+                               " initialisation failed."));
+               }
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* Initialise work estimation lock */
+       eError = OSLockCreate(&psDevInfo->hWorkEstLock);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(WorkEstLock)", ErrorExit);
+#endif
+
+       /* Initialise lists of ZSBuffers */
+       eError = OSLockCreate(&psDevInfo->hLockZSBuffer);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(LockZSBuffer)", ErrorExit);
+       dllist_init(&psDevInfo->sZSBufferHead);
+       psDevInfo->ui32ZSBufferCurrID = 1;
+
+       /* Initialise lists of growable Freelists */
+       eError = OSLockCreate(&psDevInfo->hLockFreeList);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(LockFreeList)", ErrorExit);
+       dllist_init(&psDevInfo->sFreeListHead);
+       psDevInfo->ui32FreelistCurrID = 1;
+
+       eError = OSLockCreate(&psDevInfo->hDebugFaultInfoLock);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(DebugFaultInfoLock)", ErrorExit);
+
+       if (GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED)
+       {
+               eError = OSLockCreate(&psDevInfo->hMMUCtxUnregLock);
+               PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(MMUCtxUnregLock)", ErrorExit);
+       }
+
+       /* Setup GPU utilisation stats update callback */
+       eError = OSLockCreate(&psDevInfo->hGPUUtilLock);
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSLockCreate(GPUUtilLock)", ErrorExit);
+#if !defined(NO_HARDWARE)
+       psDevInfo->pfnGetGpuUtilStats = RGXGetGpuUtilStats;
+#endif
+
+       eDefaultPowerState = PVRSRV_DEV_POWER_STATE_ON;
+       psDevInfo->eActivePMConf = eActivePMConf;
+
+       /* Validate the SPU mask and initialize to number of SPUs to power up */
+       if ((ui32AvailablePowUnitsMask & ui32AllPowUnitsMask) == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s:Invalid SPU mask (All=0x%X, Non Fused=0x%X). At-least one SPU must to be powered up.",
+                        __func__,
+                        ui32AllPowUnitsMask,
+                        ui32AvailablePowUnitsMask));
+               PVR_LOG_GOTO_WITH_ERROR("ui32AvailablePowUnitsMask", eError, PVRSRV_ERROR_INVALID_SPU_MASK, ErrorExit);
+       }
+
+       psDevInfo->ui32AvailablePowUnitsMask = ui32AvailablePowUnitsMask & ui32AllPowUnitsMask;
+
+       psDevInfo->ui32AvailableRACMask = ui32AvailableRACMask & ui32AllRACMask;
+
+#if !defined(NO_HARDWARE)
+       /* set-up the Active Power Mgmt callback */
+       {
+               RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+               IMG_BOOL bSysEnableAPM = psRGXData->psRGXTimingInfo->bEnableActivePM;
+               IMG_BOOL bEnableAPM = ((eActivePMConf == RGX_ACTIVEPM_DEFAULT) && bSysEnableAPM) ||
+                                                          (eActivePMConf == RGX_ACTIVEPM_FORCE_ON);
+
+               if (bEnableAPM && (!PVRSRV_VZ_MODE_IS(NATIVE)))
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Active Power Management disabled in virtualization mode", __func__));
+                       bEnableAPM = IMG_FALSE;
+               }
+
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1) && defined(SUPPORT_AUTOVZ)
+               /* The AutoVz driver enable a virtualisation watchdog not compatible with APM */
+               PVR_ASSERT(bEnableAPM == IMG_FALSE);
+#endif
+
+               if (bEnableAPM)
+               {
+                       eError = OSInstallMISR(&psDevInfo->pvAPMISRData,
+                                       RGX_MISRHandler_CheckFWActivePowerState,
+                                       psDeviceNode,
+                                       "RGX_CheckFWActivePower");
+                       PVR_LOG_GOTO_IF_ERROR(eError, "OSInstallMISR(APMISR)", ErrorExit);
+
+                       /* Prevent the device being woken up before there is something to do. */
+                       eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
+               }
+       }
+#endif
+
+       PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableAPM,
+                                           RGXQueryAPMState,
+                                           RGXSetAPMState,
+                                           psDeviceNode,
+                                           NULL);
+
+       RGXTimeCorrInitAppHintCallbacks(psDeviceNode);
+
+       /* Register the device with the power manager */
+       eError = PVRSRVRegisterPowerDevice(psDeviceNode,
+                                                                          (PVRSRV_VZ_MODE_IS(NATIVE)) ? &RGXPrePowerState : &RGXVzPrePowerState,
+                                                                          (PVRSRV_VZ_MODE_IS(NATIVE)) ? &RGXPostPowerState : &RGXVzPostPowerState,
+                                                                          psDevConfig->pfnPrePowerState, psDevConfig->pfnPostPowerState,
+                                                                          &RGXPreClockSpeedChange, &RGXPostClockSpeedChange,
+                                                                          &RGXForcedIdleRequest, &RGXCancelForcedIdleRequest,
+                                                                          &RGXPowUnitsStateMaskChange,
+                                                                          (IMG_HANDLE)psDeviceNode,
+                                                                          PVRSRV_DEV_POWER_STATE_OFF,
+                                                                          eDefaultPowerState);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVRegisterPowerDevice", ErrorExit);
+
+       eError = RGXSetPowerParams(psDevInfo, psDevConfig);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetPowerParams", ErrorExit);
+
+#if defined(SUPPORT_VALIDATION)
+       {
+               void *pvAppHintState = NULL;
+
+               IMG_UINT32 ui32AppHintDefault;
+
+               OSCreateKMAppHintState(&pvAppHintState);
+               ui32AppHintDefault = PVRSRV_APPHINT_TESTSLRINTERVAL;
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, TestSLRInterval,
+                                    &ui32AppHintDefault, &psDevInfo->ui32TestSLRInterval);
+               PVR_LOG(("OSGetKMAppHintUINT32(TestSLRInterval) ui32AppHintDefault=%d, psDevInfo->ui32TestSLRInterval=%d",
+                       ui32AppHintDefault, psDevInfo->ui32TestSLRInterval));
+               OSFreeKMAppHintState(pvAppHintState);
+               psDevInfo->ui32TestSLRCount = psDevInfo->ui32TestSLRInterval;
+               psDevInfo->ui32SLRSkipFWAddr = 0;
+       }
+#endif
+
+#if defined(PDUMP)
+#if defined(NO_HARDWARE)
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_DEINIT, "Wait for the FW to signal idle");
+
+       /* Kick the FW once, in case it still needs to detect and set the idle state */
+       PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME,
+                          RGX_CR_MTS_SCHEDULE,
+                          RGXFWIF_DM_GP & ~RGX_CR_MTS_SCHEDULE_DM_CLRMSK,
+                          PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_DEINIT);
+
+       eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfFwSysDataMemDesc,
+                                       offsetof(RGXFWIF_SYSDATA, ePowState),
+                                       RGXFWIF_POW_IDLE,
+                                       0xFFFFFFFFU,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       PDUMP_FLAGS_CONTINUOUS | PDUMP_FLAGS_DEINIT);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemPDumpDevmemPol32", ErrorExit);
+#endif
+
+       /* Run RGXStop with the correct PDump flags to feed the last-frame deinit buffer */
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_DEINIT,
+                             "RGX deinitialisation commands");
+
+       psDevInfo->sLayerParams.ui32PdumpFlags |= PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW;
+
+       if (! PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = RGXStop(&psDevInfo->sLayerParams);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXStop", ErrorExit);
+       }
+
+       psDevInfo->sLayerParams.ui32PdumpFlags &= ~(PDUMP_FLAGS_DEINIT | PDUMP_FLAGS_NOHW);
+#endif
+
+#if !defined(NO_HARDWARE)
+       eError = RGXInstallProcessQueuesMISR(&psDevInfo->hProcessQueuesMISR, psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXInstallProcessQueuesMISR", ErrorExit);
+
+       /* Register RGX to receive notifies when other devices complete some work */
+       PVRSRVRegisterCmdCompleteNotify(&psDeviceNode->hCmdCompNotify, &RGXScheduleProcessQueuesKM, psDeviceNode);
+
+       /* Register the interrupt handlers */
+       eError = OSInstallMISR(&psDevInfo->pvMISRData,
+                       RGX_MISRHandler_Main,
+                       psDeviceNode,
+                       "RGX_Main");
+       PVR_LOG_GOTO_IF_ERROR(eError, "OSInstallMISR(MISR)", ErrorExit);
+
+       /* only the HOST_IRQ bus is supported on volcanic for IRQ delivery */
+       psDevInfo->pfnRGXAckIrq = RGXAckIrqDedicated;
+
+       eError = SysInstallDeviceLISR(psDevConfig->hSysData,
+                                                                 psDevConfig->ui32IRQ,
+                                                                 PVRSRV_MODNAME,
+                                                                 RGX_LISRHandler,
+                                                                 psDeviceNode,
+                                                                 &psDevInfo->pvLISRData);
+       PVR_LOG_GOTO_IF_ERROR(eError, "SysInstallDeviceLISR", ErrorExit);
+#endif /* !defined(NO_HARDWARE) */
+
+#if defined(PDUMP)
+/* We need to wrap the check for S7_CACHE_HIERARCHY being supported inside
+ * #if defined(RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK)...#endif, as the
+ * RGX_IS_FEATURE_SUPPORTED macro references a bitmask define derived from its
+ * last parameter which will not exist on architectures which do not have this
+ * feature.
+ * Note we check for RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK rather than for
+ * RGX_FEATURE_S7_CACHE_HIERARCHY (which might seem a better choice) as this
+ * means we can build the kernel driver without having to worry about the BVNC
+ * (the BIT_MASK is defined in rgx_bvnc_defs_km.h for all BVNCs for a given
+ *  architecture, whereas the FEATURE is only defined for those BVNCs that
+ *  support it).
+ */
+#if defined(RGX_FEATURE_S7_CACHE_HIERARCHY_BIT_MASK)
+       if (!(RGX_IS_FEATURE_SUPPORTED(psDevInfo, S7_CACHE_HIERARCHY)))
+#endif
+       {
+               if (!PVRSRVSystemSnoopingOfCPUCache(psDevConfig) &&
+                               !PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
+               {
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                             "System has NO cache snooping");
+               }
+               else
+               {
+                       if (PVRSRVSystemSnoopingOfCPUCache(psDevConfig))
+                       {
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                     "System has CPU cache snooping");
+                       }
+                       if (PVRSRVSystemSnoopingOfDeviceCache(psDevConfig))
+                       {
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                                     "System has DEVICE cache snooping");
+                       }
+               }
+       }
+#endif
+
+       eError = PVRSRVTQLoadShaders(psDeviceNode);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVTQLoadShaders", ErrorExit);
+
+       psDevInfo->bDevInit2Done = IMG_TRUE;
+
+       return PVRSRV_OK;
+
+ErrorExit:
+       DevPart2DeInitRGX(psDeviceNode);
+
+       return eError;
+}
+
+#define VZ_RGX_FW_FILENAME_SUFFIX ".vz"
+#define RGX_FW_FILENAME_MAX_SIZE   ((sizeof(RGX_FW_FILENAME)+ \
+                       RGX_BVNC_STR_SIZE_MAX+sizeof(VZ_RGX_FW_FILENAME_SUFFIX)))
+
+static void _GetFWFileName(PVRSRV_DEVICE_NODE *psDeviceNode,
+               IMG_CHAR *pszFWFilenameStr,
+               IMG_CHAR *pszFWpFilenameStr)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const IMG_CHAR * const pszFWFilenameSuffix =
+                       PVRSRV_VZ_MODE_IS(NATIVE) ? "" : VZ_RGX_FW_FILENAME_SUFFIX;
+
+       OSSNPrintf(pszFWFilenameStr, RGX_FW_FILENAME_MAX_SIZE,
+                       "%s." RGX_BVNC_STR_FMTSPEC "%s",
+                       RGX_FW_FILENAME,
+                       psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
+                       psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C,
+                       pszFWFilenameSuffix);
+
+       OSSNPrintf(pszFWpFilenameStr, RGX_FW_FILENAME_MAX_SIZE,
+                       "%s." RGX_BVNC_STRP_FMTSPEC "%s",
+                       RGX_FW_FILENAME,
+                       psDevInfo->sDevFeatureCfg.ui32B, psDevInfo->sDevFeatureCfg.ui32V,
+                       psDevInfo->sDevFeatureCfg.ui32N, psDevInfo->sDevFeatureCfg.ui32C,
+                       pszFWFilenameSuffix);
+}
+
+PVRSRV_ERROR RGXLoadAndGetFWData(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 OS_FW_IMAGE **ppsRGXFW,
+                                 const IMG_BYTE **ppbFWData)
+{
+       IMG_CHAR aszFWFilenameStr[RGX_FW_FILENAME_MAX_SIZE];
+       IMG_CHAR aszFWpFilenameStr[RGX_FW_FILENAME_MAX_SIZE];
+       IMG_CHAR *pszLoadedFwStr;
+       PVRSRV_ERROR eErr;
+
+       /* Prepare the image filenames to use in the following code */
+       _GetFWFileName(psDeviceNode, aszFWFilenameStr, aszFWpFilenameStr);
+
+       /* Get pointer to Firmware image */
+       pszLoadedFwStr = aszFWFilenameStr;
+       eErr = OSLoadFirmware(psDeviceNode, pszLoadedFwStr, OS_FW_VERIFY_FUNCTION, ppsRGXFW);
+       if (eErr == PVRSRV_ERROR_NOT_FOUND)
+       {
+               pszLoadedFwStr = aszFWpFilenameStr;
+               eErr = OSLoadFirmware(psDeviceNode, pszLoadedFwStr, OS_FW_VERIFY_FUNCTION, ppsRGXFW);
+               if (eErr == PVRSRV_ERROR_NOT_FOUND)
+               {
+                       pszLoadedFwStr = RGX_FW_FILENAME;
+                       eErr = OSLoadFirmware(psDeviceNode, pszLoadedFwStr, OS_FW_VERIFY_FUNCTION, ppsRGXFW);
+                       if (eErr == PVRSRV_ERROR_NOT_FOUND)
+                       {
+                               PVR_DPF((PVR_DBG_FATAL, "All RGX Firmware image loads failed for '%s' (%s)",
+                                               aszFWFilenameStr, PVRSRVGetErrorString(eErr)));
+                       }
+               }
+       }
+
+       if (eErr == PVRSRV_OK)
+       {
+               PVR_LOG(("RGX Firmware image '%s' loaded", pszLoadedFwStr));
+               *ppbFWData = (const IMG_BYTE*)OSFirmwareData(*ppsRGXFW);
+       }
+       else
+       {
+               *ppbFWData = NULL;
+       }
+
+       return eErr;
+
+}
+
+#if defined(PDUMP)
+PVRSRV_ERROR RGXInitHWPerfCounters(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       RGXFWIF_KCCB_CMD sKccbCmd;
+       PVRSRV_ERROR eError;
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       /* Fill in the command structure with the parameters needed */
+       sKccbCmd.eCmdType = RGXFWIF_KCCB_CMD_HWPERF_CONFIG_ENABLE_BLKS_DIRECT;
+
+       eError = RGXSendCommandWithPowLock(psDeviceNode->pvDevice,
+                                          &sKccbCmd,
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       return eError;
+}
+#endif
+
+PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       /* set up fw memory contexts */
+       PVRSRV_RGXDEV_INFO   *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+       PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_AUTOVZ)
+       PHYS_HEAP *psDefaultPhysHeap = psDeviceNode->psMMUPhysHeap;
+
+       if (PVRSRV_VZ_MODE_IS(HOST) && (!psDeviceNode->bAutoVzFwIsUp))
+       {
+               /* Temporarily swap the MMU and default GPU physheap to allow the page
+                * tables of all memory mapped by the FwKernel context to be placed
+                * in a dedicated memory carveout. This should allow the firmware mappings to
+                * persist after a Host kernel crash or driver reset. */
+
+               psDeviceNode->psMMUPhysHeap = psDeviceNode->psFwMMUReservedPhysHeap;
+       }
+#endif
+
+       /* Set the device fabric coherency before FW context creation */
+       eError = RGXSystemGetFabricCoherency(psDevConfig,
+                                                                                psDevConfig->sRegsCpuPBase,
+                                                                                psDevConfig->ui32RegsSize,
+                                                                                &psDeviceNode->eDevFabricType,
+                                                                                &psDevConfig->eCacheSnoopingMode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed RGXSystemGetFabricCoherency (%u)",
+                        __func__,
+                        eError));
+               goto failed_to_create_ctx;
+       }
+
+       /* Register callbacks for creation of device memory contexts */
+       psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
+       psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
+
+       /* Create the memory context for the firmware. */
+       eError = DevmemCreateContext(psDeviceNode, DEVMEM_HEAPCFG_META,
+                                    &psDevInfo->psKernelDevmemCtx);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed DevmemCreateContext (%u)",
+                        __func__,
+                        eError));
+               goto failed_to_create_ctx;
+       }
+
+       eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx, RGX_FIRMWARE_MAIN_HEAP_IDENT,
+                                     &psDevInfo->psFirmwareMainHeap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed DevmemFindHeapByName (%u)",
+                        __func__,
+                        eError));
+               goto failed_to_find_heap;
+       }
+
+       eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx, RGX_FIRMWARE_CONFIG_HEAP_IDENT,
+                                     &psDevInfo->psFirmwareConfigHeap);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed DevmemFindHeapByName (%u)",
+                        __func__,
+                        eError));
+               goto failed_to_find_heap;
+       }
+
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+               IMG_UINT32 ui32OSID;
+               for (ui32OSID = RGX_FIRST_RAW_HEAP_OSID; ui32OSID < RGX_NUM_OS_SUPPORTED; ui32OSID++)
+               {
+                       IMG_CHAR szHeapName[RA_MAX_NAME_LENGTH];
+
+                       OSSNPrintf(szHeapName, sizeof(szHeapName), RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT, ui32OSID);
+                       eError = DevmemFindHeapByName(psDevInfo->psKernelDevmemCtx, szHeapName,
+                                                                                 &psDevInfo->psGuestFirmwareRawHeap[ui32OSID]);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemFindHeapByName", failed_to_find_heap);
+               }
+       }
+#endif
+
+#if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+               IMG_DEV_PHYADDR sPhysHeapBase;
+               IMG_UINT32 ui32OSID;
+
+               eError = PhysHeapGetDevPAddr(psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_MAIN], &sPhysHeapBase);
+               PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapGetDevPAddr", failed_to_find_heap);
+
+               for (ui32OSID = RGX_FIRST_RAW_HEAP_OSID; ui32OSID < RGX_NUM_OS_SUPPORTED; ui32OSID++)
+               {
+                       IMG_DEV_PHYADDR sRawFwHeapBase = {sPhysHeapBase.uiAddr + (ui32OSID * RGX_FIRMWARE_RAW_HEAP_SIZE)};
+
+                       eError = RGXFwRawHeapAllocMap(psDeviceNode,
+                                                                                 ui32OSID,
+                                                                                 sRawFwHeapBase,
+                                                                                 RGX_FIRMWARE_RAW_HEAP_SIZE);
+                       if (eError != PVRSRV_OK)
+                       {
+                               for (; ui32OSID > RGX_FIRST_RAW_HEAP_OSID; ui32OSID--)
+                               {
+                                       RGXFwRawHeapUnmapFree(psDeviceNode, ui32OSID);
+                               }
+                               PVR_LOG_GOTO_IF_ERROR(eError, "RGXFwRawHeapAllocMap", failed_to_find_heap);
+                       }
+               }
+
+#if defined(SUPPORT_AUTOVZ)
+               /* restore default Px setup */
+               psDeviceNode->psMMUPhysHeap = psDefaultPhysHeap;
+#endif
+       }
+#else
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = PvzClientMapDevPhysHeap(psDeviceNode->psDevConfig);
+               PVR_LOG_GOTO_IF_ERROR(eError, "PvzClientMapDevPhysHeap", failed_to_find_heap);
+       }
+#endif /* defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS) */
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               DevmemHeapSetPremapStatus(psDevInfo->psFirmwareMainHeap, IMG_TRUE);
+               DevmemHeapSetPremapStatus(psDevInfo->psFirmwareConfigHeap, IMG_TRUE);
+       }
+
+       return eError;
+
+failed_to_find_heap:
+       /*
+        * Clear the mem context create callbacks before destroying the RGX firmware
+        * context to avoid a spurious callback.
+        */
+       psDeviceNode->pfnRegisterMemoryContext = NULL;
+       psDeviceNode->pfnUnregisterMemoryContext = NULL;
+       DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
+       psDevInfo->psKernelDevmemCtx = NULL;
+failed_to_create_ctx:
+       return eError;
+}
+
+void RGXDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR       eError;
+
+#if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+#if defined(SUPPORT_AUTOVZ)
+               PHYS_HEAP *psDefaultPhysHeap = psDeviceNode->psMMUPhysHeap;
+
+               psDeviceNode->psMMUPhysHeap = psDeviceNode->psFwMMUReservedPhysHeap;
+
+               if (!psDeviceNode->bAutoVzFwIsUp)
+#endif
+               {
+                       IMG_UINT32 ui32OSID;
+
+                       for (ui32OSID = RGX_FIRST_RAW_HEAP_OSID; ui32OSID < RGX_NUM_OS_SUPPORTED; ui32OSID++)
+                       {
+                               RGXFwRawHeapUnmapFree(psDeviceNode, ui32OSID);
+                       }
+               }
+#if defined(SUPPORT_AUTOVZ)
+               psDeviceNode->psMMUPhysHeap = psDefaultPhysHeap;
+#endif
+       }
+#else
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               (void) PvzClientUnmapDevPhysHeap(psDeviceNode->psDevConfig);
+
+               if (psDevInfo->psFirmwareMainHeap)
+               {
+                       DevmemHeapSetPremapStatus(psDevInfo->psFirmwareMainHeap, IMG_FALSE);
+               }
+               if (psDevInfo->psFirmwareConfigHeap)
+               {
+                       DevmemHeapSetPremapStatus(psDevInfo->psFirmwareConfigHeap, IMG_FALSE);
+               }
+       }
+#endif
+
+       /*
+        * Clear the mem context create callbacks before destroying the RGX firmware
+        * context to avoid a spurious callback.
+        */
+       psDeviceNode->pfnRegisterMemoryContext = NULL;
+       psDeviceNode->pfnUnregisterMemoryContext = NULL;
+
+       if (psDevInfo->psKernelDevmemCtx)
+       {
+               eError = DevmemDestroyContext(psDevInfo->psKernelDevmemCtx);
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
+}
+
+static PVRSRV_ERROR RGXAlignmentCheck(PVRSRV_DEVICE_NODE *psDevNode,
+                                      IMG_UINT32 ui32AlignChecksSizeUM,
+                                      IMG_UINT32 aui32AlignChecksUM[])
+{
+       static const IMG_UINT32 aui32AlignChecksKM[] = {RGXFW_ALIGN_CHECKS_INIT_KM};
+       IMG_UINT32 ui32UMChecksOffset = ARRAY_SIZE(aui32AlignChecksKM) + 1;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
+       IMG_UINT32 i, *paui32FWAlignChecks;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       /* Skip the alignment check if the driver is guest
+          since there is no firmware to check against */
+       PVRSRV_VZ_RET_IF_MODE(GUEST, eError);
+
+       if (psDevInfo->psRGXFWAlignChecksMemDesc == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: FW Alignment Check Mem Descriptor is NULL",
+                        __func__));
+               return PVRSRV_ERROR_ALIGNMENT_ARRAY_NOT_AVAILABLE;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc,
+                                         (void **) &paui32FWAlignChecks);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Failed to acquire kernel address for alignment checks (%u)",
+                        __func__,
+                        eError));
+               return eError;
+       }
+
+       paui32FWAlignChecks += ui32UMChecksOffset;
+       if (*paui32FWAlignChecks++ != ui32AlignChecksSizeUM)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Mismatching sizes of RGXFW_ALIGN_CHECKS_INIT"
+                        " array between UM(%d) and FW(%d)",
+                        __func__,
+                        ui32AlignChecksSizeUM,
+                        *paui32FWAlignChecks));
+               eError = PVRSRV_ERROR_INVALID_ALIGNMENT;
+               goto return_;
+       }
+
+       for (i = 0; i < ui32AlignChecksSizeUM; i++)
+       {
+               if (aui32AlignChecksUM[i] != paui32FWAlignChecks[i])
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: size/offset mismatch in RGXFW_ALIGN_CHECKS_INIT[%d]"
+                                       " between UM(%d) and FW(%d)",
+                                       __func__, i, aui32AlignChecksUM[i], paui32FWAlignChecks[i]));
+                       eError = PVRSRV_ERROR_INVALID_ALIGNMENT;
+               }
+       }
+
+       if (eError == PVRSRV_ERROR_INVALID_ALIGNMENT)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Check for FW/KM structure"
+                               " alignment failed.", __func__));
+       }
+
+return_:
+
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWAlignChecksMemDesc);
+
+       return eError;
+}
+
+static
+PVRSRV_ERROR RGXAllocateFWMemoryRegion(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       IMG_DEVMEM_SIZE_T ui32Size,
+                                       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags,
+                                       const IMG_PCHAR pszText,
+                                       DEVMEM_MEMDESC **ppsMemDescPtr)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_DEVMEM_LOG2ALIGN_T uiLog2Align = OSGetPageShift();
+
+       uiMemAllocFlags = (uiMemAllocFlags |
+                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                          PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC) &
+                          RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       uiMemAllocFlags &= PVRSRV_MEMALLOCFLAGS_TDFWMASK;
+#endif
+
+       PVR_UNREFERENCED_PARAMETER(uiLog2Align);
+
+       PDUMPCOMMENT(psDeviceNode, "Allocate FW %s memory", pszText);
+
+       eError = DevmemFwAllocate(psDeviceNode->pvDevice,
+                                 ui32Size,
+                                 uiMemAllocFlags,
+                                 pszText,
+                                 ppsMemDescPtr);
+
+       return eError;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver
+
+ @Description
+
+ Validate the FW build options against KM driver build options (KM build options only)
+
+ Following check is redundant, because next check checks the same bits.
+ Redundancy occurs because if client-server are build-compatible and client-firmware are
+ build-compatible then server-firmware are build-compatible as well.
+
+ This check is left for clarity in error messages if any incompatibility occurs.
+
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(RGXFWIF_OSINIT *psFwOsInit)
+{
+#if !defined(NO_HARDWARE)
+       IMG_UINT32                      ui32BuildOptions, ui32BuildOptionsFWKMPart, ui32BuildOptionsMismatch;
+
+       if (psFwOsInit == NULL)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       ui32BuildOptions = (RGX_BUILD_OPTIONS_KM & RGX_BUILD_OPTIONS_MASK_FW);
+
+       ui32BuildOptionsFWKMPart = psFwOsInit->sRGXCompChecks.ui32BuildOptions & RGX_BUILD_OPTIONS_MASK_FW;
+
+       /* Check if the FW is missing support for any features required by the driver */
+       if (~ui32BuildOptionsFWKMPart & ui32BuildOptions)
+       {
+               ui32BuildOptionsMismatch = ui32BuildOptions ^ ui32BuildOptionsFWKMPart;
+#if !defined(PVRSRV_STRICT_COMPAT_CHECK)
+               /*Mask the debug flag option out as we do support combinations of debug vs release in um & km*/
+               ui32BuildOptionsMismatch &= ~OPTIONS_DEBUG_MASK;
+#endif
+               if ( (ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware and KM driver build options; "
+                                       "extra options present in the KM driver: (0x%x). Please check rgx_options.h",
+                                       ui32BuildOptions & ui32BuildOptionsMismatch ));
+                       return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+               }
+
+               if ( (ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch) != 0)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in Firmware-side and KM driver build options; "
+                                       "extra options present in Firmware: (0x%x). Please check rgx_options.h",
+                                       ui32BuildOptionsFWKMPart & ui32BuildOptionsMismatch ));
+                       return PVRSRV_ERROR_BUILD_OPTIONS_MISMATCH;
+               }
+               PVR_DPF((PVR_DBG_WARNING, "RGXDevInitCompatCheck: Firmware and KM driver build options differ."));
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware and KM driver build options match. [ OK ]"));
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver
+
+ @Description
+
+ Validate FW DDK version against driver DDK version
+
+ @Input psDevInfo - device info
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                                                                       RGXFWIF_OSINIT *psFwOsInit)
+{
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+       IMG_UINT32                      ui32DDKVersion;
+       PVRSRV_ERROR            eError;
+
+       ui32DDKVersion = PVRVERSION_PACK(PVRVERSION_MAJ, PVRVERSION_MIN);
+#endif
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW DDK version");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                               offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS, ui32DDKVersion),
+                                                                                               ui32DDKVersion,
+                                                                                               0xffffffff,
+                                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                               PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+               return eError;
+       }
+#endif
+
+#if !defined(NO_HARDWARE)
+       if (psFwOsInit == NULL)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       if (psFwOsInit->sRGXCompChecks.ui32DDKVersion != ui32DDKVersion)
+       {
+               PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible driver DDK version (%u.%u) / Firmware DDK revision (%u.%u).",
+                               PVRVERSION_MAJ, PVRVERSION_MIN,
+                               PVRVERSION_UNPACK_MAJ(psFwOsInit->sRGXCompChecks.ui32DDKVersion),
+                               PVRVERSION_UNPACK_MIN(psFwOsInit->sRGXCompChecks.ui32DDKVersion)));
+               eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+               PVR_DBG_BREAK;
+               return eError;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK version (%u.%u) and Firmware DDK revision (%u.%u) match. [ OK ]",
+                               PVRVERSION_MAJ, PVRVERSION_MIN,
+                               PVRVERSION_MAJ, PVRVERSION_MIN));
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver
+
+ @Description
+
+ Validate FW DDK build against driver DDK build
+
+ @Input psDevInfo - device info
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                                                                       RGXFWIF_OSINIT *psFwOsInit)
+{
+       PVRSRV_ERROR            eError=PVRSRV_OK;
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+       IMG_UINT32                      ui32DDKBuild;
+
+       ui32DDKBuild = PVRVERSION_BUILD;
+#endif
+
+#if defined(PDUMP) && defined(PVRSRV_STRICT_COMPAT_CHECK)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW DDK build");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                               offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS, ui32DDKBuild),
+                                                                                               ui32DDKBuild,
+                                                                                               0xffffffff,
+                                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                               PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+               return eError;
+       }
+#endif
+
+#if !defined(NO_HARDWARE)
+       if (psFwOsInit == NULL)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       if (psFwOsInit->sRGXCompChecks.ui32DDKBuild != ui32DDKBuild)
+       {
+               PVR_LOG(("(WARN) RGXDevInitCompatCheck: Different driver DDK build version (%d) / Firmware DDK build version (%d).",
+                               ui32DDKBuild, psFwOsInit->sRGXCompChecks.ui32DDKBuild));
+#if defined(PVRSRV_STRICT_COMPAT_CHECK)
+               eError = PVRSRV_ERROR_DDK_BUILD_MISMATCH;
+               PVR_DBG_BREAK;
+               return eError;
+#endif
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: driver DDK build version (%d) and Firmware DDK build version (%d) match. [ OK ]",
+                               ui32DDKBuild, psFwOsInit->sRGXCompChecks.ui32DDKBuild));
+       }
+#endif
+       return eError;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_BVNC_FWAgainstDriver
+
+ @Description
+
+ Validate FW BVNC against driver BVNC
+
+ @Input psDevInfo - device info
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_FWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                                                                       RGXFWIF_OSINIT *psFwOsInit)
+{
+#if !defined(NO_HARDWARE)
+       IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleBVNC;
+#endif
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+       RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sBVNC);
+       PVRSRV_ERROR                            eError;
+
+       sBVNC.ui64BVNC = rgx_bvnc_pack(psDevInfo->sDevFeatureCfg.ui32B,
+                                       psDevInfo->sDevFeatureCfg.ui32V,
+                                       psDevInfo->sDevFeatureCfg.ui32N,
+                                       psDevInfo->sDevFeatureCfg.ui32C);
+#endif
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (struct version)");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32LayoutVersion),
+                                                                                       sBVNC.ui32LayoutVersion,
+                                                                                       0xffffffff,
+                                                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                       PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+       }
+
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (BNC part - lower 32 bits)");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BVNC),
+                                                                                       (IMG_UINT32)sBVNC.ui64BVNC,
+                                                                                       0xffffffff,
+                                                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                       PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+       }
+
+       PDUMPCOMMENT(psDevInfo->psDeviceNode,
+                    "Compatibility check: KM driver and FW BVNC (BNC part - Higher 32 bits)");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS, sFWBVNC) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BVNC) +
+                                                                                       sizeof(IMG_UINT32),
+                                                                                       (IMG_UINT32)(sBVNC.ui64BVNC >> 32),
+                                                                                       0xffffffff,
+                                                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                       PDUMP_FLAGS_CONTINUOUS);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+       }
+#endif
+
+#if !defined(NO_HARDWARE)
+       if (psFwOsInit == NULL)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       RGX_BVNC_EQUAL(sBVNC, psFwOsInit->sRGXCompChecks.sFWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleBVNC);
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               bCompatibleAll = IMG_TRUE;
+       }
+
+       if (!bCompatibleAll)
+       {
+               if (!bCompatibleVersion)
+               {
+                       PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of driver (%u) and firmware (%u).",
+                                       __func__,
+                                       sBVNC.ui32LayoutVersion,
+                                       psFwOsInit->sRGXCompChecks.sFWBVNC.ui32LayoutVersion));
+                       eError = PVRSRV_ERROR_BVNC_MISMATCH;
+                       return eError;
+               }
+
+               if (!bCompatibleBVNC)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Mismatch in KM driver BVNC (%u.%u.%u.%u) and Firmware BVNC (%u.%u.%u.%u)",
+                                       RGX_BVNC_PACKED_EXTR_B(sBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_V(sBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_N(sBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_C(sBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_B(psFwOsInit->sRGXCompChecks.sFWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_V(psFwOsInit->sRGXCompChecks.sFWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_N(psFwOsInit->sRGXCompChecks.sFWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_C(psFwOsInit->sRGXCompChecks.sFWBVNC.ui64BVNC)));
+                       eError = PVRSRV_ERROR_BVNC_MISMATCH;
+                       return eError;
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Firmware BVNC and KM driver BNVC match. [ OK ]"));
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_BVNC_HWAgainstDriver
+
+ @Description
+
+ Validate HW BVNC against driver BVNC
+
+ @Input psDevInfo - device info
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_BVNC_HWAgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                                                                       RGXFWIF_OSINIT *psFwOsInit)
+{
+#if defined(PDUMP) || !defined(NO_HARDWARE)
+       IMG_UINT64 ui64MaskBVNC = RGX_BVNC_PACK_MASK_B |
+                                 RGX_BVNC_PACK_MASK_V |
+                                 RGX_BVNC_PACK_MASK_N |
+                                 RGX_BVNC_PACK_MASK_C;
+
+       PVRSRV_ERROR                            eError;
+       RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sSWBVNC);
+#endif
+
+#if defined(PDUMP)
+       PDUMP_FLAGS_T ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+
+#if !defined(NO_HARDWARE)
+       RGXFWIF_COMPCHECKS_BVNC_DECLARE_AND_INIT(sHWBVNC);
+       IMG_BOOL bCompatibleAll, bCompatibleVersion, bCompatibleBVNC;
+#endif
+
+       if (psDevInfo->bIgnoreHWReportedBVNC)
+       {
+               PVR_LOG(("BVNC compatibility checks between driver and HW are disabled (AppHint override)"));
+               return PVRSRV_OK;
+       }
+
+#if defined(PDUMP) || !defined(NO_HARDWARE)
+#if defined(COMPAT_BVNC_MASK_B)
+       ui64MaskBNC &= ~RGX_BVNC_PACK_MASK_B;
+#endif
+#if defined(COMPAT_BVNC_MASK_V)
+       ui64MaskBVNC &= ~RGX_BVNC_PACK_MASK_V;
+#endif
+#if defined(COMPAT_BVNC_MASK_N)
+       ui64MaskBVNC &= ~RGX_BVNC_PACK_MASK_N;
+#endif
+#if defined(COMPAT_BVNC_MASK_C)
+       ui64MaskBVNC &= ~RGX_BVNC_PACK_MASK_C;
+#endif
+
+       sSWBVNC.ui64BVNC = rgx_bvnc_pack(psDevInfo->sDevFeatureCfg.ui32B,
+                                                                       psDevInfo->sDevFeatureCfg.ui32V,
+                                                                       psDevInfo->sDevFeatureCfg.ui32N,
+                                                                       psDevInfo->sDevFeatureCfg.ui32C);
+
+
+
+       if (ui64MaskBVNC != (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_V | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C))
+       {
+               PVR_LOG(("Compatibility checks: Ignoring fields: '%s%s%s%s' of HW BVNC.",
+                               ((!(ui64MaskBVNC & RGX_BVNC_PACK_MASK_B))?("B"):("")),
+                               ((!(ui64MaskBVNC & RGX_BVNC_PACK_MASK_V))?("V"):("")),
+                               ((!(ui64MaskBVNC & RGX_BVNC_PACK_MASK_N))?("N"):("")),
+                               ((!(ui64MaskBVNC & RGX_BVNC_PACK_MASK_C))?("C"):(""))));
+       }
+#endif
+
+#if defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Compatibility check: Layout version of compchecks struct");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+                                                                                       offsetof(RGXFWIF_COMPCHECKS_BVNC, ui32LayoutVersion),
+                                                                                       sSWBVNC.ui32LayoutVersion,
+                                                                                       0xffffffff,
+                                                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                       ui32PDumpFlags);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+               return eError;
+       }
+
+       PDUMPCOM(psDevInfo->psDeviceNode, ui32PDumpFlags, "BVNC compatibility check started");
+       if (ui64MaskBVNC & (RGX_BVNC_PACK_MASK_B | RGX_BVNC_PACK_MASK_N | RGX_BVNC_PACK_MASK_C))
+       {
+               PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+               PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW BNC and FW BNC (Lower 32 bits)");
+               eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                               offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BVNC),
+                                                                                               (IMG_UINT32)sSWBVNC.ui64BVNC ,
+                                                                                               (IMG_UINT32)(ui64MaskBVNC & ~RGX_BVNC_PACK_MASK_V),
+                                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                               ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+                       return eError;
+               }
+
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW BNC and FW BNC (Higher 32 bits)");
+               eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                                                                               offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+                                                                                               offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BVNC) +
+                                                                                               sizeof(IMG_UINT32),
+                                                                                               (IMG_UINT32)(sSWBVNC.ui64BVNC >> 32),
+                                                                                               (IMG_UINT32)((ui64MaskBVNC & ~RGX_BVNC_PACK_MASK_V) >> 32),
+                                                                                               PDUMP_POLL_OPERATOR_EQUAL,
+                                                                                               ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+                       return eError;
+               }
+
+               PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWBNC_CHECK", ui32PDumpFlags);
+       }
+       if (ui64MaskBVNC & RGX_BVNC_PACK_MASK_V)
+       {
+               PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
+               PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
+
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                                     "Compatibility check: HW V and FW V");
+               eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                       offsetof(RGXFWIF_COMPCHECKS, sHWBVNC) +
+                                       offsetof(RGXFWIF_COMPCHECKS_BVNC, ui64BVNC) +
+                                       ((RGX_BVNC_PACK_SHIFT_V >= 32) ? sizeof(IMG_UINT32) : 0),
+                                       (IMG_UINT32)(sSWBVNC.ui64BVNC >> ((RGX_BVNC_PACK_SHIFT_V >= 32) ? 32 : 0)),
+                                       RGX_BVNC_PACK_MASK_V >> ((RGX_BVNC_PACK_SHIFT_V >= 32) ? 32 : 0),
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+                       return eError;
+               }
+               PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWV_CHECK", ui32PDumpFlags);
+       }
+       PDUMPCOM(psDevInfo->psDeviceNode, ui32PDumpFlags, "BVNC compatibility check finished");
+#endif
+
+#if !defined(NO_HARDWARE)
+       if (psFwOsInit == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       sHWBVNC = psFwOsInit->sRGXCompChecks.sHWBVNC;
+
+       sHWBVNC.ui64BVNC &= ui64MaskBVNC;
+       sSWBVNC.ui64BVNC &= ui64MaskBVNC;
+
+       RGX_BVNC_EQUAL(sSWBVNC, sHWBVNC, bCompatibleAll, bCompatibleVersion, bCompatibleBVNC);
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               bCompatibleAll = IMG_TRUE;
+       }
+
+       if (!bCompatibleAll)
+       {
+               if (!bCompatibleVersion)
+               {
+                       PVR_LOG(("(FAIL) %s: Incompatible compatibility struct version of HW (%d) and FW (%d).",
+                                       __func__,
+                                       sHWBVNC.ui32LayoutVersion,
+                                       sSWBVNC.ui32LayoutVersion));
+                       eError = PVRSRV_ERROR_BVNC_MISMATCH;
+                       return eError;
+               }
+
+               if (!bCompatibleBVNC)
+               {
+                       PVR_LOG(("(FAIL) RGXDevInitCompatCheck: Incompatible HW BVNC (%d.%d.%d.%d) and FW BVNC (%d.%d.%d.%d).",
+                                       RGX_BVNC_PACKED_EXTR_B(sHWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_V(sHWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_N(sHWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_C(sHWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_B(sSWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_V(sSWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_N(sSWBVNC.ui64BVNC),
+                                       RGX_BVNC_PACKED_EXTR_C(sSWBVNC.ui64BVNC)));
+                       eError = PVRSRV_ERROR_BVNC_MISMATCH;
+                       return eError;
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: HW BVNC (%d.%d.%d.%d) and FW BVNC (%d.%d.%d.%d) match. [ OK ]",
+                               RGX_BVNC_PACKED_EXTR_B(sHWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_V(sHWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_N(sHWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_C(sHWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_B(sSWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_V(sSWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_N(sSWBVNC.ui64BVNC),
+                               RGX_BVNC_PACKED_EXTR_C(sSWBVNC.ui64BVNC)));
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function     RGXDevInitCompatCheck_METACoreVersion_AgainstDriver
+
+ @Description
+
+ Validate HW META version against driver META version
+
+ @Input psDevInfo - device info
+ @Input psFwOsInit - FW init data
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                       RGXFWIF_OSINIT *psFwOsInit)
+{
+#if defined(PDUMP)||(!defined(NO_HARDWARE))
+       PVRSRV_ERROR            eError;
+#endif
+
+#if defined(PDUMP)
+       PDUMP_FLAGS_T ui32PDumpFlags = PDUMP_FLAGS_CONTINUOUS;
+#endif
+
+       IMG_UINT32      ui32FWCoreIDValue = 0;
+       IMG_CHAR *pcRGXFW_PROCESSOR = NULL;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               switch (RGX_GET_FEATURE_VALUE(psDevInfo, META))
+               {
+               case MTP218: ui32FWCoreIDValue = RGX_CR_META_MTP218_CORE_ID_VALUE; break;
+               case MTP219: ui32FWCoreIDValue = RGX_CR_META_MTP219_CORE_ID_VALUE; break;
+               case LTP218: ui32FWCoreIDValue = RGX_CR_META_LTP218_CORE_ID_VALUE; break;
+               case LTP217: ui32FWCoreIDValue = RGX_CR_META_LTP217_CORE_ID_VALUE; break;
+               default:
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Undefined FW_CORE_ID_VALUE", __func__));
+                       PVR_ASSERT(0);
+               }
+               pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
+       }
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               ui32FWCoreIDValue = RGXRISCVFW_CORE_ID_VALUE;
+               pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_RISCV;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Undefined FW_CORE_ID_VALUE", __func__));
+               PVR_ASSERT(0);
+       }
+
+#if defined(PDUMP)
+       PDUMPIF(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+       PDUMPELSE(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, ui32PDumpFlags,
+                             "Compatibility check: KM driver and HW FW Processor version");
+       eError = DevmemPDumpDevmemCheck32(psDevInfo->psRGXFWIfOsInitMemDesc,
+                                       offsetof(RGXFWIF_OSINIT, sRGXCompChecks) +
+                                       offsetof(RGXFWIF_COMPCHECKS, ui32FWProcessorVersion),
+                                       ui32FWCoreIDValue,
+                                       0xffffffff,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       ui32PDumpFlags);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDevInitCompatCheck: problem pdumping POL for psRGXFWIfOsInitMemDesc (%d)", eError));
+               return eError;
+       }
+       PDUMPFI(psDevInfo->psDeviceNode, "DISABLE_HWMETA_CHECK", ui32PDumpFlags);
+#endif
+
+#if !defined(NO_HARDWARE)
+       if (psFwOsInit == NULL)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       if (psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion != ui32FWCoreIDValue)
+       {
+               PVR_LOG(("RGXDevInitCompatCheck: Incompatible driver %s version (%d) / HW %s version (%d).",
+                                pcRGXFW_PROCESSOR,
+                                ui32FWCoreIDValue,
+                                pcRGXFW_PROCESSOR,
+                                psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
+               eError = PVRSRV_ERROR_FWPROCESSOR_MISMATCH;
+               PVR_DBG_BREAK;
+               return eError;
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXDevInitCompatCheck: Compatible driver %s version (%d) / HW %s version (%d) [OK].",
+                                pcRGXFW_PROCESSOR,
+                                ui32FWCoreIDValue,
+                                pcRGXFW_PROCESSOR,
+                                psFwOsInit->sRGXCompChecks.ui32FWProcessorVersion));
+       }
+#endif
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDevInitCompatCheck
+
+ @Description
+
+ Check compatibility of host driver and firmware (DDK and build options)
+ for RGX devices at services/device initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR - depending on mismatch found
+
+ ******************************************************************************/
+static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR            eError;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+#if !defined(NO_HARDWARE)
+       IMG_UINT32                      ui32RegValue;
+       IMG_UINT8                       ui8FwOsCount;
+       IMG_UINT32                      ui32FwTimeout = MAX_HW_TIME_US;
+
+       LOOP_UNTIL_TIMEOUT(ui32FwTimeout)
+       {
+               if (*((volatile IMG_BOOL *)&psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated))
+               {
+                       /* No need to wait if the FW has already updated the values */
+                       break;
+               }
+               OSWaitus(ui32FwTimeout/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       ui32RegValue = 0;
+
+       if ((!PVRSRV_VZ_MODE_IS(GUEST)) &&
+               RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               eError = RGXReadFWModuleAddr(psDevInfo, META_CR_T0ENABLE_OFFSET, &ui32RegValue);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_LOG(("%s: Reading RGX META register failed. Is the GPU correctly powered up? (%u)",
+                                       __func__, eError));
+                       goto chk_exit;
+               }
+
+               if (!(ui32RegValue & META_CR_TXENABLE_ENABLE_BIT))
+               {
+                       eError = PVRSRV_ERROR_META_THREAD0_NOT_ENABLED;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: RGX META is not running. Is the GPU correctly powered up? %d (%u)",
+                                       __func__, psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated, eError));
+                       goto chk_exit;
+               }
+       }
+
+       if (!*((volatile IMG_BOOL *)&psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated))
+       {
+               eError = PVRSRV_ERROR_TIMEOUT;
+               PVR_DPF((PVR_DBG_ERROR, "%s: GPU Firmware not responding: failed to supply compatibility info (%u)",
+                               __func__, eError));
+               if (PVRSRV_VZ_MODE_IS(GUEST))
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Potential causes: firmware not initialised or the current Guest driver's "
+                                                                       "OsConfig initialisation data was not accepted by the firmware", __func__));
+               }
+               goto chk_exit;
+       }
+
+       ui8FwOsCount = psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.sInitOptions.ui8OsCountSupport;
+       if ((PVRSRV_VZ_MODE_IS(NATIVE) && (ui8FwOsCount > 1)) ||
+               (PVRSRV_VZ_MODE_IS(HOST) && (ui8FwOsCount != RGX_NUM_OS_SUPPORTED)))
+       {
+               PVR_DPF((PVR_DBG_WARNING, "%s: Mismatch between the number of Operating Systems supported by KM driver (%d) and FW (%d)",
+                               __func__, (PVRSRV_VZ_MODE_IS(NATIVE)) ? (1) : (RGX_NUM_OS_SUPPORTED), ui8FwOsCount));
+       }
+#endif /* defined(NO_HARDWARE) */
+
+       eError = RGXDevInitCompatCheck_KMBuildOptions_FWAgainstDriver(psDevInfo->psRGXFWIfOsInit);
+       if (eError != PVRSRV_OK)
+       {
+               goto chk_exit;
+       }
+
+       eError = RGXDevInitCompatCheck_DDKVersion_FWAgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
+       if (eError != PVRSRV_OK)
+       {
+               goto chk_exit;
+       }
+
+       eError = RGXDevInitCompatCheck_DDKBuild_FWAgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
+       if (eError != PVRSRV_OK)
+       {
+               goto chk_exit;
+       }
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = RGXDevInitCompatCheck_BVNC_FWAgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
+               if (eError != PVRSRV_OK)
+               {
+                       goto chk_exit;
+               }
+
+               eError = RGXDevInitCompatCheck_BVNC_HWAgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
+               if (eError != PVRSRV_OK)
+               {
+                       goto chk_exit;
+               }
+       }
+
+       eError = RGXDevInitCompatCheck_FWProcessorVersion_AgainstDriver(psDevInfo, psDevInfo->psRGXFWIfOsInit);
+       if (eError != PVRSRV_OK)
+       {
+               goto chk_exit;
+       }
+
+       eError = PVRSRV_OK;
+chk_exit:
+
+       return eError;
+}
+
+static void _RGXSoftResetToggle(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                IMG_UINT64  ui64ResetValue,
+                                IMG_UINT64  ui64SPUResetValue)
+{
+       OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET, ui64ResetValue);
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, POWER_ISLAND_VERSION) == 1)
+       {
+               OSWriteHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET_SPU, ui64SPUResetValue);
+       }
+
+       /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+       (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET);
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, POWER_ISLAND_VERSION) == 1)
+       {
+               (void) OSReadHWReg64(psDevInfo->pvRegsBaseKM, RGX_CR_SOFT_RESET_SPU);
+       }
+}
+
+/**************************************************************************/ /*!
+@Function       RGXSoftReset
+@Description    Resets some modules of the RGX device
+@Input          psDeviceNode           Device node
+@Input          ui64ResetValue  A mask for which each bit set corresponds
+                                to a module to reset (via the SOFT_RESET
+                                register).
+@Input          ui64SPUResetValue A mask for which each bit set corresponds
+                                to a module to reset (via the SOFT_RESET_SPU
+                                register).
+@Return         PVRSRV_ERROR
+*/ /***************************************************************************/
+static PVRSRV_ERROR RGXSoftReset(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 IMG_UINT64  ui64ResetValue,
+                                 IMG_UINT64  ui64SPUResetValue)
+{
+       PVRSRV_RGXDEV_INFO        *psDevInfo;
+
+       PVR_ASSERT(psDeviceNode != NULL);
+       PVR_ASSERT(psDeviceNode->pvDevice != NULL);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       if (((ui64ResetValue & RGX_CR_SOFT_RESET_MASKFULL) != ui64ResetValue)
+               || (ui64SPUResetValue & RGX_CR_SOFT_RESET_SPU_MASKFULL) != ui64SPUResetValue)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       /* The device info */
+       psDevInfo = psDeviceNode->pvDevice;
+
+       /* Set in soft-reset */
+       _RGXSoftResetToggle(psDevInfo, ui64ResetValue, ui64SPUResetValue);
+
+       /* Take the modules out of reset... */
+       _RGXSoftResetToggle(psDevInfo, 0, 0);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
+                                  IMG_DEVMEM_SIZE_T    uiFWCodeLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWDataLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememCodeLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememDataLen)
+{
+       PVRSRV_MEMALLOCFLAGS_T uiMemAllocFlags;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR        eError;
+
+       /*
+        * Set up Allocation for FW code section
+        */
+       uiMemAllocFlags = PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                         PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                         PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                         PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                         PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                         PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                         PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                         PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                         PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CODE);
+
+       eError = RGXAllocateFWMemoryRegion(psDeviceNode,
+                                          uiFWCodeLen,
+                                          uiMemAllocFlags,
+                                          "FwCodeRegion",
+                                          &psDevInfo->psRGXFWCodeMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Failed to allocate fw code mem (%u)",
+                        eError));
+               goto failFWCodeMemDescAlloc;
+       }
+
+       eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc,
+                                         &psDevInfo->sFWCodeDevVAddrBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Failed to acquire devVAddr for fw code mem (%u)",
+                        eError));
+               goto failFWCodeMemDescAqDevVirt;
+       }
+
+       /*
+       * The FW code must be the first allocation in the firmware heap, otherwise
+       * the bootloader will not work (the FW will not be able to find the bootloader).
+       */
+       PVR_ASSERT(psDevInfo->sFWCodeDevVAddrBase.uiAddr == RGX_FIRMWARE_MAIN_HEAP_BASE);
+
+       /*
+        * Set up Allocation for FW data section
+        */
+       uiMemAllocFlags = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                          PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                          PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                          PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                          PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                          PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                          PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                                          PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                          PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                          PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                          PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_PRIV_DATA)) &
+                                          RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+
+       eError = RGXAllocateFWMemoryRegion(psDeviceNode,
+                                          uiFWDataLen,
+                                          uiMemAllocFlags,
+                                          "FwDataRegion",
+                                          &psDevInfo->psRGXFWDataMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Failed to allocate fw data mem (%u)",
+                        eError));
+               goto failFWDataMemDescAlloc;
+       }
+
+       eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWDataMemDesc,
+                                         &psDevInfo->sFWDataDevVAddrBase);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Failed to acquire devVAddr for fw data mem (%u)",
+                        eError));
+               goto failFWDataMemDescAqDevVirt;
+       }
+
+       if (uiFWCorememCodeLen != 0)
+       {
+               /*
+                * Set up Allocation for FW coremem code section
+                */
+               uiMemAllocFlags = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                  PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                                  PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                  PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                  PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                  PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                                                  PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                  PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                                  PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                  PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_CODE)) &
+                                                  RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+
+               eError = RGXAllocateFWMemoryRegion(psDeviceNode,
+                                                  uiFWCorememCodeLen,
+                                                  uiMemAllocFlags,
+                                                  "FwCorememCodeRegion",
+                                                  &psDevInfo->psRGXFWCorememCodeMemDesc);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "Failed to allocate fw coremem code mem, size: %"  IMG_INT64_FMTSPECd ", flags: %" PVRSRV_MEMALLOCFLAGS_FMTSPEC " (%u)",
+                                uiFWCorememCodeLen, uiMemAllocFlags, eError));
+                       goto failFWCorememMemDescAlloc;
+               }
+
+               eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc,
+                                                 &psDevInfo->sFWCorememCodeDevVAddrBase);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "Failed to acquire devVAddr for fw coremem mem code (%u)",
+                                eError));
+                       goto failFWCorememCodeMemDescAqDevVirt;
+               }
+
+               eError = RGXSetFirmwareAddress(&psDevInfo->sFWCorememCodeFWAddr,
+                                     psDevInfo->psRGXFWCorememCodeMemDesc,
+                                     0, RFW_FWADDR_NOREF_FLAG);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", failFWCorememCodeMemDescFwAddr);
+       }
+       else
+       {
+               psDevInfo->sFWCorememCodeDevVAddrBase.uiAddr = 0;
+               psDevInfo->sFWCorememCodeFWAddr.ui32Addr = 0;
+       }
+
+       if (uiFWCorememDataLen != 0)
+       {
+               /*
+                * Set up Allocation for FW coremem data section
+                */
+               uiMemAllocFlags = (PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                               PVRSRV_MEMALLOCFLAG_GPU_READABLE  |
+                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                               PVRSRV_MEMALLOCFLAG_CPU_READABLE  |
+                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                               PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_PRIV_DATA)) &
+                               RGX_AUTOVZ_KEEP_FW_DATA_MASK(psDeviceNode->bAutoVzFwIsUp);
+
+               eError = RGXAllocateFWMemoryRegion(psDeviceNode,
+                               uiFWCorememDataLen,
+                               uiMemAllocFlags,
+                               "FwCorememDataRegion",
+                               &psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "Failed to allocate fw coremem data mem, "
+                                "size: %"  IMG_INT64_FMTSPECd ", flags: %" PVRSRV_MEMALLOCFLAGS_FMTSPEC " (%u)",
+                                uiFWCorememDataLen,
+                                uiMemAllocFlags,
+                                eError));
+                       goto failFWCorememDataMemDescAlloc;
+               }
+
+               eError = DevmemAcquireDevVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+                               &psDevInfo->sFWCorememDataStoreDevVAddrBase);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "Failed to acquire devVAddr for fw coremem mem data (%u)",
+                                eError));
+                       goto failFWCorememDataMemDescAqDevVirt;
+               }
+
+               eError = RGXSetFirmwareAddress(&psDevInfo->sFWCorememDataStoreFWAddr,
+                               psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+                               0, RFW_FWADDR_NOREF_FLAG);
+               PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", failFWCorememDataMemDescFwAddr);
+       }
+       else
+       {
+               psDevInfo->sFWCorememDataStoreDevVAddrBase.uiAddr = 0;
+               psDevInfo->sFWCorememDataStoreFWAddr.ui32Addr = 0;
+       }
+
+       return PVRSRV_OK;
+
+failFWCorememDataMemDescFwAddr:
+failFWCorememDataMemDescAqDevVirt:
+       if (uiFWCorememDataLen != 0)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+               psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
+       }
+failFWCorememDataMemDescAlloc:
+failFWCorememCodeMemDescFwAddr:
+failFWCorememCodeMemDescAqDevVirt:
+       if (uiFWCorememCodeLen != 0)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCorememCodeMemDesc);
+               psDevInfo->psRGXFWCorememCodeMemDesc = NULL;
+       }
+failFWCorememMemDescAlloc:
+failFWDataMemDescAqDevVirt:
+       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWDataMemDesc);
+       psDevInfo->psRGXFWDataMemDesc = NULL;
+failFWDataMemDescAlloc:
+failFWCodeMemDescAqDevVirt:
+       DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCodeMemDesc);
+       psDevInfo->psRGXFWCodeMemDesc = NULL;
+failFWCodeMemDescAlloc:
+       return eError;
+}
+
+/*
+       AppHint parameter interface
+ */
+static
+PVRSRV_ERROR RGXFWTraceQueryFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
+{
+       PVRSRV_ERROR eResult;
+
+       eResult = PVRSRVRGXFWDebugQueryFWLogKM(NULL, psDeviceNode, pui32Value);
+       *pui32Value &= RGXFWIF_LOG_TYPE_GROUP_MASK;
+       return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceQueryLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const void *psPrivate,
+                                   IMG_UINT32 *pui32Value)
+{
+       PVRSRV_ERROR eResult;
+
+       eResult = PVRSRVRGXFWDebugQueryFWLogKM(NULL, psDeviceNode, pui32Value);
+       if (PVRSRV_OK == eResult)
+       {
+               if (*pui32Value & RGXFWIF_LOG_TYPE_TRACE)
+               {
+                       *pui32Value = 0; /* Trace */
+               }
+               else
+               {
+                       *pui32Value = 1; /* TBI */
+               }
+       }
+       return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceSetFilter(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 const void *psPrivate,
+                                 IMG_UINT32 ui32Value)
+{
+       PVRSRV_ERROR eResult;
+       IMG_UINT32 ui32RGXFWLogType;
+
+       eResult = RGXFWTraceQueryLogType(psDeviceNode, NULL, &ui32RGXFWLogType);
+       if (PVRSRV_OK == eResult)
+       {
+               if (0 == ui32RGXFWLogType)
+               {
+                       BITMASK_SET(ui32Value, RGXFWIF_LOG_TYPE_TRACE);
+               }
+               eResult = PVRSRVRGXFWDebugSetFWLogKM(NULL, psDeviceNode, ui32Value);
+       }
+       return eResult;
+}
+
+static
+PVRSRV_ERROR RGXFWTraceSetLogType(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  const void *psPrivate,
+                                  IMG_UINT32 ui32Value)
+{
+       PVRSRV_ERROR eResult;
+       IMG_UINT32 ui32RGXFWLogType = ui32Value;
+
+       eResult = RGXFWTraceQueryFilter(psDeviceNode, NULL, &ui32RGXFWLogType);
+       if (PVRSRV_OK != eResult)
+       {
+               return eResult;
+       }
+
+       /* 0 - trace, 1 - tbi */
+       if (0 == ui32Value)
+       {
+               BITMASK_SET(ui32RGXFWLogType, RGXFWIF_LOG_TYPE_TRACE);
+       }
+#if defined(SUPPORT_TBI_INTERFACE)
+       else if (1 == ui32Value)
+       {
+               BITMASK_UNSET(ui32RGXFWLogType, RGXFWIF_LOG_TYPE_TRACE);
+       }
+#endif
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Invalid parameter %u specified to set FW log type AppHint.",
+                        __func__, ui32Value));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eResult = PVRSRVRGXFWDebugSetFWLogKM(NULL, psDeviceNode, ui32RGXFWLogType);
+       return eResult;
+}
+
+#if defined(DEBUG)
+static
+PVRSRV_ERROR RGXQueryFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                       const void *psPrivate,
+                                                                       IMG_BOOL *pbValue)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+
+       *pbValue = (PVRSRV_MEMALLOCFLAG_POISON_ON_FREE == psDevInfo->uiFWPoisonOnFreeFlag)
+               ? IMG_TRUE
+               : IMG_FALSE;
+       return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR RGXSetFWPoisonOnFree(const PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                       const void *psPrivate,
+                                                                       IMG_BOOL bValue)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *) psDeviceNode->pvDevice;
+       psDevInfo->uiFWPoisonOnFreeFlag = bValue
+                       ? PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
+                       : 0ULL;
+
+       return PVRSRV_OK;
+}
+#endif
+
+/*
+ * RGXInitFirmware
+ */
+PVRSRV_ERROR
+RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                IMG_BOOL                 bEnableSignatureChecks,
+                IMG_UINT32               ui32SignatureChecksBufSize,
+                IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                IMG_UINT64               ui64HWPerfFilter,
+                IMG_UINT32               ui32ConfigFlags,
+                IMG_UINT32               ui32LogType,
+                IMG_UINT32               ui32FilterFlags,
+                IMG_UINT32               ui32JonesDisableMask,
+                IMG_UINT32               ui32HWRDebugDumpLimit,
+                IMG_UINT32                              ui32RenderKillingCtl,
+                IMG_UINT32                              ui32CDMTDMKillingCtl,
+                IMG_UINT32                              *pui32TPUTrilinearFracMask,
+                IMG_UINT32                              *pui32USRMNumRegions,
+                IMG_UINT64                              *pui64UVBRMNumRegions,
+                IMG_UINT32               ui32HWPerfCountersDataSize,
+                RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
+                FW_PERF_CONF             eFirmwarePerf,
+                IMG_UINT32               ui32KCCBSizeLog2,
+                IMG_UINT32               ui32ConfigFlagsExt,
+                IMG_UINT32               ui32AvailablePowUnitsMask,
+                IMG_UINT32               ui32AvailableRACMask,
+                IMG_UINT32               ui32FwOsCfgFlags)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+#if defined(DEBUG)
+       IMG_BOOL bEnableFWPoisonOnFree = IMG_FALSE;
+#endif
+
+       eError = RGXSetupFirmware(psDeviceNode,
+                                 bEnableSignatureChecks,
+                                 ui32SignatureChecksBufSize,
+                                 ui32HWPerfFWBufSizeKB,
+                                 ui64HWPerfFilter,
+                                 ui32ConfigFlags,
+                                 ui32ConfigFlagsExt,
+                                 ui32FwOsCfgFlags,
+                                 ui32LogType,
+                                 ui32FilterFlags,
+                                 ui32JonesDisableMask,
+                                 ui32HWRDebugDumpLimit,
+                                 ui32HWPerfCountersDataSize,
+                                 ui32RenderKillingCtl,
+                                 ui32CDMTDMKillingCtl,
+                                 pui32TPUTrilinearFracMask,
+                                 pui32USRMNumRegions,
+                                 pui64UVBRMNumRegions,
+                                 eRGXRDPowerIslandingConf,
+                                 eFirmwarePerf,
+                                 ui32KCCBSizeLog2,
+                                 ui32AvailablePowUnitsMask,
+                                                         ui32AvailableRACMask);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRGXInitFirmwareKM: RGXSetupFirmware failed (%u)",
+                        eError));
+               goto failed_init_firmware;
+       }
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_EnableLogGroup,
+                                                   RGXFWTraceQueryFilter,
+                                                   RGXFWTraceSetFilter,
+                                                   psDeviceNode,
+                                                   NULL);
+               PVRSRVAppHintRegisterHandlersUINT32(APPHINT_ID_FirmwareLogType,
+                                                   RGXFWTraceQueryLogType,
+                                                   RGXFWTraceSetLogType,
+                                                   psDeviceNode,
+                                                   NULL);
+       }
+
+#if defined(DEBUG)
+       bEnableFWPoisonOnFree = PVRSRV_APPHINT_ENABLEFWPOISONONFREE;
+
+       PVRSRVAppHintRegisterHandlersBOOL(APPHINT_ID_EnableFWPoisonOnFree,
+                                          RGXQueryFWPoisonOnFree,
+                                          RGXSetFWPoisonOnFree,
+                                          psDeviceNode,
+                                          NULL);
+
+       psDevInfo->uiFWPoisonOnFreeFlag = bEnableFWPoisonOnFree
+                       ? PVRSRV_MEMALLOCFLAG_POISON_ON_FREE
+                       : 0ULL;
+#else
+       psDevInfo->uiFWPoisonOnFreeFlag = 0ULL;
+#endif
+
+       return PVRSRV_OK;
+
+failed_init_firmware:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+/* See device.h for function declaration */
+static PVRSRV_ERROR RGXAllocUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                        DEVMEM_MEMDESC **psMemDesc,
+                                                                        IMG_UINT32 *puiSyncPrimVAddr,
+                                                                        IMG_UINT32 *puiSyncPrimBlockSize)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_ERROR eError;
+       RGXFWIF_DEV_VIRTADDR pFirmwareAddr;
+       IMG_DEVMEM_SIZE_T uiUFOBlockSize = sizeof(IMG_UINT32);
+       IMG_DEVMEM_ALIGN_T ui32UFOBlockAlign = sizeof(IMG_UINT32);
+       IMG_UINT32 ui32CoherencyFlag = 0;
+
+       psDevInfo = psDeviceNode->pvDevice;
+
+       /* Size and align are 'expanded' because we request an Exportalign allocation */
+       eError = DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareMainHeap),
+                                                                               &uiUFOBlockSize,
+                                                                               &ui32UFOBlockAlign);
+
+       if (eError != PVRSRV_OK)
+       {
+               goto e0;
+       }
+
+       if (PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig) &&
+               PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig))
+       {
+               ui32CoherencyFlag = PVRSRV_MEMALLOCFLAG_CACHE_COHERENT;
+       }
+       else
+       {
+               ui32CoherencyFlag = PVRSRV_MEMALLOCFLAG_UNCACHED;
+       }
+
+       eError = DevmemFwAllocateExportable(psDeviceNode,
+                                                                               uiUFOBlockSize,
+                                                                               ui32UFOBlockAlign,
+                                                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN) |
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                                               ui32CoherencyFlag,
+                                                                               "FwExUFOBlock",
+                                                                               psMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               goto e0;
+       }
+
+       eError = RGXSetFirmwareAddress(&pFirmwareAddr, *psMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_GOTO_IF_ERROR(eError, e1);
+
+       *puiSyncPrimVAddr = pFirmwareAddr.ui32Addr;
+       *puiSyncPrimBlockSize = TRUNCATE_64BITS_TO_32BITS(uiUFOBlockSize);
+
+       return PVRSRV_OK;
+
+e1:
+       DevmemFwUnmapAndFree(psDevInfo, *psMemDesc);
+e0:
+       return eError;
+}
+
+/* See device.h for function declaration */
+static void RGXFreeUFOBlock(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       DEVMEM_MEMDESC *psMemDesc)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       /*
+               If the system has snooping of the device cache then the UFO block
+               might be in the cache so we need to flush it out before freeing
+               the memory
+
+               When the device is being shutdown/destroyed we don't care anymore.
+               Several necessary data structures to issue a flush were destroyed
+               already.
+        */
+       if (PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig) &&
+               psDeviceNode->eDevState != PVRSRV_DEVICE_STATE_DEINIT)
+       {
+               RGXFWIF_KCCB_CMD sFlushInvalCmd;
+               PVRSRV_ERROR eError;
+               IMG_UINT32 ui32kCCBCommandSlot;
+
+               /* Schedule the SLC flush command ... */
+#if defined(PDUMP)
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "Submit SLC flush and invalidate");
+#endif
+               sFlushInvalCmd.eCmdType = RGXFWIF_KCCB_CMD_SLCFLUSHINVAL;
+               sFlushInvalCmd.uCmdData.sSLCFlushInvalData.ui64Size = 0;
+               sFlushInvalCmd.uCmdData.sSLCFlushInvalData.ui64Address = 0;
+               sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bInval = IMG_TRUE;
+               sFlushInvalCmd.uCmdData.sSLCFlushInvalData.bDMContext = IMG_FALSE;
+               sFlushInvalCmd.uCmdData.sSLCFlushInvalData.psContext.ui32Addr = 0;
+
+               eError = RGXSendCommandWithPowLockAndGetKCCBSlot(psDevInfo,
+                                                                                                                &sFlushInvalCmd,
+                                                                                                                PDUMP_FLAGS_CONTINUOUS,
+                                                                                                                &ui32kCCBCommandSlot);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to schedule SLC flush command with error (%u)",
+                                __func__,
+                                eError));
+               }
+               else
+               {
+                       /* Wait for the SLC flush to complete */
+                       eError = RGXWaitForKCCBSlotUpdate(psDevInfo, ui32kCCBCommandSlot, PDUMP_FLAGS_CONTINUOUS);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: SLC flush and invalidate aborted with error (%u)",
+                                        __func__,
+                                        eError));
+                       }
+                       else if (unlikely(psDevInfo->pui32KernelCCBRtnSlots[ui32kCCBCommandSlot] &
+                                                         RGXFWIF_KCCB_RTN_SLOT_POLL_FAILURE))
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: FW poll on a HW operation failed", __func__));
+                       }
+               }
+       }
+
+       RGXUnsetFirmwareAddress(psMemDesc);
+       DevmemFwUnmapAndFree(psDevInfo, psMemDesc);
+}
+
+static void DevPart2DeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+
+       psDevInfo->bDevInit2Done = IMG_FALSE;
+
+       if ((psDevInfo->hTQUSCSharedMem != NULL) &&
+           (psDevInfo->hTQCLISharedMem != NULL))
+       {
+               PVRSRVTQUnloadShaders(psDeviceNode);
+       }
+
+#if !defined(NO_HARDWARE)
+       if (psDevInfo->pvLISRData != NULL)
+       {
+               (void) SysUninstallDeviceLISR(psDevInfo->pvLISRData);
+       }
+       if (psDevInfo->pvMISRData != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->pvMISRData);
+       }
+       if (psDevInfo->hProcessQueuesMISR != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->hProcessQueuesMISR);
+       }
+       if (psDevInfo->pvAPMISRData != NULL)
+       {
+               (void) OSUninstallMISR(psDevInfo->pvAPMISRData);
+       }
+       if (psDeviceNode->hCmdCompNotify != NULL)
+       {
+               PVRSRVUnregisterCmdCompleteNotify(psDeviceNode->hCmdCompNotify);
+               psDeviceNode->hCmdCompNotify = NULL;
+       }
+#endif /* !NO_HARDWARE */
+
+       /* Remove the device from the power manager */
+       PVRSRVRemovePowerDevice(psDeviceNode);
+
+       psDevInfo->pfnGetGpuUtilStats = NULL;
+       if (psDevInfo->hGPUUtilLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hGPUUtilLock);
+       }
+
+       if ((GetInfoPageDebugFlagsKM() & DEBUG_FEATURE_PAGE_FAULT_DEBUG_ENABLED) &&
+               (psDevInfo->hMMUCtxUnregLock != NULL))
+       {
+               OSLockDestroy(psDevInfo->hMMUCtxUnregLock);
+       }
+
+       if (psDevInfo->hDebugFaultInfoLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hDebugFaultInfoLock);
+       }
+
+       /* De-init Freelists/ZBuffers... */
+       if (psDevInfo->hLockFreeList != NULL)
+       {
+               OSLockDestroy(psDevInfo->hLockFreeList);
+       }
+
+       if (psDevInfo->hLockZSBuffer != NULL)
+       {
+               OSLockDestroy(psDevInfo->hLockZSBuffer);
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* De-init work estimation lock */
+       if (psDevInfo->hWorkEstLock != NULL)
+       {
+               OSLockDestroy(psDevInfo->hWorkEstLock);
+       }
+#endif
+
+       /* Free DVFS Table */
+       if (psDevInfo->psGpuDVFSTable != NULL)
+       {
+               OSFreeMem(psDevInfo->psGpuDVFSTable);
+               psDevInfo->psGpuDVFSTable = NULL;
+       }
+}
+
+/*
+       DevDeInitRGX
+ */
+PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO              *psDevInfo = (PVRSRV_RGXDEV_INFO*)psDeviceNode->pvDevice;
+       PVRSRV_ERROR                    eError;
+       DEVICE_MEMORY_INFO              *psDevMemoryInfo;
+       IMG_UINT32              ui32Temp=0;
+
+       if (!psDevInfo)
+       {
+               /* Can happen if DevInitRGX failed */
+               PVR_DPF((PVR_DBG_ERROR, "DevDeInitRGX: Null DevInfo"));
+               return PVRSRV_OK;
+       }
+
+       if (psDevInfo->psRGXFWIfOsInit)
+       {
+               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+       }
+
+       DeviceDepBridgeDeInit(psDevInfo);
+
+#if defined(PDUMP)
+       DevmemIntFreeDefBackingPage(psDeviceNode,
+                                                               &psDeviceNode->sDummyPage,
+                                                               DUMMY_PAGE);
+       DevmemIntFreeDefBackingPage(psDeviceNode,
+                                                               &psDeviceNode->sDevZeroPage,
+                                                               DEV_ZERO_PAGE);
+#endif
+
+#if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
+       if (PVRSRVGetPVRSRVData()->eServicesState != PVRSRV_SERVICES_STATE_OK)
+       {
+               OSAtomicWrite(&psDeviceNode->sDummyPage.atRefCounter, 0);
+               PVR_UNREFERENCED_PARAMETER(ui32Temp);
+       }
+       else
+#else
+       {
+               /*Delete the Dummy page related info */
+               ui32Temp = (IMG_UINT32)OSAtomicRead(&psDeviceNode->sDummyPage.atRefCounter);
+               if (0 != ui32Temp)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Dummy page reference counter is non zero (%u)",
+                                __func__,
+                                ui32Temp));
+                       PVR_ASSERT(0);
+               }
+       }
+#endif
+
+       /*Delete the Dummy page related info */
+       ui32Temp = (IMG_UINT32)OSAtomicRead(&psDeviceNode->sDevZeroPage.atRefCounter);
+       if (0 != ui32Temp)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Zero page reference counter is non zero (%u)",
+                        __func__,
+                        ui32Temp));
+       }
+
+#if defined(PDUMP)
+       if (NULL != psDeviceNode->sDummyPage.hPdumpPg)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Error dummy page handle is still active");
+       }
+
+       if (NULL != psDeviceNode->sDevZeroPage.hPdumpPg)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Error Zero page handle is still active");
+       }
+#endif
+
+       /*The lock type need to be dispatch type here because it can be acquired from MISR (Z-buffer) path */
+       OSLockDestroy(psDeviceNode->sDummyPage.psPgLock);
+
+       /* Destroy the zero page lock */
+       OSLockDestroy(psDeviceNode->sDevZeroPage.psPgLock);
+
+       /* Unregister debug request notifiers first as they could depend on anything. */
+
+       RGXDebugDeinit(psDevInfo);
+
+       /*
+        * De-initialise in reverse order, so stage 2 init is undone first.
+        */
+       if (psDevInfo->bDevInit2Done)
+       {
+               DevPart2DeInitRGX(psDeviceNode);
+       }
+
+       /* Unregister MMU related stuff */
+       eError = RGXMMUInit_Unregister(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevDeInitRGX: Failed RGXMMUInit_Unregister (0x%x)",
+                        eError));
+       }
+
+       /* UnMap Regs */
+       if (psDevInfo->pvRegsBaseKM != NULL)
+       {
+#if !defined(NO_HARDWARE)
+               OSUnMapPhysToLin((void __force *) psDevInfo->pvRegsBaseKM,
+                                                psDevInfo->ui32RegSize);
+#endif /* !NO_HARDWARE */
+               psDevInfo->pvRegsBaseKM = NULL;
+       }
+
+#if 0 /* not required at this time */
+       if (psDevInfo->hTimer)
+       {
+               eError = OSRemoveTimer(psDevInfo->hTimer);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "DevDeInitRGX: Failed to remove timer"));
+                       return eError;
+               }
+               psDevInfo->hTimer = NULL;
+       }
+#endif
+
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+       RGXDeInitHeaps(psDevMemoryInfo);
+
+       if (psDevInfo->psRGXFWCodeMemDesc)
+       {
+               /* Free fw code */
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW code memory");
+               DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCodeMemDesc);
+               psDevInfo->psRGXFWCodeMemDesc = NULL;
+       }
+       if (psDevInfo->psRGXFWDataMemDesc)
+       {
+               /* Free fw data */
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW data memory");
+               DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWDataMemDesc);
+               psDevInfo->psRGXFWDataMemDesc = NULL;
+       }
+       if (psDevInfo->psRGXFWCorememCodeMemDesc)
+       {
+               /* Free fw core mem code */
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW coremem code memory");
+               DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWCorememCodeMemDesc);
+               psDevInfo->psRGXFWCorememCodeMemDesc = NULL;
+       }
+
+       if (psDevInfo->psRGXFWIfCorememDataStoreMemDesc)
+       {
+               /* Free fw core mem data */
+               PDUMPCOMMENT(psDeviceNode, "Freeing FW coremem data store memory");
+               DevmemReleaseDevVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+               psDevInfo->psRGXFWIfCorememDataStoreMemDesc = NULL;
+       }
+
+       /*
+          Free the firmware allocations.
+        */
+       RGXFreeFirmware(psDevInfo);
+
+#if defined(SUPPORT_VALIDATION)
+       RGXPowerDomainDeInitState(&psDevInfo->sPowerDomainState);
+#endif
+
+       RGXDeInitMultiCoreInfo(psDeviceNode);
+
+       /* De-initialise non-device specific (TL) users of RGX device memory */
+       RGXHWPerfDeinit(psDevInfo);
+
+       RGXDeInitDestroyFWKernelMemoryContext(psDeviceNode);
+
+       RGXHWPerfHostDeInit(psDevInfo);
+       eError = HTBDeInit();
+       PVR_LOG_IF_ERROR(eError, "HTBDeInit");
+
+       /* destroy the stalled CCB locks */
+       OSLockDestroy(psDevInfo->hCCBRecoveryLock);
+       OSLockDestroy(psDevInfo->hCCBStallCheckLock);
+
+       /* destroy the context list locks */
+       OSLockDestroy(psDevInfo->sRegCongfig.hLock);
+       OSLockDestroy(psDevInfo->hBPLock);
+       OSLockDestroy(psDevInfo->hRGXFWIfBufInitLock);
+       OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+       OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+       OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+       OSWRLockDestroy(psDevInfo->hTDMCtxListLock);
+       OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
+       OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+       OSSpinLockDestroy(psDevInfo->hLockKCCBDeferredCommandsList);
+       OSWRLockDestroy(psDevInfo->hCommonCtxtListLock);
+
+       /* Free device BVNC string */
+       if (NULL != psDevInfo->sDevFeatureCfg.pszBVNCString)
+       {
+               OSFreeMem(psDevInfo->sDevFeatureCfg.pszBVNCString);
+       }
+
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+       if (NULL != psDevInfo->sRGXTimerValues.pui64uscTimers)
+       {
+               OSFreeMem(psDevInfo->sRGXTimerValues.pui64uscTimers);
+               psDevInfo->sRGXTimerValues.pui64uscTimers = NULL;
+       }
+#endif
+
+       /* DeAllocate devinfo */
+       OSFreeMem(psDevInfo);
+
+       psDeviceNode->pvDevice = NULL;
+
+       return PVRSRV_OK;
+}
+
+#if defined(PDUMP)
+static
+PVRSRV_ERROR RGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)(psDeviceNode->pvDevice);
+
+       psDevInfo->bDumpedKCCBCtlAlready = IMG_FALSE;
+
+       return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+/* Takes a log2 page size parameter and calculates a suitable page size
+ * for the RGX heaps. Returns 0 if parameter is wrong.*/
+static INLINE IMG_UINT32 RGXHeapDerivePageSize(IMG_UINT32 uiLog2PageSize)
+{
+       IMG_BOOL bFound = IMG_FALSE;
+
+       /* OS page shift must be at least RGX_HEAP_4KB_PAGE_SHIFT,
+        * max RGX_HEAP_2MB_PAGE_SHIFT, non-zero and a power of two*/
+       if (uiLog2PageSize == 0U ||
+           (uiLog2PageSize < RGX_HEAP_4KB_PAGE_SHIFT) ||
+           (uiLog2PageSize > RGX_HEAP_2MB_PAGE_SHIFT))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Provided incompatible log2 page size %u",
+                               __func__,
+                               uiLog2PageSize));
+               PVR_ASSERT(0);
+               return 0;
+       }
+
+       do
+       {
+               switch (uiLog2PageSize)
+               {
+                       case RGX_HEAP_4KB_PAGE_SHIFT:
+                       case RGX_HEAP_16KB_PAGE_SHIFT:
+                       case RGX_HEAP_64KB_PAGE_SHIFT:
+                       case RGX_HEAP_256KB_PAGE_SHIFT:
+                       case RGX_HEAP_1MB_PAGE_SHIFT:
+                       case RGX_HEAP_2MB_PAGE_SHIFT:
+                               /* All good, RGX page size equals given page size
+                                * => use it as default for heaps */
+                               bFound = IMG_TRUE;
+                               break;
+                       default:
+                               /* We have to fall back to a smaller device
+                                * page size than given page size because there
+                                * is no exact match for any supported size. */
+                               uiLog2PageSize -= 1U;
+                               break;
+               }
+       } while (!bFound);
+
+       return uiLog2PageSize;
+}
+
+/* First 16-bits define possible types */
+#define HEAP_INST_VALUE_MASK     (0xFFFF)
+#define HEAP_INST_DEFAULT_VALUE  (1U)  /* Used to show either the heap is always instantiated by default (pfn = NULL)
+                                             OR
+                                             that this is the default configuration of the heap with an Alternative BRN */
+#define HEAP_INST_BRN_DEP_VALUE  (2U)  /* The inclusion of this heap is dependent on the brn being present */
+#define HEAP_INST_FEAT_DEP_VALUE (3U)  /* The inclusion of this heap is dependent on the feature being present */
+#define HEAP_INST_BRN_ALT_VALUE  (4U)  /* This entry is a possible alternative to the default determined by a BRN */
+#define HEAP_INST_FEAT_ALT_VALUE (5U)  /* The entry is a possible alternative to the default determined by a Feature define */
+
+/* Latter 16-bits define other flags we may need */
+#define HEAP_INST_NON4K_FLAG     (1 << 16U) /* This is a possible NON4K Entry and we should use the device
+                                               NON4K size when instantiating */
+
+typedef struct RGX_HEAP_INFO_TAG RGX_HEAP_INFO; // Forward declaration
+typedef IMG_BOOL (*PFN_IS_PRESENT)(PVRSRV_RGXDEV_INFO*, const RGX_HEAP_INFO*);
+
+struct RGX_HEAP_INFO_TAG
+{
+       IMG_CHAR           *pszName;
+       IMG_UINT64         ui64HeapBase;
+       IMG_DEVMEM_SIZE_T  uiHeapLength;
+       IMG_DEVMEM_SIZE_T  uiHeapReservedRegionLength;
+       IMG_UINT32         ui32Log2ImportAlignment;
+       PFN_IS_PRESENT     pfnIsHeapPresent;
+       IMG_UINT32         ui32HeapInstanceFlags;
+};
+
+/* Feature Present function prototypes */
+
+/* FW Feature Present function prototypes */
+
+static IMG_BOOL FWVZConfigPresent(PVRSRV_RGXDEV_INFO* psDevInfo, const RGX_HEAP_INFO* pksHeapInfo)
+{
+       /* Used to determine the correct table row to instantiate as a heap by checking
+        * the Heap base at run time VS the current table instance
+        */
+
+       /* Determine if we should include this entry based upon previous checks */
+       return (pksHeapInfo->ui64HeapBase == RGX_FIRMWARE_CONFIG_HEAP_BASE) ? IMG_TRUE : IMG_FALSE;
+}
+
+static IMG_BOOL FWVZMainHeapPresent(PVRSRV_RGXDEV_INFO* psDevInfo, const RGX_HEAP_INFO* pksHeapInfo)
+{
+       /* Used to determine the correct table row to instantiate as a heap by checking
+        * the Heap base at run time VS the current table instance
+        */
+       return (pksHeapInfo->ui64HeapBase == RGX_FIRMWARE_MAIN_HEAP_BASE) ? IMG_TRUE : IMG_FALSE;
+}
+
+static const RGX_HEAP_INFO gasRGXHeapLayoutApp[] =
+{
+       /* Name                             HeapBase                          HeapLength                        HeapReservedRegionLength                     Log2ImportAlignment pfnIsHeapPresent HeapInstanceFlags   */
+       {RGX_GENERAL_SVM_HEAP_IDENT,        RGX_GENERAL_SVM_HEAP_BASE,        RGX_GENERAL_SVM_HEAP_SIZE,        0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_GENERAL_HEAP_IDENT,            RGX_GENERAL_HEAP_BASE,            RGX_GENERAL_HEAP_SIZE,            (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_GENERAL_NON4K_HEAP_IDENT,      RGX_GENERAL_NON4K_HEAP_BASE,      RGX_GENERAL_NON4K_HEAP_SIZE,      0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE | HEAP_INST_NON4K_FLAG},
+       {RGX_PDSCODEDATA_HEAP_IDENT,        RGX_PDSCODEDATA_HEAP_BASE,        RGX_PDSCODEDATA_HEAP_SIZE,        (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_USCCODE_HEAP_IDENT,            RGX_USCCODE_HEAP_BASE,            RGX_USCCODE_HEAP_SIZE,            (1 * DEVMEM_HEAP_RESERVED_SIZE_GRANULARITY), 0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_VK_CAPT_REPLAY_HEAP_IDENT,     RGX_VK_CAPT_REPLAY_HEAP_BASE,     RGX_VK_CAPT_REPLAY_HEAP_SIZE,     0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_SIGNALS_HEAP_IDENT,            RGX_SIGNALS_HEAP_BASE,            RGX_SIGNALS_HEAP_SIZE,            0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_COMPONENT_CTRL_HEAP_IDENT,     RGX_COMPONENT_CTRL_HEAP_BASE,     RGX_COMPONENT_CTRL_HEAP_SIZE,     0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_FBCDC_HEAP_IDENT,              RGX_FBCDC_HEAP_BASE,              RGX_FBCDC_HEAP_SIZE,              0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_FBCDC_LARGE_HEAP_IDENT,        RGX_FBCDC_LARGE_HEAP_BASE,        RGX_FBCDC_LARGE_HEAP_SIZE,        0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_PDS_INDIRECT_STATE_HEAP_IDENT, RGX_PDS_INDIRECT_STATE_HEAP_BASE, RGX_PDS_INDIRECT_STATE_HEAP_SIZE, 0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_CMP_MISSION_RMW_HEAP_IDENT,    RGX_CMP_MISSION_RMW_HEAP_BASE,    RGX_CMP_MISSION_RMW_HEAP_SIZE,    0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_CMP_SAFETY_RMW_HEAP_IDENT,     RGX_CMP_SAFETY_RMW_HEAP_BASE,     RGX_CMP_SAFETY_RMW_HEAP_SIZE,     0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_TEXTURE_STATE_HEAP_IDENT,      RGX_TEXTURE_STATE_HEAP_BASE,      RGX_TEXTURE_STATE_HEAP_SIZE,      0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE},
+       {RGX_VISIBILITY_TEST_HEAP_IDENT,    RGX_VISIBILITY_TEST_HEAP_BASE,    RGX_VISIBILITY_TEST_HEAP_SIZE,    0,                                           0,                  NULL,            HEAP_INST_DEFAULT_VALUE}
+};
+
+static const RGX_HEAP_INFO gasRGXHeapLayoutFW[] =
+{
+       /* Name                          HeapBase                             HeapLength                        HeapReservedRegionLength Log2ImportAlignment pfnPresent           HeapInstanceFlags*/
+       {RGX_FIRMWARE_MAIN_HEAP_IDENT,   RGX_FIRMWARE_MAIN_HEAP_BASE,    RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE, 0,                       0,                  FWVZMainHeapPresent, HEAP_INST_DEFAULT_VALUE},
+       {RGX_FIRMWARE_CONFIG_HEAP_IDENT, RGX_FIRMWARE_CONFIG_HEAP_BASE,  RGX_FIRMWARE_CONFIG_HEAP_SIZE,       0,                       0,                  FWVZConfigPresent,   HEAP_INST_DEFAULT_VALUE}
+};
+
+/* Generic counting method. */
+static void _CountRequiredHeaps(PVRSRV_RGXDEV_INFO  *psDevInfo,
+                                   const RGX_HEAP_INFO  pksHeapInfo[],
+                                   IMG_UINT32           ui32HeapListSize,
+                                   IMG_UINT32*          ui32HeapCount)
+{
+       IMG_UINT32 i;
+
+       /* Loop over rows in the heap data array using callback to decide if we
+        * should include the heap
+        */
+       for (i = 0; i < ui32HeapListSize; i++)
+       {
+               const RGX_HEAP_INFO *psHeapInfo = &pksHeapInfo[i];
+
+               if (psHeapInfo->pfnIsHeapPresent)
+               {
+                       if (!psHeapInfo->pfnIsHeapPresent(psDevInfo, psHeapInfo))
+                       {
+                               /* We don't need to create this heap */
+                               continue;
+                       }
+               }
+
+               (*ui32HeapCount)++;
+       }
+}
+/* Generic heap instantiator */
+static void _InstantiateRequiredHeaps(PVRSRV_RGXDEV_INFO     *psDevInfo,
+                                         const RGX_HEAP_INFO     pksHeapInfo[],
+                                         IMG_UINT32              ui32HeapListSize,
+                                         DEVMEM_HEAP_BLUEPRINT **psDeviceMemoryHeapCursor)
+{
+       IMG_UINT32 i;
+       /* We now have a list of the heaps to include and so we should loop over this
+        * list and instantiate.
+        */
+       for (i = 0; i < ui32HeapListSize; i++)
+       {
+               IMG_UINT32 ui32Log2RgxDefaultPageShift = RGXHeapDerivePageSize(OSGetPageShift());
+               IMG_UINT32 ui32Log2DataPageSize = 0;
+
+               const RGX_HEAP_INFO *psHeapInfo = &pksHeapInfo[i];
+
+               if (psHeapInfo->pfnIsHeapPresent)
+               {
+                       if (!psHeapInfo->pfnIsHeapPresent(psDevInfo, psHeapInfo))
+                       {
+                               /* We don't need to create this heap */
+                               continue;
+                       }
+               }
+
+               if (psHeapInfo->ui32HeapInstanceFlags & HEAP_INST_NON4K_FLAG)
+               {
+                       ui32Log2DataPageSize = psDevInfo->ui32Log2Non4KPgSize;
+               }
+               else
+               {
+                       ui32Log2DataPageSize = ui32Log2RgxDefaultPageShift;
+               }
+
+               HeapCfgBlueprintInit(psHeapInfo->pszName,
+                                        psHeapInfo->ui64HeapBase,
+                                        psHeapInfo->uiHeapLength,
+                                        psHeapInfo->uiHeapReservedRegionLength,
+                                        ui32Log2DataPageSize,
+                                        psHeapInfo->ui32Log2ImportAlignment,
+                                        *psDeviceMemoryHeapCursor);
+
+               (*psDeviceMemoryHeapCursor)++;
+       }
+}
+
+static PVRSRV_ERROR RGXInitHeaps(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                    DEVICE_MEMORY_INFO *psNewMemoryInfo)
+{
+       PVRSRV_ERROR eError;
+       DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor;
+
+       IMG_UINT32 ui32HeapListSize = ARRAY_SIZE(gasRGXHeapLayoutApp);
+       IMG_UINT32 ui32FWHeapListSize = ARRAY_SIZE(gasRGXHeapLayoutFW);
+       IMG_UINT32 ui32CountedHeapSize;
+
+       IMG_UINT32 ui32HeapCount = 0;
+       IMG_UINT32 ui32FWHeapCount = 0;
+
+       /* Count heaps required for the app heaps */
+       _CountRequiredHeaps(psDevInfo,
+                               gasRGXHeapLayoutApp,
+                               ui32HeapListSize,
+                               &ui32HeapCount);
+
+       /* Count heaps required for the FW heaps */
+       _CountRequiredHeaps(psDevInfo,
+                               gasRGXHeapLayoutFW,
+                               ui32FWHeapListSize,
+                               &ui32FWHeapCount);
+
+       ui32CountedHeapSize = (ui32HeapCount + ui32FWHeapCount + RGX_NUM_OS_SUPPORTED);
+
+       psNewMemoryInfo->psDeviceMemoryHeap = OSAllocMem(sizeof(DEVMEM_HEAP_BLUEPRINT) * ui32CountedHeapSize);
+       PVR_LOG_GOTO_IF_NOMEM(psNewMemoryInfo->psDeviceMemoryHeap, eError, e0);
+
+       /* Initialise the heaps */
+       psDeviceMemoryHeapCursor = psNewMemoryInfo->psDeviceMemoryHeap;
+
+       /* Instantiate App Heaps */
+       _InstantiateRequiredHeaps(psDevInfo,
+                                     gasRGXHeapLayoutApp,
+                                     ui32HeapListSize,
+                                     &psDeviceMemoryHeapCursor);
+
+       /* Instantiate FW Heaps */
+       _InstantiateRequiredHeaps(psDevInfo,
+                                     gasRGXHeapLayoutFW,
+                                     ui32FWHeapListSize,
+                                     &psDeviceMemoryHeapCursor);
+
+       /* set the heap count */
+       psNewMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeapCursor - psNewMemoryInfo->psDeviceMemoryHeap);
+
+       /* Check we have allocated the correct # of heaps, minus any VZ heaps as these
+        * have not been created at this point
+        */
+       PVR_ASSERT(psNewMemoryInfo->ui32HeapCount == (ui32CountedHeapSize - RGX_NUM_OS_SUPPORTED));
+
+       /*
+          In the new heap setup, we initialise 2 configurations:
+               1 - One will be for the firmware only (index 1 in array)
+                       a. This primarily has the firmware heap in it.
+                       b. It also has additional guest OSID firmware heap(s)
+                               - Only if the number of support firmware OSID > 1
+               2 - Others shall be for clients only (index 0 in array)
+                       a. This has all the other client heaps in it.
+        */
+       psNewMemoryInfo->uiNumHeapConfigs = 2;
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray = OSAllocMem(sizeof(DEVMEM_HEAP_CONFIG) * psNewMemoryInfo->uiNumHeapConfigs);
+       PVR_LOG_GOTO_IF_NOMEM(psNewMemoryInfo->psDeviceMemoryHeapConfigArray, eError, e1);
+
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].pszName = "Default Heap Configuration";
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].uiNumHeaps = psNewMemoryInfo->ui32HeapCount - RGX_FIRMWARE_NUMBER_OF_FW_HEAPS;
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[0].psHeapBlueprintArray = psNewMemoryInfo->psDeviceMemoryHeap;
+
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].pszName = "Firmware Heap Configuration";
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps = RGX_FIRMWARE_NUMBER_OF_FW_HEAPS;
+       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].psHeapBlueprintArray = psDeviceMemoryHeapCursor - RGX_FIRMWARE_NUMBER_OF_FW_HEAPS;
+
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, MMU_VERSION) >= 4)
+       {
+               IMG_UINT32 i;
+               const IMG_UINT32 ui32GeneralNon4KHeapPageSize = (1 << psDevInfo->ui32Log2Non4KPgSize);
+               const IMG_UINT32 ui32RgxDefaultPageSize = (1 << RGXHeapDerivePageSize(OSGetPageShift()));
+
+               /*
+                * Initialise all MMU Page Size Range Config register to the default page size
+                * used by the OS, leaving the address range 0;
+                */
+               for (i = 0; i < ARRAY_SIZE(psDevInfo->aui64MMUPageSizeRangeValue); ++i)
+               {
+                       psDevInfo->aui64MMUPageSizeRangeValue[i] =
+                                       RGXMMUInit_GetConfigRangeValue(ui32RgxDefaultPageSize,
+                                                                                                  0,
+                                                                                                  (1 << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_ALIGNSHIFT));
+               }
+
+
+               /* set the last MMU config range covering the entire virtual memory to the OS's page size */
+               psDevInfo->aui64MMUPageSizeRangeValue[RGX_MAX_NUM_MMU_PAGE_SIZE_RANGES - 1] =
+                               RGXMMUInit_GetConfigRangeValue(ui32RgxDefaultPageSize, 0, (1ULL << 40));
+
+               /*
+                * If the Non4K heap has a different page size than the OS's page size
+                * (used as default for all other heaps), configure one MMU config range
+                * for the Non4K heap
+                */
+               if (ui32GeneralNon4KHeapPageSize != ui32RgxDefaultPageSize)
+               {
+                       psDevInfo->aui64MMUPageSizeRangeValue[0] =
+                                       RGXMMUInit_GetConfigRangeValue(ui32GeneralNon4KHeapPageSize,
+                                                                                                  RGX_GENERAL_NON4K_HEAP_BASE,
+                                                                                                  RGX_GENERAL_NON4K_HEAP_SIZE);
+               }
+       }
+
+#if (RGX_NUM_OS_SUPPORTED > 1)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+               IMG_UINT32 ui32OSid;
+
+               /* Create additional raw firmware heaps */
+               for (ui32OSid = RGX_FIRST_RAW_HEAP_OSID; ui32OSid < RGX_NUM_OS_SUPPORTED; ui32OSid++)
+               {
+                       if (RGXInitFwRawHeap(psDeviceMemoryHeapCursor, ui32OSid) != PVRSRV_OK)
+                       {
+                               /* if any allocation fails, free previously allocated heaps and abandon initialisation */
+                               for (; ui32OSid > RGX_FIRST_RAW_HEAP_OSID; ui32OSid--)
+                               {
+                                       RGXDeInitFwRawHeap(psDeviceMemoryHeapCursor);
+                                       psDeviceMemoryHeapCursor--;
+                               }
+                               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto e1;
+                       }
+
+                       /* Append additional firmware heaps to host driver firmware context heap configuration */
+                       psNewMemoryInfo->psDeviceMemoryHeapConfigArray[1].uiNumHeaps += 1;
+
+                       /* advance to the next heap */
+                       psDeviceMemoryHeapCursor++;
+               }
+       }
+#endif /* (RGX_NUM_OS_SUPPORTED > 1) */
+
+       return PVRSRV_OK;
+e1:
+       OSFreeMem(psNewMemoryInfo->psDeviceMemoryHeap);
+e0:
+       return eError;
+}
+
+static void RGXDeInitHeaps(DEVICE_MEMORY_INFO *psDevMemoryInfo)
+{
+#if (RGX_NUM_OS_SUPPORTED > 1)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+               IMG_UINT32 ui32OSid;
+               DEVMEM_HEAP_BLUEPRINT *psDeviceMemoryHeapCursor = psDevMemoryInfo->psDeviceMemoryHeap;
+
+               /* Delete all guest firmware heaps */
+               for (ui32OSid = RGX_FIRST_RAW_HEAP_OSID; ui32OSid < RGX_NUM_OS_SUPPORTED; ui32OSid++)
+               {
+                       RGXDeInitFwRawHeap(psDeviceMemoryHeapCursor);
+                       psDeviceMemoryHeapCursor++;
+               }
+       }
+#endif /* (RGX_NUM_OS_SUPPORTED > 1) */
+
+       OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeapConfigArray);
+       OSFreeMem(psDevMemoryInfo->psDeviceMemoryHeap);
+}
+
+static PVRSRV_ERROR RGXPhysMemDeviceHeapsInit(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PHYS_HEAP_CONFIG *psFwMainConfig = FindPhysHeapConfig(psDeviceNode->psDevConfig,
+                                                                                                                  PHYS_HEAP_USAGE_FW_MAIN);
+
+#if defined(RGX_NUM_OS_SUPPORTED) && (RGX_NUM_OS_SUPPORTED > 1)
+       /* VZ heap validation */
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               PVR_LOG_RETURN_IF_FALSE(psFwMainConfig != NULL,
+                                                               "FW Main heap is required for VZ Guest.",
+                                                               PVRSRV_ERROR_PHYSHEAP_CONFIG);
+       }
+#endif
+
+       if (psFwMainConfig != NULL)
+       {
+               /* Check FW_MAIN for multiple usage flags. Because FW_MAIN is divided
+                  into subheaps, shared usage with other heaps is not allowed.  */
+               PVR_LOG_RETURN_IF_FALSE(psFwMainConfig->ui32UsageFlags == PHYS_HEAP_USAGE_FW_MAIN,
+                                                               "FW Main phys heap config specified with more than one usage. FW Main must be FW Main only.",
+                                                               PVRSRV_ERROR_PHYSHEAP_CONFIG);
+       }
+
+       if (psFwMainConfig == NULL)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: Firmware physical heap not set", __func__));
+       }
+       else if (psFwMainConfig->eType == PHYS_HEAP_TYPE_UMA)
+       {
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: Firmware physical heap uses OS System memory (UMA)", __func__));
+       }
+       else /* PHYS_HEAP_TYPE_LMA or PHYS_HEAP_TYPE_DMA */
+       {
+               PHYS_HEAP_CONFIG sFwHeapConfig;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: Firmware physical heap uses local memory managed by the driver (LMA)", __func__));
+
+               PVR_LOG_GOTO_IF_FALSE(psFwMainConfig->uiSize >= RGX_FIRMWARE_RAW_HEAP_SIZE,
+                                                         "Invalid firmware physical heap size.", ErrorDeinit);
+
+#if defined(SUPPORT_AUTOVZ)
+               if (PVRSRV_VZ_MODE_IS(HOST))
+               {
+                       /* 1 Mb can hold the maximum amount of page tables for the memory shared between the firmware and all KM drivers:
+                        *  MAX(RAW_HEAP_SIZE) = 32 Mb; MAX(NUMBER_OS) = 8; Total shared memory = 256 Mb;
+                        *  MMU objects required: 65536 PTEs; 16 PDEs; 1 PCE; */
+                       IMG_UINT64 uMaxFwMmuPageTableSize = 1 * 1024 * 1024;
+
+                       sFwHeapConfig = *psFwMainConfig;
+
+                       /* By default the firmware MMU's page tables are allocated from the same carveout memory as the firmware heap.
+                        * If a different base address is specified for this reserved range, use the overriding define instead. */
+#if defined(PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR)
+                       sFwHeapConfig.sStartAddr.uiAddr = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
+                       sFwHeapConfig.sCardBase.uiAddr = PVR_AUTOVZ_OVERRIDE_FW_MMU_CARVEOUT_BASE_ADDR;
+#else
+                       sFwHeapConfig.sStartAddr.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED;
+                       sFwHeapConfig.sCardBase.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE * RGX_NUM_OS_SUPPORTED;
+#endif
+
+                       sFwHeapConfig.uiSize = uMaxFwMmuPageTableSize;
+                       sFwHeapConfig.ui32UsageFlags = 0;
+
+                       eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, "Fw MMU subheap",
+                                                     &psDeviceNode->psFwMMUReservedPhysHeap);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemCreateHeapLMA:MMU", ErrorDeinit);
+               }
+#endif
+
+               /* Subheap layout: Main + (optional MIPS reserved range) + Config */
+               sFwHeapConfig = *psFwMainConfig;
+               sFwHeapConfig.uiSize = RGX_FIRMWARE_DEFAULT_MAIN_HEAP_SIZE;
+               sFwHeapConfig.ui32UsageFlags = PHYS_HEAP_USAGE_FW_MAIN;
+
+               eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, "Fw Main subheap", &psDeviceNode->psFWMainPhysHeap);
+               PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemCreateHeapLMA:MAIN", ErrorDeinit);
+
+               sFwHeapConfig = *psFwMainConfig;
+               sFwHeapConfig.sStartAddr.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE;
+               sFwHeapConfig.sCardBase.uiAddr += RGX_FIRMWARE_RAW_HEAP_SIZE - RGX_FIRMWARE_CONFIG_HEAP_SIZE;
+               sFwHeapConfig.uiSize = RGX_FIRMWARE_CONFIG_HEAP_SIZE;
+               sFwHeapConfig.ui32UsageFlags = PHYS_HEAP_USAGE_FW_CONFIG;
+
+               eError = PhysmemCreateHeapLMA(psDeviceNode, &sFwHeapConfig, "Fw Cfg subheap", &psDeviceNode->psFWCfgPhysHeap);
+               PVR_LOG_GOTO_IF_ERROR(eError, "PhysmemCreateHeapLMA:CFG", ErrorDeinit);
+       }
+
+       /* Acquire FW heaps */
+       eError = PhysHeapAcquireByDevPhysHeap(PVRSRV_PHYS_HEAP_FW_MAIN, psDeviceNode,
+                                                                                 &psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_MAIN]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquire:FW_MAIN", ErrorDeinit);
+
+       eError = PhysHeapAcquireByDevPhysHeap(PVRSRV_PHYS_HEAP_FW_CONFIG, psDeviceNode,
+                                                                                 &psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_CONFIG]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquire:FW_CONFIG", ErrorDeinit);
+
+       eError = PhysHeapAcquireByDevPhysHeap(PVRSRV_PHYS_HEAP_FW_CODE, psDeviceNode,
+                                                                                 &psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_CODE]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquire:FW_CODE", ErrorDeinit);
+
+       eError = PhysHeapAcquireByDevPhysHeap(PVRSRV_PHYS_HEAP_FW_PRIV_DATA, psDeviceNode,
+                                                                                 &psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_PRIV_DATA]);
+       PVR_LOG_GOTO_IF_ERROR(eError, "PhysHeapAcquire:FW_DATA", ErrorDeinit);
+
+       return eError;
+
+ErrorDeinit:
+       PVR_ASSERT(IMG_FALSE);
+       PVRSRVPhysMemHeapsDeinit(psDeviceNode);
+
+       return eError;
+}
+
+static void _ReadNon4KHeapPageSize(IMG_UINT32 *pui32Log2Non4KPgSize)
+{
+       void *pvAppHintState = NULL;
+       IMG_UINT32 ui32AppHintDefault = PVRSRV_APPHINT_GENERALNON4KHEAPPAGESIZE;
+       IMG_UINT32 ui32GeneralNon4KHeapPageSize;
+
+       /* Get the page size for the dummy page from the NON4K heap apphint */
+       OSCreateKMAppHintState(&pvAppHintState);
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState,
+                GeneralNon4KHeapPageSize,&ui32AppHintDefault, &ui32GeneralNon4KHeapPageSize);
+       *pui32Log2Non4KPgSize = ExactLog2(ui32GeneralNon4KHeapPageSize);
+       OSFreeKMAppHintState(pvAppHintState);
+}
+
+/* RGXRegisterDevice
+ *
+ * WARNING!
+ *
+ * No PDUMP statements are allowed in until Part 2 of the device initialisation
+ * is reached.
+ */
+PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+       DEVICE_MEMORY_INFO *psDevMemoryInfo;
+       PVRSRV_RGXDEV_INFO      *psDevInfo;
+       void *pvAppHintState = NULL;
+       IMG_UINT32 ui32AppHintDefault = HWPERF_HOST_TL_STREAM_SIZE_DEFAULT, ui32HWPerfHostBufSizeKB;
+
+       ui32AppHintDefault = PVRSRV_APPHINT_DRIVERMODE;
+       OSCreateKMAppHintState(&pvAppHintState);
+       OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, HWPerfHostBufSizeInKB,
+                            &ui32AppHintDefault, &ui32HWPerfHostBufSizeKB);
+       OSFreeKMAppHintState(pvAppHintState);
+       pvAppHintState = NULL;
+
+       /*********************
+        * Device node setup *
+        *********************/
+       /* Setup static data and callbacks on the device agnostic device node */
+#if defined(PDUMP)
+       psDeviceNode->sDevId.pszPDumpRegName    = RGX_PDUMPREG_NAME;
+       psDeviceNode->sDevId.pszPDumpDevName    = PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL]);
+       psDeviceNode->pfnPDumpInitDevice = &RGXResetPDump;
+       psDeviceNode->ui64FBCClearColour = RGX_FBC_CC_DEFAULT;
+
+#endif /* PDUMP */
+
+       OSAtomicWrite(&psDeviceNode->eHealthStatus, PVRSRV_DEVICE_HEALTH_STATUS_OK);
+       OSAtomicWrite(&psDeviceNode->eHealthReason, PVRSRV_DEVICE_HEALTH_REASON_NONE);
+
+       psDeviceNode->pfnDevSLCFlushRange = RGXSLCFlushRange;
+       psDeviceNode->pfnInvalFBSCTable = RGXInvalidateFBSCTable;
+
+       psDeviceNode->pfnValidateOrTweakPhysAddrs = NULL;
+
+       psDeviceNode->pfnMMUCacheInvalidate = RGXMMUCacheInvalidate;
+
+       psDeviceNode->pfnMMUCacheInvalidateKick = RGXMMUCacheInvalidateKick;
+
+       psDeviceNode->pfnInitDeviceCompatCheck  = &RGXDevInitCompatCheck;
+
+       /* Register callbacks for creation of device memory contexts */
+       psDeviceNode->pfnRegisterMemoryContext = RGXRegisterMemoryContext;
+       psDeviceNode->pfnUnregisterMemoryContext = RGXUnregisterMemoryContext;
+
+       /* Register callbacks for Unified Fence Objects */
+       psDeviceNode->pfnAllocUFOBlock = RGXAllocUFOBlock;
+       psDeviceNode->pfnFreeUFOBlock = RGXFreeUFOBlock;
+
+       /* Register callback for checking the device's health */
+       psDeviceNode->pfnUpdateHealthStatus = PVRSRV_VZ_MODE_IS(GUEST) ? NULL : RGXUpdateHealthStatus;
+
+#if defined(SUPPORT_AUTOVZ)
+       /* Register callback for updating the virtualization watchdog */
+       psDeviceNode->pfnUpdateAutoVzWatchdog = RGXUpdateAutoVzWatchdog;
+#endif
+
+       /* Register method to service the FW HWPerf buffer */
+       psDeviceNode->pfnServiceHWPerf = RGXHWPerfDataStoreCB;
+
+       /* Register callback for getting the device version information string */
+       psDeviceNode->pfnDeviceVersionString = RGXDevVersionString;
+
+       /* Register callback for getting the device clock speed */
+       psDeviceNode->pfnDeviceClockSpeed = RGXDevClockSpeed;
+
+       /* Register callback for soft resetting some device modules */
+       psDeviceNode->pfnSoftReset = RGXSoftReset;
+
+       /* Register callback for resetting the HWR logs */
+       psDeviceNode->pfnResetHWRLogs = RGXResetHWRLogs;
+
+       /* Register callback for resetting the HWR logs */
+       psDeviceNode->pfnVerifyBVNC = RGXVerifyBVNC;
+
+       /* Register callback for checking alignment of UM structures */
+       psDeviceNode->pfnAlignmentCheck = RGXAlignmentCheck;
+
+       /*Register callback for checking the supported features and getting the
+        * corresponding values */
+       psDeviceNode->pfnCheckDeviceFeature = RGXBvncCheckFeatureSupported;
+       psDeviceNode->pfnGetDeviceFeatureValue = RGXBvncGetSupportedFeatureValue;
+
+       /* Callback for checking if system layer supports FBC 3.1 */
+       psDeviceNode->pfnHasFBCDCVersion31 = NULL;
+
+       /* Callback for getting the MMU device attributes */
+       psDeviceNode->pfnGetMMUDeviceAttributes = RGXDevMMUAttributes;
+
+       /* Register callback for initialising device-specific physical memory heaps */
+       psDeviceNode->pfnPhysMemDeviceHeapsInit = RGXPhysMemDeviceHeapsInit;
+
+       /* Set up required support for dummy page */
+       OSAtomicWrite(&(psDeviceNode->sDummyPage.atRefCounter), 0);
+       OSAtomicWrite(&(psDeviceNode->sDevZeroPage.atRefCounter), 0);
+
+       /* Set the order to 0 */
+       psDeviceNode->sDummyPage.sPageHandle.uiOrder = 0;
+       psDeviceNode->sDevZeroPage.sPageHandle.uiOrder = 0;
+
+       /* Set the size of the Dummy page to zero */
+       psDeviceNode->sDummyPage.ui32Log2PgSize = 0;
+
+       /* Set the size of the Zero page to zero */
+       psDeviceNode->sDevZeroPage.ui32Log2PgSize = 0;
+
+       /* Set the Dummy page phys addr */
+       psDeviceNode->sDummyPage.ui64PgPhysAddr = MMU_BAD_PHYS_ADDR;
+
+       /* Set the Zero page phys addr */
+       psDeviceNode->sDevZeroPage.ui64PgPhysAddr = MMU_BAD_PHYS_ADDR;
+
+       /* The lock can be acquired from MISR (Z-buffer) path */
+       eError = OSLockCreate(&psDeviceNode->sDummyPage.psPgLock);
+       if (PVRSRV_OK != eError)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create dummy page lock", __func__));
+               return eError;
+       }
+
+       /* Create the lock for zero page */
+       eError = OSLockCreate(&psDeviceNode->sDevZeroPage.psPgLock);
+       if (PVRSRV_OK != eError)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create Zero page lock", __func__));
+               goto free_dummy_page;
+       }
+#if defined(PDUMP)
+       psDeviceNode->sDummyPage.hPdumpPg = NULL;
+       psDeviceNode->sDevZeroPage.hPdumpPg = NULL;
+#endif
+
+       psDeviceNode->pfnHasFBCDCVersion31 = RGXSystemHasFBCDCVersion31;
+
+       /* The device shared-virtual-memory heap address-space size is stored here for faster
+          look-up without having to walk the device heap configuration structures during
+          client device connection  (i.e. this size is relative to a zero-based offset) */
+       psDeviceNode->ui64GeneralSVMHeapTopVA = RGX_GENERAL_SVM_HEAP_BASE + RGX_GENERAL_SVM_HEAP_SIZE;
+
+       /*********************
+        * Device info setup *
+        *********************/
+       /* Allocate device control block */
+       psDevInfo = OSAllocZMem(sizeof(*psDevInfo));
+       if (psDevInfo == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "DevInitRGXPart1 : Failed to alloc memory for DevInfo"));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* create locks for the context lists stored in the DevInfo structure.
+        * these lists are modified on context create/destroy and read by the
+        * watchdog thread
+        */
+
+       eError = OSWRLockCreate(&(psDevInfo->hRenderCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create render context list lock", __func__));
+               goto e0;
+       }
+
+       eError = OSWRLockCreate(&(psDevInfo->hComputeCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create compute context list lock", __func__));
+               goto e1;
+       }
+
+       eError = OSWRLockCreate(&(psDevInfo->hTransferCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create transfer context list lock", __func__));
+               goto e2;
+       }
+
+       eError = OSWRLockCreate(&(psDevInfo->hTDMCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create TDM context list lock", __func__));
+               goto e3;
+       }
+
+       eError = OSWRLockCreate(&(psDevInfo->hKickSyncCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create kick sync context list lock", __func__));
+               goto e4;
+       }
+
+       eError = OSWRLockCreate(&(psDevInfo->hMemoryCtxListLock));
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create memory context list lock", __func__));
+               goto e5;
+       }
+
+       eError = OSSpinLockCreate(&psDevInfo->hLockKCCBDeferredCommandsList);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to KCCB deferred commands list lock", __func__));
+               goto e6;
+       }
+       dllist_init(&(psDevInfo->sKCCBDeferredCommandsListHead));
+
+       dllist_init(&(psDevInfo->sRenderCtxtListHead));
+       dllist_init(&(psDevInfo->sComputeCtxtListHead));
+       dllist_init(&(psDevInfo->sTDMCtxtListHead));
+       dllist_init(&(psDevInfo->sKickSyncCtxtListHead));
+
+       dllist_init(&(psDevInfo->sCommonCtxtListHead));
+       psDevInfo->ui32CommonCtxtCurrentID = 1;
+
+
+       eError = OSWRLockCreate(&psDevInfo->hCommonCtxtListLock);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create common context list lock", __func__));
+               goto e7;
+       }
+
+       eError = OSLockCreate(&psDevInfo->sRegCongfig.hLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create register configuration lock", __func__));
+               goto e8;
+       }
+
+       eError = OSLockCreate(&psDevInfo->hBPLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock for break points", __func__));
+               goto e9;
+       }
+
+       eError = OSLockCreate(&psDevInfo->hRGXFWIfBufInitLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock for trace buffers", __func__));
+               goto e10;
+       }
+
+       eError = OSLockCreate(&psDevInfo->hCCBStallCheckLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create stalled CCB checking lock", __func__));
+               goto e11;
+       }
+       eError = OSLockCreate(&psDevInfo->hCCBRecoveryLock);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create stalled CCB recovery lock", __func__));
+               goto e12;
+       }
+
+       dllist_init(&psDevInfo->sMemoryContextList);
+
+       /* initialise ui32SLRHoldoffCounter */
+       if (RGX_INITIAL_SLR_HOLDOFF_PERIOD_MS > DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT)
+       {
+               psDevInfo->ui32SLRHoldoffCounter = RGX_INITIAL_SLR_HOLDOFF_PERIOD_MS / DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT;
+       }
+       else
+       {
+               psDevInfo->ui32SLRHoldoffCounter = 0;
+       }
+
+       /* Setup static data and callbacks on the device specific device info */
+       psDevInfo->psDeviceNode         = psDeviceNode;
+
+       psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+       psDevInfo->pvDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+       /*
+        * Map RGX Registers
+        */
+       psDevInfo->ui32RegSize = psDeviceNode->psDevConfig->ui32RegsSize;
+       psDevInfo->sRegsPhysBase = psDeviceNode->psDevConfig->sRegsCpuPBase;
+
+#if !defined(NO_HARDWARE)
+       psDevInfo->pvRegsBaseKM = (void __iomem *) OSMapPhysToLin(psDeviceNode->psDevConfig->sRegsCpuPBase,
+                                                                                               psDeviceNode->psDevConfig->ui32RegsSize,
+                                                                                    PVRSRV_MEMALLOCFLAG_CPU_UNCACHED);
+
+       if (psDevInfo->pvRegsBaseKM == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "PVRSRVRGXInitDevPart2KM: Failed to create RGX register mapping"));
+               eError = PVRSRV_ERROR_BAD_MAPPING;
+               goto e13;
+       }
+#else
+       psDevInfo->pvRegsBaseKM = NULL;
+#endif /* !NO_HARDWARE */
+
+       psDeviceNode->pvDevice = psDevInfo;
+
+       eError = RGXBvncInitialiseConfiguration(psDeviceNode);
+       if (PVRSRV_OK != eError)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Unsupported HW device detected by driver",
+                        __func__));
+               goto e14;
+       }
+
+       _ReadNon4KHeapPageSize(&psDevInfo->ui32Log2Non4KPgSize);
+
+       /*Set the zero & dummy page sizes as needed for the heap with largest page size */
+       psDeviceNode->sDevZeroPage.ui32Log2PgSize = psDevInfo->ui32Log2Non4KPgSize;
+       psDeviceNode->sDummyPage.ui32Log2PgSize = psDevInfo->ui32Log2Non4KPgSize;
+
+       /* Configure MMU specific stuff */
+       RGXMMUInit_Register(psDeviceNode);
+
+       eError = RGXInitHeaps(psDevInfo, psDevMemoryInfo);
+       if (eError != PVRSRV_OK)
+       {
+               goto e14;
+       }
+
+       eError = RGXHWPerfInit(psDevInfo);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfInit", e14);
+
+       eError = RGXHWPerfHostInit(psDeviceNode->pvDevice, ui32HWPerfHostBufSizeKB);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXHWPerfHostInit", ErrorDeInitHWPerfFw);
+
+#if defined(SUPPORT_VALIDATION)
+       eError = RGXPowerDomainInitState(&psDevInfo->sPowerDomainState,
+                                                                               psDevInfo->sDevFeatureCfg.ui32MAXPowUnitCount);
+       if (eError != PVRSRV_OK)
+       {
+               goto ErrorDeInitHWPerfHost;
+       }
+
+       /* This completion will be signaled by the ISR when processing
+        * the answer CCB command carrying an RGX Register read value */
+       init_completion(&psDevInfo->sFwRegs.sRegComp);
+       psDevInfo->sFwRegs.ui64RegVal = 0;
+
+#if defined(SUPPORT_SOC_TIMER)
+       {
+               IMG_BOOL ui32AppHintDefault = IMG_FALSE;
+               IMG_BOOL bInitSocTimer;
+               void *pvAppHintState = NULL;
+
+               OSCreateKMAppHintState(&pvAppHintState);
+               OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, ValidateSOCUSCTimer, &ui32AppHintDefault, &bInitSocTimer);
+               OSFreeKMAppHintState(pvAppHintState);
+
+               if (bInitSocTimer)
+               {
+                       eError = RGXInitSOCUSCTimer(psDeviceNode);
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXInitSOCUSCTimer", e16);
+               }
+       }
+#endif
+#endif
+
+       /* Register callback for dumping debug info */
+       eError = RGXDebugInit(psDevInfo);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXDebugInit", e16);
+
+       /* Initialise the device dependent bridges */
+       eError = DeviceDepBridgeInit(psDevInfo);
+       PVR_LOG_IF_ERROR(eError, "DeviceDepBridgeInit");
+
+       /* Initialise error counters */
+       memset(&psDevInfo->sErrorCounts, 0, sizeof(PVRSRV_RGXDEV_ERROR_COUNTS));
+
+       return PVRSRV_OK;
+
+e16:
+#if defined(SUPPORT_VALIDATION)
+       RGXPowerDomainDeInitState(&psDevInfo->sPowerDomainState);
+ErrorDeInitHWPerfHost:
+#endif
+       RGXHWPerfHostDeInit(psDevInfo);
+ErrorDeInitHWPerfFw:
+       RGXHWPerfDeinit(psDevInfo);
+e14:
+#if !defined(NO_HARDWARE)
+       OSUnMapPhysToLin((void __force *) psDevInfo->pvRegsBaseKM,
+                                                        psDevInfo->ui32RegSize);
+
+e13:
+#endif /* !NO_HARDWARE */
+       OSLockDestroy(psDevInfo->hCCBRecoveryLock);
+e12:
+       OSLockDestroy(psDevInfo->hCCBStallCheckLock);
+e11:
+       OSLockDestroy(psDevInfo->hRGXFWIfBufInitLock);
+e10:
+       OSLockDestroy(psDevInfo->hBPLock);
+e9:
+       OSLockDestroy(psDevInfo->sRegCongfig.hLock);
+e8:
+       OSWRLockDestroy(psDevInfo->hCommonCtxtListLock);
+e7:
+       OSSpinLockDestroy(psDevInfo->hLockKCCBDeferredCommandsList);
+e6:
+       OSWRLockDestroy(psDevInfo->hMemoryCtxListLock);
+e5:
+       OSWRLockDestroy(psDevInfo->hKickSyncCtxListLock);
+e4:
+       OSWRLockDestroy(psDevInfo->hTDMCtxListLock);
+e3:
+       OSWRLockDestroy(psDevInfo->hTransferCtxListLock);
+e2:
+       OSWRLockDestroy(psDevInfo->hComputeCtxListLock);
+e1:
+       OSWRLockDestroy(psDevInfo->hRenderCtxListLock);
+e0:
+       OSFreeMem(psDevInfo);
+
+       /* Destroy the zero page lock created above */
+       OSLockDestroy(psDeviceNode->sDevZeroPage.psPgLock);
+
+free_dummy_page:
+       /* Destroy the dummy page lock created above */
+       OSLockDestroy(psDeviceNode->sDummyPage.psPgLock);
+
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+IMG_PCHAR RGXDevBVNCString(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       IMG_PCHAR psz = psDevInfo->sDevFeatureCfg.pszBVNCString;
+       if (NULL == psz)
+       {
+               IMG_CHAR pszBVNCInfo[RGX_HWPERF_MAX_BVNC_LEN];
+               size_t uiBVNCStringSize;
+               size_t uiStringLength;
+
+               uiStringLength = OSSNPrintf(pszBVNCInfo, RGX_HWPERF_MAX_BVNC_LEN, "%d.%d.%d.%d",
+                               psDevInfo->sDevFeatureCfg.ui32B,
+                               psDevInfo->sDevFeatureCfg.ui32V,
+                               psDevInfo->sDevFeatureCfg.ui32N,
+                               psDevInfo->sDevFeatureCfg.ui32C);
+               PVR_ASSERT(uiStringLength < RGX_HWPERF_MAX_BVNC_LEN);
+
+               uiBVNCStringSize = (uiStringLength + 1) * sizeof(IMG_CHAR);
+               psz = OSAllocMem(uiBVNCStringSize);
+               if (NULL != psz)
+               {
+                       OSCachedMemCopy(psz, pszBVNCInfo, uiBVNCStringSize);
+                       psDevInfo->sDevFeatureCfg.pszBVNCString = psz;
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_MESSAGE,
+                                       "%s: Allocating memory for BVNC Info string failed",
+                                       __func__));
+               }
+       }
+
+       return psz;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXDevVersionString
+@Description    Gets the version string for the given device node and returns
+                a pointer to it in ppszVersionString. It is then the
+                responsibility of the caller to free this memory.
+@Input          psDeviceNode            Device node from which to obtain the
+                                        version string
+@Output                ppszVersionString       Contains the version string upon return
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       IMG_CHAR **ppszVersionString)
+{
+#if defined(COMPAT_BVNC_MASK_B) || defined(COMPAT_BVNC_MASK_V) || defined(COMPAT_BVNC_MASK_N) || defined(COMPAT_BVNC_MASK_C) || defined(NO_HARDWARE) || defined(EMULATOR)
+       const IMG_CHAR szFormatString[] = "GPU variant BVNC: %s (SW)";
+#else
+       const IMG_CHAR szFormatString[] = "GPU variant BVNC: %s (HW)";
+#endif
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       IMG_PCHAR pszBVNC;
+       size_t uiStringLength;
+
+       if (psDeviceNode == NULL || ppszVersionString == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       pszBVNC = RGXDevBVNCString(psDevInfo);
+
+       if (NULL == pszBVNC)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       uiStringLength = OSStringLength(pszBVNC);
+       uiStringLength += (sizeof(szFormatString) - 2); /* sizeof includes the null, -2 for "%s" */
+       *ppszVersionString = OSAllocMem(uiStringLength * sizeof(IMG_CHAR));
+       if (*ppszVersionString == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       OSSNPrintf(*ppszVersionString, uiStringLength, szFormatString,
+               pszBVNC);
+
+       return PVRSRV_OK;
+}
+
+/**************************************************************************/ /*!
+@Function       RGXDevClockSpeed
+@Description    Gets the clock speed for the given device node and returns
+                it in pui32RGXClockSpeed.
+@Input          psDeviceNode           Device node
+@Output         pui32RGXClockSpeed  Variable for storing the clock speed
+@Return         PVRSRV_ERROR
+*/ /***************************************************************************/
+static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                       IMG_PUINT32  pui32RGXClockSpeed)
+{
+       RGX_DATA *psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+
+       /* get clock speed */
+       *pui32RGXClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+
+       return PVRSRV_OK;
+}
+
+#if (RGX_NUM_OS_SUPPORTED > 1)
+/*!
+ *******************************************************************************
+
+ @Function             RGXInitFwRawHeap
+
+ @Description  Called to perform additional initialisation
+ ******************************************************************************/
+static PVRSRV_ERROR RGXInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap, IMG_UINT32 ui32OSid)
+{
+       IMG_UINT32 uiStringLength;
+       IMG_UINT32 uiStringLengthMax = 32;
+
+       IMG_UINT32 ui32Log2RgxDefaultPageShift = RGXHeapDerivePageSize(OSGetPageShift());
+
+       uiStringLength = MIN(sizeof(RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT), uiStringLengthMax + 1);
+
+       /* Start by allocating memory for this OSID heap identification string */
+       psDevMemHeap->pszName = OSAllocMem(uiStringLength * sizeof(IMG_CHAR));
+       if (psDevMemHeap->pszName == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       /* Append the OSID number to the RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT string */
+       OSSNPrintf((IMG_CHAR *)psDevMemHeap->pszName, uiStringLength, RGX_FIRMWARE_GUEST_RAW_HEAP_IDENT, ui32OSid);
+
+       /* Use the common blueprint template support function to initialise the heap */
+       HeapCfgBlueprintInit(psDevMemHeap->pszName,
+                                RGX_FIRMWARE_RAW_HEAP_BASE + (ui32OSid * RGX_FIRMWARE_RAW_HEAP_SIZE),
+                                RGX_FIRMWARE_RAW_HEAP_SIZE,
+                                0,
+                                ui32Log2RgxDefaultPageShift,
+                                0,
+                                psDevMemHeap);
+
+       return PVRSRV_OK;
+}
+
+/*!
+ *******************************************************************************
+
+ @Function             RGXDeInitFwRawHeap
+
+ @Description  Called to perform additional deinitialisation
+ ******************************************************************************/
+static void RGXDeInitFwRawHeap(DEVMEM_HEAP_BLUEPRINT *psDevMemHeap)
+{
+       IMG_UINT64 uiBase = RGX_FIRMWARE_RAW_HEAP_BASE + RGX_FIRMWARE_RAW_HEAP_SIZE;
+       IMG_UINT64 uiSpan = uiBase + ((RGX_NUM_OS_SUPPORTED - 1) * RGX_FIRMWARE_RAW_HEAP_SIZE);
+
+       /* Safe to do as the guest firmware heaps are last in the list */
+       if (psDevMemHeap->sHeapBaseAddr.uiAddr >= uiBase &&
+           psDevMemHeap->sHeapBaseAddr.uiAddr < uiSpan)
+       {
+               void *pszName = (void*)psDevMemHeap->pszName;
+               OSFreeMem(pszName);
+       }
+}
+#endif /* (RGX_NUM_OS_SUPPORTED > 1) */
+
+/******************************************************************************
+ End of file (rgxinit.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxinit.h
new file mode 100644 (file)
index 0000000..87d8509
--- /dev/null
@@ -0,0 +1,308 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX initialisation header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX initialisation
+@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(RGXINIT_H)
+#define RGXINIT_H
+
+#include "connection_server.h"
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgx_bridge.h"
+#include "fwload.h"
+
+#if defined(__linux__)
+#define OS_FW_VERIFY_FUNCTION OSVerifyFirmware
+#else
+#define OS_FW_VERIFY_FUNCTION NULL
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     RGXInitDevPart2
+
+ @Description
+
+ Second part of server-side RGX initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXInitDevPart2 (PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                         IMG_UINT32                    ui32DeviceFlags,
+                                                         IMG_UINT32                    ui32HWPerfHostFilter,
+                                                         RGX_ACTIVEPM_CONF             eActivePMConf,
+                                                         IMG_UINT32                    ui32AvailableSPUMask,
+                                                         IMG_UINT32                    ui32AvailableRACMask);
+
+PVRSRV_ERROR RGXInitAllocFWImgMem(PVRSRV_DEVICE_NODE   *psDeviceNode,
+                                  IMG_DEVMEM_SIZE_T    ui32FWCodeLen,
+                                  IMG_DEVMEM_SIZE_T    ui32FWDataLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememCodeLen,
+                                  IMG_DEVMEM_SIZE_T    uiFWCorememDataLen);
+
+
+/*!
+*******************************************************************************
+
+ @Function     RGXInitFirmware
+
+ @Description
+
+ Server-side RGX firmware initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR
+RGXInitFirmware(PVRSRV_DEVICE_NODE       *psDeviceNode,
+                IMG_BOOL                 bEnableSignatureChecks,
+                IMG_UINT32               ui32SignatureChecksBufSize,
+                IMG_UINT32               ui32HWPerfFWBufSizeKB,
+                IMG_UINT64               ui64HWPerfFilter,
+                IMG_UINT32               ui32ConfigFlags,
+                IMG_UINT32               ui32LogType,
+                IMG_UINT32               ui32FilterFlags,
+                IMG_UINT32               ui32JonesDisableMask,
+                IMG_UINT32               ui32HWRDebugDumpLimit,
+                IMG_UINT32                              ui32RenderKillingCtl,
+                IMG_UINT32                              ui32CDMTDMKillingCtl,
+                IMG_UINT32                              *pui32TPUTrilinearFracMask,
+                IMG_UINT32                              *pui32USRMNumRegions,
+                IMG_UINT64                              *pui64UVBRMNumRegions,
+                IMG_UINT32               ui32HWPerfCountersDataSize,
+                RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandingConf,
+                FW_PERF_CONF             eFirmwarePerf,
+                IMG_UINT32               ui32KCCBSizeLog2,
+                IMG_UINT32               ui32ConfigFlagsExt,
+                IMG_UINT32               ui32AvailableSPUMask,
+                IMG_UINT32               ui32AvailableRACMask,
+                IMG_UINT32               ui32FwOsCfgFlags);
+
+
+/*!
+*******************************************************************************
+
+ @Function     RGXLoadAndGetFWData
+
+ @Description
+
+ Load FW and return pointer to FW data.
+
+ @Input psDeviceNode - device node
+
+ @Input ppsRGXFW - fw pointer
+
+ @Output ppbFWData - pointer to FW data (NULL if an error occurred)
+
+ @Return PVRSRV_ERROR - PVRSRV_OK on success
+                        PVRSRV_ERROR_NOT_READY if filesystem is not ready
+                        PVRSRV_ERROR_NOT_FOUND if no suitable FW image found
+                        PVRSRV_ERROR_OUT_OF_MEMORY if unable to alloc memory for FW image
+                        PVRSRV_ERROR_NOT_AUTHENTICATED if FW image failed verification
+
+******************************************************************************/
+PVRSRV_ERROR RGXLoadAndGetFWData(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 OS_FW_IMAGE **ppsRGXFW,
+                                 const IMG_BYTE **ppbFWData);
+#if defined(PDUMP)
+/*!
+*******************************************************************************
+
+ @Function     RGXInitHWPerfCounters
+
+ @Description
+
+ Initialisation of the performance counters
+
+ @Input psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXInitHWPerfCounters(PVRSRV_DEVICE_NODE  *psDeviceNode);
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function     RGXRegisterDevice
+
+ @Description
+
+ Registers the device with the system
+
+ @Input:       psDeviceNode - device node
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXRegisterDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*!
+*******************************************************************************
+
+ @Function     RGXDevBVNCString
+
+ @Description
+
+ Returns the Device BVNC string. It will allocate and fill it first, if necessary.
+
+ @Input:   psDevInfo - device info (must not be null)
+
+ @Return   IMG_PCHAR - pointer to BVNC string
+
+******************************************************************************/
+IMG_PCHAR RGXDevBVNCString(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function     DevDeInitRGX
+
+ @Description
+
+ Reset and deinitialise Chip
+
+ @Input psDeviceNode - device info. structure
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR DevDeInitRGX(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+
+#if !defined(NO_HARDWARE)
+
+void RGX_WaitForInterruptsTimeout(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+/*!
+*******************************************************************************
+
+ @Function     SORgxGpuUtilStatsRegister
+
+ @Description  SO Interface function called from the OS layer implementation.
+               Initialise data used to compute GPU utilisation statistics
+               for a particular user (identified by the handle passed as
+               argument). This function must be called only once for each
+               different user/handle.
+
+ @Input        phGpuUtilUser - Pointer to handle used to identify a user of
+                               RGXGetGpuUtilStats
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SORgxGpuUtilStatsRegister(IMG_HANDLE *phGpuUtilUser);
+
+
+/*!
+*******************************************************************************
+
+ @Function     SORgxGpuUtilStatsUnregister
+
+ @Description  SO Interface function called from the OS layer implementation.
+               Free data previously used to compute GPU utilisation statistics
+               for a particular user (identified by the handle passed as
+               argument).
+
+ @Input        hGpuUtilUser - Handle used to identify a user of
+                              RGXGetGpuUtilStats
+
+ @Return       PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR SORgxGpuUtilStatsUnregister(IMG_HANDLE hGpuUtilUser);
+#endif /* !defined(NO_HARDWARE) */
+
+/*!
+************************************************************************************
+ @Function             RGXSystemGetFabricCoherency
+
+ @Description  Get the system fabric coherency for the device by reading default
+                               configuration from device register, subject to AppHint overrides.
+
+ @Input                        sRegsCpuPBase           : Device register CPU physical address base
+                               ui32RegsSize            : Device register size
+                               peDevFabricType         : Device memory bus fabric type
+                               peCacheSnoopingMode : Fabric coherency override
+
+ @Return               PVRSRV_ERROR
+************************************************************************************/
+PVRSRV_ERROR RGXSystemGetFabricCoherency(PVRSRV_DEVICE_CONFIG *psDeviceConfig,
+                                                                                IMG_CPU_PHYADDR sRegsCpuPBase,
+                                                                                IMG_UINT32 ui32RegsSize,
+                                                                                PVRSRV_DEVICE_FABRIC_TYPE *peDevFabricType,
+                                                                                PVRSRV_DEVICE_SNOOP_MODE *peCacheSnoopingMode);
+
+/*!
+ *******************************************************************************
+
+ @Function      RGXInitCreateFWKernelMemoryContext
+
+ @Description   Called to perform initialisation during firmware kernel context
+                creation.
+
+ @Input         psDeviceNode  device node
+ ******************************************************************************/
+PVRSRV_ERROR RGXInitCreateFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+/*!
+ *******************************************************************************
+
+ @Function      RGXDeInitDestroyFWKernelMemoryContext
+
+ @Description   Called to perform deinitialisation during firmware kernel
+                context destruction.
+
+ @Input         psDeviceNode  device node
+ ******************************************************************************/
+void RGXDeInitDestroyFWKernelMemoryContext(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+#endif /* RGXINIT_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer.h
new file mode 100644 (file)
index 0000000..42fdf1e
--- /dev/null
@@ -0,0 +1,510 @@
+/*************************************************************************/ /*!
+@File
+@Title          Header for Services abstraction layer
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Declaration of an interface layer used to abstract code that
+                can be compiled outside of the DDK, potentially in a
+                completely different OS.
+                All the headers included by this file must also be copied to
+                the alternative source tree.
+                All the functions declared here must have a DDK implementation
+                inside the DDK source tree (e.g. rgxlayer_impl.h/.c) and
+                another different implementation in case they are used outside
+                of the DDK.
+                All of the functions accept as a first parameter a
+                "const void *hPrivate" argument. It should be used to pass
+                around any implementation specific data required.
+@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(RGXLAYER_H)
+#define RGXLAYER_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#include "img_defs.h"
+#include "img_types.h"
+#include "img_elf.h"
+#include "pvrsrv_error.h" /* includes pvrsrv_errors.h */
+#include "pvrsrv_device.h"
+#include "rgx_bvnc_defs_km.h"
+#include "rgx_fw_info.h"
+#include "rgx_fwif_shared.h" /* includes rgx_common.h and mem_types.h */
+#include "rgx_meta.h"
+#include "rgx_riscv.h"
+
+#include "rgxdefs_km.h"
+/* includes:
+ * rgx_cr_defs_km.h,
+ * RGX_BVNC_CORE_KM_HEADER (rgxcore_km_B.V.N.C.h),
+ * RGX_BNC_CONFIG_KM_HEADER (rgxconfig_km_B.V.N.C.h)
+ */
+
+
+/*!
+*******************************************************************************
+
+ @Function       RGXMemCopy
+
+ @Description    MemCopy implementation
+
+ @Input          hPrivate   : Implementation specific data
+ @Input          pvDst      : Pointer to the destination
+ @Input          pvSrc      : Pointer to the source location
+ @Input          uiSize     : The amount of memory to copy in bytes
+
+ @Return         void
+
+******************************************************************************/
+void RGXMemCopy(const void *hPrivate,
+                void *pvDst,
+                void *pvSrc,
+                size_t uiSize);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXMemSet
+
+ @Description    MemSet implementation
+
+ @Input          hPrivate   : Implementation specific data
+ @Input          pvDst      : Pointer to the start of the memory region
+ @Input          ui8Value   : The value to be written
+ @Input          uiSize     : The number of bytes to be set to ui8Value
+
+ @Return         void
+
+******************************************************************************/
+void RGXMemSet(const void *hPrivate,
+               void *pvDst,
+               IMG_UINT8 ui8Value,
+               size_t uiSize);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXCommentLog
+
+ @Description    Generic log function used for debugging or other purposes
+
+ @Input          hPrivate   : Implementation specific data
+ @Input          pszString  : Message to be printed
+ @Input          ...        : Variadic arguments
+
+ @Return         void
+
+******************************************************************************/
+__printf(2, 3)
+void RGXCommentLog(const void *hPrivate,
+                   const IMG_CHAR *pszString,
+                   ...);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXErrorLog
+
+ @Description    Generic error log function used for debugging or other purposes
+
+ @Input          hPrivate   : Implementation specific data
+ @Input          pszString  : Message to be printed
+ @Input          ...        : Variadic arguments
+
+ @Return         void
+
+******************************************************************************/
+__printf(2, 3)
+void RGXErrorLog(const void *hPrivate,
+                 const IMG_CHAR *pszString,
+                 ...);
+
+/* This is used to check if a specific feature is enabled.
+ * Should be used instead of calling RGXDeviceHasFeature.  */
+#define RGX_DEVICE_HAS_FEATURE(hPrivate, Feature) \
+                       RGXDeviceHasFeature(hPrivate, RGX_FEATURE_##Feature##_BIT_MASK)
+
+/* This is used to check if a specific feature with value is enabled.
+ * Should be used instead of calling RGXDeviceGetFeatureValue.  */
+#define RGX_DEVICE_HAS_FEATURE_VALUE(hPrivate, Feature) \
+                       (RGXDeviceGetFeatureValue(hPrivate, RGX_FEATURE_##Feature##_IDX) >= 0)
+
+/* This is used to get the value of a specific feature from hPrivate.
+ * Should be used instead of calling RGXDeviceGetFeatureValue.  */
+#define RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, Feature) \
+                       RGXDeviceGetFeatureValue(hPrivate, RGX_FEATURE_##Feature##_IDX)
+
+/* This is used to get the value of a specific ERN from hPrivate.
+ * Should be used instead of calling RGXDeviceHasErnBrn.  */
+#define RGX_DEVICE_HAS_ERN(hPrivate, FixNum) \
+                       RGXDeviceHasErnBrn(hPrivate, HW_##FixNum##_BIT_MASK)
+
+/* This is used to get the value of a specific BRN from hPrivate.
+ * Should be used instead of calling RGXDeviceHasErnBrn.  */
+#define RGX_DEVICE_HAS_BRN(hPrivate, FixNum) \
+                       RGXDeviceHasErnBrn(hPrivate, FIX_HW_##FixNum##_BIT_MASK)
+
+#define CLK_CTRL_FORCE_ON(X, Module) \
+                       X = (((X) & RGX_CR_##Module##_CLRMSK) | RGX_CR_##Module##_ON)
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceGetFeatureValue
+
+ @Description    Checks if a device has a particular feature with values
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64Feature  : Feature with values to check
+
+ @Return         Value >= 0 if the given feature is available, -1 otherwise
+
+******************************************************************************/
+IMG_INT32 RGXDeviceGetFeatureValue(const void *hPrivate, IMG_UINT64 ui64Feature);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasFeature
+
+ @Description    Checks if a device has a particular feature
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64Feature  : Feature to check
+
+ @Return         IMG_TRUE if the given feature is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_BOOL RGXDeviceHasFeature(const void *hPrivate, IMG_UINT64 ui64Feature);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXDeviceHasErnBrn
+
+ @Description    Checks if a device has a particular errata
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui64ErnsBrns : Flags to check
+
+ @Return         IMG_TRUE if the given errata is available, IMG_FALSE otherwise
+
+******************************************************************************/
+IMG_BOOL RGXDeviceHasErnBrn(const void *hPrivate, IMG_UINT64 ui64ErnsBrns);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetFWCorememSize
+
+ @Description    Get the FW coremem size
+
+ @Input          hPrivate   : Implementation specific data
+
+ @Return         FW coremem size
+
+******************************************************************************/
+IMG_INTERNAL
+IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function      RGXWriteReg32/64
+
+ @Description   Write a value to a 32/64 bit RGX register
+
+ @Input         hPrivate         : Implementation specific data
+ @Input         ui32RegAddr      : Register offset inside the register bank
+ @Input         ui32/64RegValue  : New register value
+
+ @Return        void
+
+******************************************************************************/
+void RGXWriteReg32(const void *hPrivate,
+                   IMG_UINT32 ui32RegAddr,
+                   IMG_UINT32 ui32RegValue);
+
+void RGXWriteReg64(const void *hPrivate,
+                   IMG_UINT32 ui32RegAddr,
+                   IMG_UINT64 ui64RegValue);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXReadReg32/64
+
+ @Description    Read a 32/64 bit RGX register
+
+ @Input          hPrivate     : Implementation specific data
+ @Input          ui32RegAddr  : Register offset inside the register bank
+
+ @Return         Register value
+
+******************************************************************************/
+IMG_UINT32 RGXReadReg32(const void *hPrivate,
+                        IMG_UINT32 ui32RegAddr);
+
+IMG_UINT64 RGXReadReg64(const void *hPrivate,
+                        IMG_UINT32 ui32RegAddr);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXReadModifyWriteReg32
+
+ @Description    Read-modify-write a 32 bit RGX register
+
+ @Input          hPrivate     : Implementation specific data.
+ @Input          ui32RegAddr  : Register offset inside the register bank.
+ @Input          ui32RegValue : New register value.
+ @Input          ui32RegMask  : Keep the bits set in the mask.
+
+ @Return         Always returns PVRSRV_OK
+
+******************************************************************************/
+IMG_UINT32 RGXReadModifyWriteReg64(const void *hPrivate,
+                                   IMG_UINT32 ui32RegAddr,
+                                   IMG_UINT64 ui64RegValue,
+                                   IMG_UINT64 ui64RegKeepMask);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXPollReg32/64
+
+ @Description    Poll on a 32/64 bit RGX register until some bits are set/unset
+
+ @Input          hPrivate         : Implementation specific data
+ @Input          ui32RegAddr      : Register offset inside the register bank
+ @Input          ui32/64RegValue  : Value expected from the register
+ @Input          ui32/64RegMask   : Only the bits set in this mask will be
+                                    checked against uiRegValue
+
+ @Return         PVRSRV_OK if the poll succeeds,
+                 PVRSRV_ERROR_TIMEOUT if the poll takes too long
+
+******************************************************************************/
+PVRSRV_ERROR RGXPollReg32(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT32 ui32RegValue,
+                          IMG_UINT32 ui32RegMask);
+
+PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT64 ui64RegValue,
+                          IMG_UINT64 ui64RegMask);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXWaitCycles
+
+ @Description    Wait for a number of GPU cycles and/or microseconds
+
+ @Input          hPrivate    : Implementation specific data
+ @Input          ui32Cycles  : Number of GPU cycles to wait for in pdumps,
+                               it can also be used when running driver-live
+                               if desired (ignoring the next parameter)
+ @Input          ui32WaitUs  : Number of microseconds to wait for when running
+                               driver-live
+
+ @Return         void
+
+******************************************************************************/
+void RGXWaitCycles(const void *hPrivate,
+                   IMG_UINT32 ui32Cycles,
+                   IMG_UINT32 ui32WaitUs);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireKernelMMUPC
+
+ @Description     Acquire the Kernel MMU Page Catalogue device physical address
+
+ @Input           hPrivate  : Implementation specific data
+ @Input           psPCAddr  : Returned page catalog address
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXWriteKernelMMUPC32/64
+
+ @Description     Write the Kernel MMU Page Catalogue to the 32/64 bit
+                  RGX register passed as argument.
+                  In a driver-live scenario without PDump these functions
+                  are the same as RGXWriteReg32/64 and they don't need
+                  to be reimplemented.
+
+ @Input           hPrivate        : Implementation specific data
+ @Input           ui32PCReg       : Register offset inside the register bank
+ @Input           ui32AlignShift  : PC register alignshift
+ @Input           ui32Shift       : PC register shift
+ @Input           ui32/64PCVal    : Page catalog value (aligned and shifted)
+
+ @Return          void
+
+******************************************************************************/
+#if defined(PDUMP)
+void RGXWriteKernelMMUPC32(const void *hPrivate,
+                           IMG_UINT32 ui32PCReg,
+                           IMG_UINT32 ui32PCRegAlignShift,
+                           IMG_UINT32 ui32PCRegShift,
+                           IMG_UINT32 ui32PCVal);
+
+#else  /* defined(PDUMP) */
+#define RGXWriteKernelMMUPC32(priv, pcreg, alignshift, shift, pcval) \
+       RGXWriteReg32(priv, pcreg, pcval)
+#endif /* defined(PDUMP) */
+
+/*!
+*******************************************************************************
+
+ @Function        RGXDoFWSlaveBoot
+
+ @Description     Returns whether or not a FW Slave Boot is required
+                  while powering on
+
+ @Input           hPrivate       : Implementation specific data
+
+ @Return          IMG_BOOL
+
+******************************************************************************/
+IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXFabricCoherencyTest
+
+ @Description    Performs fabric coherency test
+
+ @Input          hPrivate         : Implementation specific data
+
+ @Return         PVRSRV_OK if the test succeeds,
+                 PVRSRV_ERROR_INIT_FAILURE if the test fails at some point
+
+******************************************************************************/
+PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetDeviceSLCBanks
+
+ @Description    Returns the number of SLC banks used by the device
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return         Number of SLC banks
+
+******************************************************************************/
+IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function       RGXGetDeviceCacheLineSize
+
+ @Description    Returns the device cache line size
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return         Cache line size
+
+******************************************************************************/
+IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireBootCodeAddr
+
+ @Description     Acquire the device virtual address of the RISCV boot code
+
+ @Input           hPrivate         : Implementation specific data
+ @Output          psBootCodeAddr   : Boot code base address
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireBootCodeAddr(const void *hPrivate, IMG_DEV_VIRTADDR *psBootCodeAddr);
+
+/*!
+*******************************************************************************
+
+ @Function        RGXAcquireBootDataAddr
+
+ @Description     Acquire the device virtual address of the RISCV boot data
+
+ @Input           hPrivate         : Implementation specific data
+ @Output          psBootDataAddr   : Boot data base address
+
+ @Return          void
+
+******************************************************************************/
+void RGXAcquireBootDataAddr(const void *hPrivate, IMG_DEV_VIRTADDR *psBootDataAddr);
+
+/*!
+*******************************************************************************
+
+ @Function      RGXDeviceAckIrq
+
+ @Description   Checks the implementation specific IRQ status register,
+                clearing it if necessary and returning the IRQ status.
+
+ @Input          hPrivate    : Implementation specific data
+
+ @Return:       IRQ status
+
+******************************************************************************/
+IMG_BOOL RGXDeviceAckIrq(const void *hPrivate);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* RGXLAYER_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer_impl.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxlayer_impl.c
new file mode 100644 (file)
index 0000000..4778142
--- /dev/null
@@ -0,0 +1,993 @@
+/*************************************************************************/ /*!
+@File
+@Title          DDK implementation of the Services abstraction layer
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    DDK implementation of the Services abstraction layer
+@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.
+*/ /**************************************************************************/
+
+#include "rgxlayer_impl.h"
+#include "osfunc.h"
+#include "pdump_km.h"
+#include "rgxfwutils.h"
+#include "cache_km.h"
+
+#if defined(PDUMP)
+#include <stdarg.h>
+#endif
+
+void RGXMemCopy(const void *hPrivate,
+                void *pvDst,
+                void *pvSrc,
+                size_t uiSize)
+{
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+       OSDeviceMemCopy(pvDst, pvSrc, uiSize);
+}
+
+void RGXMemSet(const void *hPrivate,
+               void *pvDst,
+               IMG_UINT8 ui8Value,
+               size_t uiSize)
+{
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+       OSDeviceMemSet(pvDst, ui8Value, uiSize);
+}
+
+void RGXCommentLog(const void *hPrivate,
+                   const IMG_CHAR *pszString,
+                   ...)
+{
+#if defined(PDUMP)
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       va_list argList;
+       va_start(argList, pszString);
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       PDumpCommentWithFlagsVA(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, pszString, argList);
+       va_end(argList);
+#else
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+       PVR_UNREFERENCED_PARAMETER(pszString);
+#endif
+}
+
+void RGXErrorLog(const void *hPrivate,
+                 const IMG_CHAR *pszString,
+                 ...)
+{
+       IMG_CHAR szBuffer[PVR_MAX_DEBUG_MESSAGE_LEN];
+       va_list argList;
+
+       PVR_UNREFERENCED_PARAMETER(hPrivate);
+
+       va_start(argList, pszString);
+       vsnprintf(szBuffer, sizeof(szBuffer), pszString, argList);
+       va_end(argList);
+
+       PVR_DPF((PVR_DBG_ERROR, "%s", szBuffer));
+}
+
+IMG_INT32 RGXDeviceGetFeatureValue(const void *hPrivate, IMG_UINT64 ui64Feature)
+{
+       IMG_INT32 i32Ret = -1;
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVR_ASSERT(hPrivate != NULL);
+
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       psDeviceNode = psDevInfo->psDeviceNode;
+
+       if ((psDeviceNode->pfnGetDeviceFeatureValue))
+       {
+               i32Ret = psDeviceNode->pfnGetDeviceFeatureValue(psDeviceNode, ui64Feature);
+       }
+
+       return i32Ret;
+}
+
+IMG_BOOL RGXDeviceHasFeature(const void *hPrivate, IMG_UINT64 ui64Feature)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       return (psDevInfo->sDevFeatureCfg.ui64Features & ui64Feature) != 0;
+}
+
+IMG_UINT32 RGXGetFWCorememSize(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META_COREMEM_SIZE))
+       {
+               return RGX_GET_FEATURE_VALUE(psDevInfo, META_COREMEM_SIZE);
+       }
+       return 0;
+}
+
+void RGXWriteReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (!(psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW))
+#endif
+       {
+               OSWriteHWReg32(pvRegsBase, ui32RegAddr, ui32RegValue);
+       }
+
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                  ui32RegAddr, ui32RegValue, psParams->ui32PdumpFlags);
+}
+
+void RGXWriteReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr, IMG_UINT64 ui64RegValue)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (!(psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW))
+#endif
+       {
+               OSWriteHWReg64(pvRegsBase, ui32RegAddr, ui64RegValue);
+       }
+
+       PDUMPREG64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                  ui32RegAddr, ui64RegValue, psParams->ui32PdumpFlags);
+}
+
+IMG_UINT32 RGXReadReg32(const void *hPrivate, IMG_UINT32 ui32RegAddr)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+       IMG_UINT32 ui32RegValue;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
+       {
+               ui32RegValue = IMG_UINT32_MAX;
+       }
+       else
+#endif
+       {
+               ui32RegValue = OSReadHWReg32(pvRegsBase, ui32RegAddr);
+       }
+
+       PDUMPREGREAD32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                      ui32RegAddr, psParams->ui32PdumpFlags);
+
+       return ui32RegValue;
+}
+
+IMG_UINT64 RGXReadReg64(const void *hPrivate, IMG_UINT32 ui32RegAddr)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+       IMG_UINT64 ui64RegValue;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW)
+       {
+               ui64RegValue = IMG_UINT64_MAX;
+       }
+       else
+#endif
+       {
+               ui64RegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
+       }
+
+       PDUMPREGREAD64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                      ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
+
+       return ui64RegValue;
+}
+
+IMG_UINT32 RGXReadModifyWriteReg64(const void *hPrivate,
+                                   IMG_UINT32 ui32RegAddr,
+                                   IMG_UINT64 uiRegValueNew,
+                                   IMG_UINT64 uiRegKeepMask)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+       /* only use the new values for bits we update according to the keep mask */
+       uiRegValueNew &= ~uiRegKeepMask;
+
+#if defined(PDUMP)
+       /* Store register offset to temp PDump variable */
+       PDumpRegRead64ToInternalVar(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                                   ":SYSMEM:$1", ui32RegAddr, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Keep the bits set in the mask */
+       PDumpWriteVarANDValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                               uiRegKeepMask, PDUMP_FLAGS_CONTINUOUS);
+
+       /* OR the new values */
+       PDumpWriteVarORValueOp(psDevInfo->psDeviceNode, ":SYSMEM:$1",
+                              uiRegValueNew, PDUMP_FLAGS_CONTINUOUS);
+
+       /* Do the actual register write */
+       PDumpInternalVarToReg64(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME,
+                               ui32RegAddr, ":SYSMEM:$1", 0);
+
+       if (!(psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW))
+#endif
+
+       {
+               IMG_UINT64 uiRegValue = OSReadHWReg64(pvRegsBase, ui32RegAddr);
+               uiRegValue &= uiRegKeepMask;
+               OSWriteHWReg64(pvRegsBase, ui32RegAddr, uiRegValue | uiRegValueNew);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXPollReg32(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT32 ui32RegValue,
+                          IMG_UINT32 ui32RegMask)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (!(psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW))
+#endif
+       {
+               if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                        (IMG_UINT32 __iomem *)((IMG_UINT8 __iomem *)pvRegsBase + ui32RegAddr),
+                                        ui32RegValue,
+                                        ui32RegMask,
+                                        POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXPollReg32: Poll for Reg (0x%x) failed", ui32RegAddr));
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+       }
+
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   ui32RegAddr,
+                   ui32RegValue,
+                   ui32RegMask,
+                   psParams->ui32PdumpFlags,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXPollReg64(const void *hPrivate,
+                          IMG_UINT32 ui32RegAddr,
+                          IMG_UINT64 ui64RegValue,
+                          IMG_UINT64 ui64RegMask)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       void __iomem *pvRegsBase;
+
+       /* Split lower and upper words */
+       IMG_UINT32 ui32UpperValue = (IMG_UINT32) (ui64RegValue >> 32);
+       IMG_UINT32 ui32LowerValue = (IMG_UINT32) (ui64RegValue);
+       IMG_UINT32 ui32UpperMask = (IMG_UINT32) (ui64RegMask >> 32);
+       IMG_UINT32 ui32LowerMask = (IMG_UINT32) (ui64RegMask);
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+       pvRegsBase = psDevInfo->pvRegsBaseKM;
+
+#if defined(PDUMP)
+       if (!(psParams->ui32PdumpFlags & PDUMP_FLAGS_NOHW))
+#endif
+       {
+               if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                        (IMG_UINT32 __iomem *)((IMG_UINT8 __iomem *)pvRegsBase + ui32RegAddr + 4),
+                                        ui32UpperValue,
+                                        ui32UpperMask,
+                                        POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for upper part of Reg (0x%x) failed", ui32RegAddr));
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+
+               if (PVRSRVPollForValueKM(psDevInfo->psDeviceNode,
+                                        (IMG_UINT32 __iomem *)((IMG_UINT8 __iomem *)pvRegsBase + ui32RegAddr),
+                                        ui32LowerValue,
+                                        ui32LowerMask,
+                                        POLL_FLAG_LOG_ERROR) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "RGXPollReg64: Poll for lower part of Reg (0x%x) failed", ui32RegAddr));
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+       }
+
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   ui32RegAddr + 4,
+                   ui32UpperValue,
+                   ui32UpperMask,
+                   psParams->ui32PdumpFlags,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+
+       PDUMPREGPOL(psDevInfo->psDeviceNode,
+                   RGX_PDUMPREG_NAME,
+                   ui32RegAddr,
+                   ui32LowerValue,
+                   ui32LowerMask,
+                   psParams->ui32PdumpFlags,
+                   PDUMP_POLL_OPERATOR_EQUAL);
+
+       return PVRSRV_OK;
+}
+
+void RGXWaitCycles(const void *hPrivate, IMG_UINT32 ui32Cycles, IMG_UINT32 ui32TimeUs)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+       OSWaitus(ui32TimeUs);
+       PDUMPIDLWITHFLAGS(psDevInfo->psDeviceNode, ui32Cycles, PDUMP_FLAGS_CONTINUOUS);
+}
+
+void RGXAcquireKernelMMUPC(const void *hPrivate, IMG_DEV_PHYADDR *psPCAddr)
+{
+       PVR_ASSERT(hPrivate != NULL);
+       *psPCAddr = ((RGX_LAYER_PARAMS*)hPrivate)->sPCAddr;
+}
+
+#if defined(PDUMP)
+void RGXWriteKernelMMUPC32(const void *hPrivate,
+                           IMG_UINT32 ui32PCReg,
+                           IMG_UINT32 ui32PCRegAlignShift,
+                           IMG_UINT32 ui32PCRegShift,
+                           IMG_UINT32 ui32PCVal)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+       /* Write the cat-base address */
+       OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32PCReg, ui32PCVal);
+
+       /* Pdump catbase address */
+       MMU_PDumpWritePageCatBase(psDevInfo->psKernelMMUCtx,
+                                 RGX_PDUMPREG_NAME,
+                                 ui32PCReg,
+                                 4,
+                                 ui32PCRegAlignShift,
+                                 ui32PCRegShift,
+                                 PDUMP_FLAGS_CONTINUOUS);
+}
+#endif /* defined(PDUMP) */
+
+#define MAX_NUM_COHERENCY_TESTS  (10)
+IMG_BOOL RGXDoFWSlaveBoot(const void *hPrivate)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_DEVICE_NODE *psDeviceNode;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+       if (psDevInfo->ui32CoherencyTestsDone >= MAX_NUM_COHERENCY_TESTS)
+       {
+               return IMG_FALSE;
+       }
+
+       psDeviceNode = psDevInfo->psDeviceNode;
+#if !defined(NO_HARDWARE)
+       return (PVRSRVSystemSnoopingOfCPUCache(psDeviceNode->psDevConfig) &&
+               PVRSRVSystemSnoopingOfDeviceCache(psDeviceNode->psDevConfig));
+#else
+       return IMG_FALSE;
+#endif
+}
+
+/*
+ * The fabric coherency test is performed when platform supports fabric coherency
+ * either in the form of ACE-lite or Full-ACE. This test is done quite early
+ * with the firmware processor quiescent and makes exclusive use of the slave
+ * port interface for reading/writing through the device memory hierarchy. The
+ * rationale for the test is to ensure that what the CPU writes to its dcache
+ * is visible to the GPU via coherency snoop miss/hit and vice-versa without
+ * any intervening cache maintenance by the writing agent.
+ */
+PVRSRV_ERROR RGXFabricCoherencyTest(const void *hPrivate)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       IMG_UINT32 *pui32FabricCohTestBufferCpuVA = NULL;
+       IMG_UINT32 *pui32FabricCohCcTestBufferCpuVA = NULL;
+       IMG_UINT32 *pui32FabricCohNcTestBufferCpuVA = NULL;
+       DEVMEM_MEMDESC *psFabricCohTestBufferMemDesc = NULL;
+       DEVMEM_MEMDESC *psFabricCohCcTestBufferMemDesc = NULL;
+       DEVMEM_MEMDESC *psFabricCohNcTestBufferMemDesc = NULL;
+       RGXFWIF_DEV_VIRTADDR sFabricCohCcTestBufferDevVA;
+       RGXFWIF_DEV_VIRTADDR sFabricCohNcTestBufferDevVA;
+       RGXFWIF_DEV_VIRTADDR *psFabricCohTestBufferDevVA = NULL;
+       IMG_DEVMEM_SIZE_T uiFabricCohTestBlockSize = sizeof(IMG_UINT64);
+       IMG_DEVMEM_ALIGN_T uiFabricCohTestBlockAlign = sizeof(IMG_UINT64);
+       IMG_UINT64 ui64SegOutAddrTopCached = 0;
+       IMG_UINT64 ui64SegOutAddrTopUncached = 0;
+       IMG_UINT32 ui32OddEven;
+       IMG_UINT32 ui32OddEvenSeed = 1;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_BOOL bFullTestPassed = IMG_TRUE;
+       IMG_BOOL bExit = IMG_FALSE;
+#if defined(DEBUG)
+       IMG_BOOL bSubTestPassed = IMG_FALSE;
+#endif
+       enum TEST_TYPE {
+               CPU_WRITE_GPU_READ_SM=0, GPU_WRITE_CPU_READ_SM,
+               CPU_WRITE_GPU_READ_SH,   GPU_WRITE_CPU_READ_SH
+       } eTestType;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+       PVR_LOG(("Starting fabric coherency test ....."));
+
+       /* Size and align are 'expanded' because we request an export align allocation */
+       eError = DevmemExportalignAdjustSizeAndAlign(DevmemGetHeapLog2PageSize(psDevInfo->psFirmwareMainHeap),
+                                                    &uiFabricCohTestBlockSize,
+                                                    &uiFabricCohTestBlockAlign);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "DevmemExportalignAdjustSizeAndAlign() error: %s, exiting",
+                               PVRSRVGetErrorString(eError)));
+               goto e0;
+       }
+
+       /* Allocate, acquire cpu address and set firmware address for cc=1 buffer */
+       eError = DevmemFwAllocateExportable(psDevInfo->psDeviceNode,
+                                                                               uiFabricCohTestBlockSize,
+                                                                               uiFabricCohTestBlockAlign,
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                                               "FwExFabricCoherencyCcTestBuffer",
+                                                                               &psFabricCohCcTestBufferMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "DevmemFwAllocateExportable() error: %s, exiting",
+                               PVRSRVGetErrorString(eError)));
+               goto e0;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psFabricCohCcTestBufferMemDesc, (void **) &pui32FabricCohCcTestBufferCpuVA);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "DevmemAcquireCpuVirtAddr() error: %s, exiting",
+                               PVRSRVGetErrorString(eError)));
+               goto e1;
+       }
+
+       /* Create a FW address which is uncached in the Meta DCache and in the SLC using the Meta bootloader segment.
+          This segment is the only one configured correctly out of reset (when this test is meant to be executed) */
+       eError = RGXSetFirmwareAddress(&sFabricCohCcTestBufferDevVA,
+                                                 psFabricCohCcTestBufferMemDesc,
+                                                 0,
+                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", e2);
+
+       /* Undo most of the FW mappings done by RGXSetFirmwareAddress */
+       sFabricCohCcTestBufferDevVA.ui32Addr &= ~RGXFW_SEGMMU_DATA_META_CACHE_MASK;
+       sFabricCohCcTestBufferDevVA.ui32Addr &= ~RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK;
+       sFabricCohCcTestBufferDevVA.ui32Addr -= RGXFW_SEGMMU_DATA_BASE_ADDRESS;
+
+       /* Map the buffer in the bootloader segment as uncached */
+       sFabricCohCcTestBufferDevVA.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
+       sFabricCohCcTestBufferDevVA.ui32Addr |= RGXFW_SEGMMU_DATA_META_UNCACHED;
+
+       /* Allocate, acquire cpu address and set firmware address for cc=0 buffer  */
+       eError = DevmemFwAllocateExportable(psDevInfo->psDeviceNode,
+                                                                               uiFabricCohTestBlockSize,
+                                                                               uiFabricCohTestBlockAlign,
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                               PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                                               "FwExFabricCoherencyNcTestBuffer",
+                                                                               &psFabricCohNcTestBufferMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "DevmemFwAllocateExportable() error: %s, exiting",
+                               PVRSRVGetErrorString(eError)));
+               goto e3;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psFabricCohNcTestBufferMemDesc, (void **) &pui32FabricCohNcTestBufferCpuVA);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "DevmemAcquireCpuVirtAddr() error: %s, exiting",
+                               PVRSRVGetErrorString(eError)));
+               goto e4;
+       }
+
+       eError = RGXSetFirmwareAddress(&sFabricCohNcTestBufferDevVA,
+                                                 psFabricCohNcTestBufferMemDesc,
+                                                 0,
+                                                 RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", e5);
+
+       /* Undo most of the FW mappings done by RGXSetFirmwareAddress */
+       sFabricCohNcTestBufferDevVA.ui32Addr &= ~RGXFW_SEGMMU_DATA_META_CACHE_MASK;
+       sFabricCohNcTestBufferDevVA.ui32Addr &= ~RGXFW_SEGMMU_DATA_VIVT_SLC_CACHE_MASK;
+       sFabricCohNcTestBufferDevVA.ui32Addr -= RGXFW_SEGMMU_DATA_BASE_ADDRESS;
+
+       /* Map the buffer in the bootloader segment as uncached */
+       sFabricCohNcTestBufferDevVA.ui32Addr |= RGXFW_BOOTLDR_META_ADDR;
+       sFabricCohNcTestBufferDevVA.ui32Addr |= RGXFW_SEGMMU_DATA_META_UNCACHED;
+
+       /* Obtain the META segment addresses corresponding to cached and uncached windows into SLC */
+       ui64SegOutAddrTopCached   = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_CACHED(MMU_CONTEXT_MAPPING_FWIF);
+       ui64SegOutAddrTopUncached = RGXFW_SEGMMU_OUTADDR_TOP_VIVT_SLC_UNCACHED(MMU_CONTEXT_MAPPING_FWIF);
+
+       /* At the top level, we perform snoop-miss (i.e. to verify slave port) & snoop-hit (i.e. to verify ACE) test.
+          NOTE: For now, skip snoop-miss test as Services currently forces all firmware allocations to be coherent */
+       for (eTestType = CPU_WRITE_GPU_READ_SH; eTestType <= GPU_WRITE_CPU_READ_SH && bExit == IMG_FALSE; eTestType++)
+       {
+               IMG_CPU_PHYADDR sCpuPhyAddr;
+               IMG_BOOL bValid;
+               PMR *psPMR;
+
+               if (eTestType == CPU_WRITE_GPU_READ_SM)
+               {
+                       /* All snoop miss test must bypass the SLC, here memory is region of coherence so
+                          configure META to use SLC bypass cache policy for the bootloader segment. Note
+                          this cannot be done on a cache-coherent (i.e. CC=1) VA, as this violates ACE
+                          standard as one cannot issue a non-coherent request into the bus fabric for
+                          an allocation's VA that is cache-coherent in SLC, so use non-coherent buffer */
+                       RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
+                                                                       (ui64SegOutAddrTopUncached |  RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
+                       pui32FabricCohTestBufferCpuVA = pui32FabricCohNcTestBufferCpuVA;
+                       psFabricCohTestBufferMemDesc = psFabricCohNcTestBufferMemDesc;
+                       psFabricCohTestBufferDevVA = &sFabricCohNcTestBufferDevVA;
+               }
+               else if (eTestType == CPU_WRITE_GPU_READ_SH)
+               {
+                       /* All snoop hit test must obviously use SLC, here SLC is region of coherence so
+                          configure META not to bypass the SLC for the bootloader segment */
+                       RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
+                                                                       (ui64SegOutAddrTopCached |  RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
+                       pui32FabricCohTestBufferCpuVA = pui32FabricCohCcTestBufferCpuVA;
+                       psFabricCohTestBufferMemDesc = psFabricCohCcTestBufferMemDesc;
+                       psFabricCohTestBufferDevVA = &sFabricCohCcTestBufferDevVA;
+               }
+
+               if (eTestType == GPU_WRITE_CPU_READ_SH &&
+                       !PVRSRVSystemSnoopingOfDeviceCache(psDevInfo->psDeviceNode->psDevConfig))
+               {
+                       /* Cannot perform this test if there is no snooping of device cache */
+                       continue;
+               }
+
+               /* Acquire underlying PMR CpuPA in preparation for cache maintenance */
+               (void) DevmemLocalGetImportHandle(psFabricCohTestBufferMemDesc, (void**)&psPMR);
+               eError = PMR_CpuPhysAddr(psPMR, OSGetPageShift(), 1, 0, &sCpuPhyAddr, &bValid);
+               if (eError != PVRSRV_OK || bValid == IMG_FALSE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "PMR_CpuPhysAddr error: %s, exiting",
+                                       PVRSRVGetErrorString(eError)));
+                       bExit = IMG_TRUE;
+                       continue;
+               }
+
+               /* Here we do two passes mostly to account for the effects of using a different
+                  seed (i.e. ui32OddEvenSeed) value to read and write */
+               for (ui32OddEven = 1; ui32OddEven < 3 && bExit == IMG_FALSE; ui32OddEven++)
+               {
+                       IMG_UINT32 i;
+
+                       /* Do multiple sub-dword cache line tests */
+                       for (i = 0; i < 2 && bExit == IMG_FALSE; i++)
+                       {
+                               IMG_UINT32 ui32FWAddr;
+                               IMG_UINT32 ui32FWValue;
+                               IMG_UINT32 ui32FWValue2;
+                               IMG_UINT32 ui32LastFWValue = ~0;
+                               IMG_UINT32 ui32Offset = i * sizeof(IMG_UINT32);
+
+                               /* Calculate next address and seed value to write/read from slave-port */
+                               ui32FWAddr = psFabricCohTestBufferDevVA->ui32Addr + ui32Offset;
+                               ui32OddEvenSeed += 1;
+
+                               if (eTestType == GPU_WRITE_CPU_READ_SM || eTestType == GPU_WRITE_CPU_READ_SH)
+                               {
+                                       /* Clean dcache to ensure there is no stale data in dcache that might over-write
+                                          what we are about to write via slave-port here because if it drains from the CPU
+                                          dcache before we read it, it would corrupt what we are going to read back via
+                                          the CPU */
+                                       CacheOpValExec(psPMR, 0, ui32Offset, sizeof(IMG_UINT32), PVRSRV_CACHE_OP_CLEAN);
+
+                                       /* Calculate a new value to write */
+                                       ui32FWValue = i + ui32OddEvenSeed;
+
+                                       /* Write the value using the RGX slave-port interface */
+                                       eError = RGXWriteFWModuleAddr(psDevInfo, ui32FWAddr, ui32FWValue);
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "RGXWriteFWModuleAddr error: %s, exiting",
+                                                                PVRSRVGetErrorString(eError)));
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+
+                                       /* Read back value using RGX slave-port interface, this is used
+                                          as a sort of memory barrier for the above write */
+                                       eError = RGXReadFWModuleAddr(psDevInfo, ui32FWAddr, &ui32FWValue2);
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "RGXReadFWModuleAddr error: %s, exiting",
+                                                                PVRSRVGetErrorString(eError)));
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+                                       else if (ui32FWValue != ui32FWValue2)
+                                       {
+                                               //IMG_UINT32 ui32FWValue3;
+                                               //RGXReadFWModuleAddr(psDevInfo, 0xC1F00000, &ui32FWValue3);
+
+                                               /* Fatal error, we should abort */
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "At Offset: %d, RAW via SlavePort failed: expected: %x, got: %x",
+                                                               i,
+                                                               ui32FWValue,
+                                                               ui32FWValue2));
+                                               eError = PVRSRV_ERROR_INIT_FAILURE;
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+
+                                       if (!PVRSRVSystemSnoopingOfDeviceCache(psDevInfo->psDeviceNode->psDevConfig))
+                                       {
+                                               /* Invalidate dcache to ensure that any prefetched data by the CPU from this memory
+                                                  region is discarded before we read (i.e. next read must trigger a cache miss).
+                                                  If there is snooping of device cache, then any prefetching done by the CPU
+                                                  will reflect the most up to date datum writing by GPU into said location,
+                                                  that is to say prefetching must be coherent so CPU d-flush is not needed */
+                                               CacheOpValExec(psPMR, 0, ui32Offset, sizeof(IMG_UINT32), PVRSRV_CACHE_OP_INVALIDATE);
+                                       }
+                               }
+                               else
+                               {
+                                       IMG_UINT32 ui32RAWCpuValue;
+
+                                       /* Ensures line is in dcache */
+                                       ui32FWValue = IMG_UINT32_MAX;
+
+                                       /* Dirty allocation in dcache */
+                                       ui32RAWCpuValue = i + ui32OddEvenSeed;
+                                       pui32FabricCohTestBufferCpuVA[i] = i + ui32OddEvenSeed;
+
+                                       /* Flush possible cpu store-buffer(ing) on LMA */
+                                       OSWriteMemoryBarrier(&pui32FabricCohTestBufferCpuVA[i]);
+
+                                       switch (eTestType)
+                                       {
+                                       case CPU_WRITE_GPU_READ_SM:
+                                               /* Flush dcache to force subsequent incoming CPU-bound snoop to miss so
+                                                  memory is coherent before the SlavePort reads */
+                                               CacheOpValExec(psPMR, 0, ui32Offset, sizeof(IMG_UINT32), PVRSRV_CACHE_OP_FLUSH);
+                                               break;
+                                       default:
+                                               break;
+                                       }
+
+                                       /* Read back value using RGX slave-port interface */
+                                       eError = RGXReadFWModuleAddr(psDevInfo, ui32FWAddr, &ui32FWValue);
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "RGXReadWithSP error: %s, exiting",
+                                                               PVRSRVGetErrorString(eError)));
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+
+                                       /* Being mostly paranoid here, verify that CPU RAW operation is valid
+                                          after the above slave port read */
+                                       CacheOpValExec(psPMR, 0, ui32Offset, sizeof(IMG_UINT32), PVRSRV_CACHE_OP_INVALIDATE);
+                                       if (pui32FabricCohTestBufferCpuVA[i] != ui32RAWCpuValue)
+                                       {
+                                               /* Fatal error, we should abort */
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "At Offset: %d, RAW by CPU failed: expected: %x, got: %x",
+                                                               i,
+                                                               ui32RAWCpuValue,
+                                                               pui32FabricCohTestBufferCpuVA[i]));
+                                               eError = PVRSRV_ERROR_INIT_FAILURE;
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+                               }
+
+                               /* Compare to see if sub-test passed */
+                               if (pui32FabricCohTestBufferCpuVA[i] == ui32FWValue)
+                               {
+#if defined(DEBUG)
+                                       bSubTestPassed = IMG_TRUE;
+#endif
+                               }
+                               else
+                               {
+                                       bFullTestPassed = IMG_FALSE;
+                                       eError = PVRSRV_ERROR_INIT_FAILURE;
+#if defined(DEBUG)
+                                       bSubTestPassed = IMG_FALSE;
+#endif
+                                       if (ui32LastFWValue != ui32FWValue)
+                                       {
+#if defined(DEBUG)
+                                               PVR_LOG(("At Offset: %d, Expected: %x, Got: %x",
+                                                                i,
+                                                                (eTestType & 0x1) ? ui32FWValue : pui32FabricCohTestBufferCpuVA[i],
+                                                                (eTestType & 0x1) ? pui32FabricCohTestBufferCpuVA[i] : ui32FWValue));
+#endif
+                                       }
+                                       else
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "test encountered unexpected error, exiting"));
+                                               eError = PVRSRV_ERROR_INIT_FAILURE;
+                                               bExit = IMG_TRUE;
+                                               continue;
+                                       }
+                               }
+
+                               ui32LastFWValue = (eTestType & 0x1) ? ui32FWValue : pui32FabricCohTestBufferCpuVA[i];
+                       }
+
+#if defined(DEBUG)
+                       bSubTestPassed = bExit ? IMG_FALSE : bSubTestPassed;
+                       switch (eTestType)
+                       {
+                       case CPU_WRITE_GPU_READ_SM:
+                               PVR_LOG(("CPU:Write/GPU:Read Snoop Miss Test: completed [run #%u]: %s",
+                                                ui32OddEven, bSubTestPassed ? "PASSED" : "FAILED"));
+                               break;
+                       case GPU_WRITE_CPU_READ_SM:
+                               PVR_LOG(("GPU:Write/CPU:Read Snoop Miss Test: completed [run #%u]: %s",
+                                                ui32OddEven, bSubTestPassed ? "PASSED" : "FAILED"));
+                               break;
+                       case CPU_WRITE_GPU_READ_SH:
+                               PVR_LOG(("CPU:Write/GPU:Read Snoop Hit Test: completed [run #%u]: %s",
+                                                ui32OddEven, bSubTestPassed ? "PASSED" : "FAILED"));
+                               break;
+                       case GPU_WRITE_CPU_READ_SH:
+                               PVR_LOG(("GPU:Write/CPU:Read Snoop Hit Test: completed [run #%u]: %s",
+                                                ui32OddEven, bSubTestPassed ? "PASSED" : "FAILED"));
+                               break;
+                       default:
+                               PVR_LOG(("Internal error, exiting test"));
+                               eError = PVRSRV_ERROR_INIT_FAILURE;
+                               bExit = IMG_TRUE;
+                               continue;
+                       }
+#endif
+               }
+       }
+
+       /* Release and free NC/CC test buffers */
+       RGXUnsetFirmwareAddress(psFabricCohCcTestBufferMemDesc);
+e5:
+       DevmemReleaseCpuVirtAddr(psFabricCohCcTestBufferMemDesc);
+e4:
+       DevmemFwUnmapAndFree(psDevInfo, psFabricCohCcTestBufferMemDesc);
+
+e3:
+       RGXUnsetFirmwareAddress(psFabricCohNcTestBufferMemDesc);
+e2:
+       DevmemReleaseCpuVirtAddr(psFabricCohNcTestBufferMemDesc);
+e1:
+       DevmemFwUnmapAndFree(psDevInfo, psFabricCohNcTestBufferMemDesc);
+
+e0:
+       /* Restore bootloader segment settings */
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_MMCU_SEGMENTn_OUTA1(6),
+                                (ui64SegOutAddrTopCached | RGXFW_BOOTLDR_DEVV_ADDR) >> 32);
+
+       bFullTestPassed = bExit ? IMG_FALSE: bFullTestPassed;
+       if (bFullTestPassed)
+       {
+               PVR_LOG(("fabric coherency test: PASSED"));
+               psDevInfo->ui32CoherencyTestsDone = MAX_NUM_COHERENCY_TESTS + 1;
+       }
+       else
+       {
+               PVR_LOG(("fabric coherency test: FAILED"));
+               psDevInfo->ui32CoherencyTestsDone++;
+       }
+
+       return eError;
+}
+
+IMG_BOOL RGXDeviceHasErnBrn(const void *hPrivate, IMG_UINT64 ui64ErnsBrns)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       return (psDevInfo->sDevFeatureCfg.ui64ErnsBrns & ui64ErnsBrns) != 0;
+}
+
+IMG_UINT32 RGXGetDeviceSLCBanks(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       if (!RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, SLC_BANKS))
+       {
+               return 0;
+       }
+       return RGX_GET_FEATURE_VALUE(psDevInfo, SLC_BANKS);
+}
+
+IMG_UINT32 RGXGetDeviceCacheLineSize(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       if (!RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, SLC_CACHE_LINE_SIZE_BITS))
+       {
+               return 0;
+       }
+       return RGX_GET_FEATURE_VALUE(psDevInfo, SLC_CACHE_LINE_SIZE_BITS);
+}
+
+void RGXAcquireBootCodeAddr(const void *hPrivate, IMG_DEV_VIRTADDR *psBootCodeAddr)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+       *psBootCodeAddr = psDevInfo->sFWCodeDevVAddrBase;
+}
+
+void RGXAcquireBootDataAddr(const void *hPrivate, IMG_DEV_VIRTADDR *psBootDataAddr)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psDevInfo = ((RGX_LAYER_PARAMS*)hPrivate)->psDevInfo;
+
+       *psBootDataAddr = psDevInfo->sFWDataDevVAddrBase;
+}
+
+IMG_BOOL RGXDeviceAckIrq(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+
+       PVR_ASSERT(hPrivate != NULL);
+       psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       psDevInfo = psParams->psDevInfo;
+
+       return (psDevInfo->pfnRGXAckIrq != NULL) ?
+                       psDevInfo->pfnRGXAckIrq(psDevInfo) : IMG_TRUE;
+}
@@ -1,8 +1,8 @@
 /*************************************************************************/ /*!
 @File
-@Title          System Description Header
+@Title          Header for DDK implementation of the Services abstraction layer
 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    This header provides system-specific declarations and macros
+@Description    Header for DDK implementation of the Services abstraction layer
 @License        Dual MIT/GPLv2
 
 The contents of this file are subject to the MIT license as set out below.
@@ -41,17 +41,21 @@ 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(SYSINFO_H)
-#define SYSINFO_H
+#if !defined(RGXLAYER_IMPL_H)
+#define RGXLAYER_IMPL_H
 
-/*!< System specific poll/timeout details */
-#define MAX_HW_TIME_US                           (500000)
-#define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT  (1500)//(10000)
-#define DEVICES_WATCHDOG_POWER_OFF_SLEEP_TIMEOUT (3600000)
-#define WAIT_TRY_COUNT                           (10000)
+#include "rgxlayer.h"
+#include "device_connection.h"
 
-#if defined(__linux__)
-#define SYS_RGX_DEV_NAME    "rgxnohw"
+typedef struct _RGX_LAYER_PARAMS_
+{
+       void *psDevInfo;
+       void *psDevConfig;
+#if defined(PDUMP)
+       IMG_UINT32 ui32PdumpFlags;
 #endif
 
-#endif /* !defined(SYSINFO_H) */
+       IMG_DEV_PHYADDR sPCAddr;
+} RGX_LAYER_PARAMS;
+
+#endif /* RGXLAYER_IMPL_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.c
new file mode 100644 (file)
index 0000000..8d13954
--- /dev/null
@@ -0,0 +1,1272 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific MMU initialisation
+@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.
+ */ /**************************************************************************/
+#include "rgxmmuinit.h"
+#include "rgxmmudefs_km.h"
+
+#include "rgxdevice.h"
+#include "img_types.h"
+#include "img_defs.h"
+#include "mmu_common.h"
+#include "pdump_mmu.h"
+
+#include "pvr_debug.h"
+#include "pvrsrv_error.h"
+#include "rgx_memallocflags.h"
+#include "rgx_heaps.h"
+#include "pdump_km.h"
+
+
+/* useful macros */
+/* units represented in a bitfield */
+#define UNITS_IN_BITFIELD(Mask, Shift) ((Mask >> Shift) + 1)
+
+
+/*
+ * Bits of PT, PD and PC not involving addresses
+ */
+
+
+
+/* protection bits for MMU_VERSION <= 3 */
+#define RGX_MMUCTRL_PTE_PROTMASK       (RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_EN | \
+               ~RGX_MMUCTRL_PT_DATA_AXCACHE_CLRMSK | \
+               RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_EN | \
+               RGX_MMUCTRL_PT_DATA_PM_SRC_EN | \
+               RGX_MMUCTRL_PT_DATA_CC_EN | \
+               RGX_MMUCTRL_PT_DATA_READ_ONLY_EN | \
+               RGX_MMUCTRL_PT_DATA_VALID_EN)
+
+#define RGX_MMUCTRL_PDE_PROTMASK       (RGX_MMUCTRL_PD_DATA_ENTRY_PENDING_EN | \
+               ~RGX_MMUCTRL_PD_DATA_PAGE_SIZE_CLRMSK | \
+               RGX_MMUCTRL_PD_DATA_VALID_EN)
+
+#define RGX_MMUCTRL_PCE_PROTMASK       (RGX_MMUCTRL_PC_DATA_ENTRY_PENDING_EN | \
+               RGX_MMUCTRL_PC_DATA_VALID_EN)
+
+
+/*
+ * protection bits for MMU_VERSION >= 4
+ * MMU4 has no PENDING or PAGE_SIZE fields in PxE
+ */
+#define RGX_MMU4CTRL_PTE_PROTMASK      (RGX_MMUCTRL_PTE_PROTMASK & ~RGX_MMUCTRL_PT_DATA_ENTRY_PENDING_EN)
+
+#define RGX_MMU4CTRL_PDE_PROTMASK      (RGX_MMUCTRL_PD_DATA_VALID_EN)
+
+#define RGX_MMU4CTRL_PCE_PROTMASK      (RGX_MMUCTRL_PC_DATA_VALID_EN)
+
+
+
+
+static MMU_PxE_CONFIG sRGXMMUPCEConfig;
+static MMU_DEVVADDR_CONFIG sRGXMMUTopLevelDevVAddrConfig;
+
+
+/*
+ *
+ *  Configuration for heaps with 4kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_4KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_4KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_4KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig4KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 16kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_16KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_16KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_16KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig16KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 64kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_64KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_64KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_64KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig64KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 256kB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_256KBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_256KBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_256KBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig256KB;
+
+
+/*
+ *
+ *  Configuration for heaps with 1MB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_1MBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_1MBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_1MBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig1MB;
+
+
+/*
+ *
+ *  Configuration for heaps with 2MB Data-Page size
+ *
+ */
+
+static MMU_PxE_CONFIG sRGXMMUPDEConfig_2MBDP;
+static MMU_PxE_CONFIG sRGXMMUPTEConfig_2MBDP;
+static MMU_DEVVADDR_CONFIG sRGXMMUDevVAddrConfig_2MBDP;
+static MMU_PAGESIZECONFIG gsPageSizeConfig2MB;
+
+
+/* Forward declaration of protection bits derivation functions, for
+   the following structure */
+static IMG_UINT64 RGXDerivePCEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePCEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePDEProt4(IMG_UINT32 uiProtFlags);
+static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static IMG_UINT32 RGXDerivePTEProt4(IMG_UINT32 uiProtFlags);
+
+/* protection bits derivation functions for MMUv4 */
+static IMG_UINT64 RGXMMU4DerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize);
+static PVRSRV_ERROR RGXMMU4GetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize);
+static PVRSRV_ERROR RGXMMU4GetPageSizeFromVirtAddr(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+                                                                                                  IMG_DEV_VIRTADDR sDevVAddr,
+                                                                                                  IMG_UINT32 *pui32Log2PageSize);
+
+
+static PVRSRV_ERROR RGXGetPageSizeConfigCB(IMG_UINT32 uiLog2DataPageSize,
+               const MMU_PxE_CONFIG **ppsMMUPDEConfig,
+               const MMU_PxE_CONFIG **ppsMMUPTEConfig,
+               const MMU_DEVVADDR_CONFIG **ppsMMUDevVAddrConfig,
+               IMG_HANDLE *phPriv);
+
+static PVRSRV_ERROR RGXPutPageSizeConfigCB(IMG_HANDLE hPriv);
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE4(IMG_UINT32 ui32PDE, IMG_UINT32 *pui32Log2PageSize);
+static PVRSRV_ERROR RGXGetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize);
+
+static MMU_DEVICEATTRIBS sRGXMMUDeviceAttributes;
+
+PVRSRV_ERROR RGXMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       IMG_BOOL bHaveMMU4 = (RGX_GET_FEATURE_VALUE(psDevInfo, MMU_VERSION) >= 4);
+
+       /* Setup of Px Entries:
+        *
+        *
+        * PAGE TABLE (8 Byte):
+        *
+        * | 62              | 61...40         | 39...12 (varies) | 11...6          | 5             | 4      | 3               | 2               | 1         | 0     |
+        * | PM/Meta protect | VP Page (39:18) | Physical Page    | VP Page (17:12) | Entry Pending | PM src | SLC Bypass Ctrl | Cache Coherency | Read Only | Valid |
+        *
+        *
+        * PAGE DIRECTORY (8 Byte):
+        *
+        *  | 40            | 39...5  (varies)        | 4          | 3...1     | 0     |
+        *  | Entry Pending | Page Table base address | (reserved) | Page Size | Valid |
+        *
+        *
+        * PAGE CATALOGUE (4 Byte):
+        *
+        *  | 31...4                      | 3...2      | 1             | 0     |
+        *  | Page Directory base address | (reserved) | Entry Pending | Valid |
+        *
+        */
+
+
+       /* Example how to get the PD address from a PC entry.
+        * The procedure is the same for PD and PT entries to retrieve PT and Page addresses:
+        *
+        * 1) sRGXMMUPCEConfig.uiAddrMask applied to PC entry with '&':
+        *  | 31...4   | 3...2      | 1             | 0     |
+        *  | PD Addr  | 0          | 0             | 0     |
+        *
+        * 2) sRGXMMUPCEConfig.uiAddrShift applied with '>>':
+        *  | 27...0   |
+        *  | PD Addr  |
+        *
+        * 3) sRGXMMUPCEConfig.uiAddrLog2Align applied with '<<':
+        *  | 39...0   |
+        *  | PD Addr  |
+        *
+        */
+
+
+       sRGXMMUDeviceAttributes.pszMMUPxPDumpMemSpaceName =
+                       PhysHeapPDumpMemspaceName(psDeviceNode->apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL]);
+
+       /*
+        * Setup sRGXMMUPCEConfig
+        */
+       sRGXMMUPCEConfig.uiBytesPerEntry = 4;     /* 32 bit entries */
+       sRGXMMUPCEConfig.uiAddrMask = 0xfffffff0; /* Mask to get significant address bits of PC entry i.e. the address of the PD */
+
+       sRGXMMUPCEConfig.uiAddrShift = 4;         /* Shift this many bits to get PD address */
+       sRGXMMUPCEConfig.uiAddrLog2Align = 12;    /* Alignment of PD physical addresses. */
+
+       sRGXMMUPCEConfig.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PCE_PROTMASK : RGX_MMUCTRL_PCE_PROTMASK; /* Mask to get the status bits */
+       sRGXMMUPCEConfig.uiProtShift = 0;                       /* Shift this many bits to get the status bits */
+
+       sRGXMMUPCEConfig.uiValidEnMask = RGX_MMUCTRL_PC_DATA_VALID_EN;     /* Mask to get entry valid bit of the PC */
+       sRGXMMUPCEConfig.uiValidEnShift = RGX_MMUCTRL_PC_DATA_VALID_SHIFT; /* Shift this many bits to get entry valid bit */
+
+       /*
+        *  Setup sRGXMMUTopLevelDevVAddrConfig
+        */
+       sRGXMMUTopLevelDevVAddrConfig.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK; /* Mask to get PC index applied to a 40 bit virt. device address */
+       sRGXMMUTopLevelDevVAddrConfig.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;  /* Shift a 40 bit virt. device address by this amount to get the PC index */
+       sRGXMMUTopLevelDevVAddrConfig.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUTopLevelDevVAddrConfig.uiPCIndexMask,
+                       sRGXMMUTopLevelDevVAddrConfig.uiPCIndexShift));
+
+       sRGXMMUTopLevelDevVAddrConfig.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK; /* Mask to get PD index applied to a 40 bit virt. device address */
+       sRGXMMUTopLevelDevVAddrConfig.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;  /* Shift a 40 bit virt. device address by this amount to get the PD index */
+       sRGXMMUTopLevelDevVAddrConfig.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUTopLevelDevVAddrConfig.uiPDIndexMask,
+                       sRGXMMUTopLevelDevVAddrConfig.uiPDIndexShift));
+
+       /*
+        *
+        *  Configuration for heaps with 4kB Data-Page size
+        *
+        */
+
+       /*
+        * Setup sRGXMMUPDEConfig_4KBDP
+        */
+       sRGXMMUPDEConfig_4KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_4KBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       sRGXMMUPDEConfig_4KBDP.uiAddrShift = 12;
+       sRGXMMUPDEConfig_4KBDP.uiAddrLog2Align = 12;
+
+       sRGXMMUPDEConfig_4KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_4KBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_4KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_4KBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_4KBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_4KBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUPTEConfig_4KBDP
+        */
+       sRGXMMUPTEConfig_4KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_4KBDP.uiAddrMask = IMG_UINT64_C(0xfffffff000);
+       sRGXMMUPTEConfig_4KBDP.uiAddrShift = 12;
+       sRGXMMUPTEConfig_4KBDP.uiAddrLog2Align = 12; /* Alignment of the physical addresses of the pages NOT PTs */
+
+       sRGXMMUPTEConfig_4KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_4KBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_4KBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_4KBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_4KBDP
+        */
+       sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_4KBDP.uiPCIndexShift));
+
+       sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_4KBDP.uiPDIndexShift));
+
+       sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexMask = ~RGX_MMUCTRL_VADDR_PT_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexShift = RGX_MMUCTRL_VADDR_PT_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_4KBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_4KBDP.uiPTIndexShift));
+
+       sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetMask = IMG_UINT64_C(0x0000000fff);
+       sRGXMMUDevVAddrConfig_4KBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_4KBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig4KB
+        */
+       gsPageSizeConfig4KB.psPDEConfig = &sRGXMMUPDEConfig_4KBDP;
+       gsPageSizeConfig4KB.psPTEConfig = &sRGXMMUPTEConfig_4KBDP;
+       gsPageSizeConfig4KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_4KBDP;
+       gsPageSizeConfig4KB.uiRefCount = 0;
+       gsPageSizeConfig4KB.uiMaxRefCount = 0;
+
+
+       /*
+        *
+        *  Configuration for heaps with 16kB Data-Page size
+        *
+        */
+
+       /*
+        * Setup sRGXMMUPDEConfig_16KBDP
+        */
+       sRGXMMUPDEConfig_16KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_16KBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       sRGXMMUPDEConfig_16KBDP.uiAddrShift = 10;
+       sRGXMMUPDEConfig_16KBDP.uiAddrLog2Align = 10;
+
+       sRGXMMUPDEConfig_16KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_16KBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_16KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_16KBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_16KBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_16KBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUPTEConfig_16KBDP
+        */
+       sRGXMMUPTEConfig_16KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_16KBDP.uiAddrMask = IMG_UINT64_C(0xffffffc000);
+       sRGXMMUPTEConfig_16KBDP.uiAddrShift = 14;
+       sRGXMMUPTEConfig_16KBDP.uiAddrLog2Align = 14;
+
+       sRGXMMUPTEConfig_16KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_16KBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_16KBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_16KBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_16KBDP
+        */
+       sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_16KBDP.uiPCIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_16KBDP.uiPDIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001fc000);
+       sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexShift = 14;
+       sRGXMMUDevVAddrConfig_16KBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_16KBDP.uiPTIndexShift));
+
+       sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetMask = IMG_UINT64_C(0x0000003fff);
+       sRGXMMUDevVAddrConfig_16KBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_16KBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig16KB
+        */
+       gsPageSizeConfig16KB.psPDEConfig = &sRGXMMUPDEConfig_16KBDP;
+       gsPageSizeConfig16KB.psPTEConfig = &sRGXMMUPTEConfig_16KBDP;
+       gsPageSizeConfig16KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_16KBDP;
+       gsPageSizeConfig16KB.uiRefCount = 0;
+       gsPageSizeConfig16KB.uiMaxRefCount = 0;
+
+
+       /*
+        *
+        *  Configuration for heaps with 64kB Data-Page size
+        *
+        */
+
+       /*
+        * Setup sRGXMMUPDEConfig_64KBDP
+        */
+       sRGXMMUPDEConfig_64KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_64KBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       sRGXMMUPDEConfig_64KBDP.uiAddrShift = 8;
+       sRGXMMUPDEConfig_64KBDP.uiAddrLog2Align = 8;
+
+       sRGXMMUPDEConfig_64KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_64KBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_64KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_64KBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_64KBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_64KBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUPTEConfig_64KBDP
+        */
+       sRGXMMUPTEConfig_64KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_64KBDP.uiAddrMask = IMG_UINT64_C(0xffffff0000);
+       sRGXMMUPTEConfig_64KBDP.uiAddrShift = 16;
+       sRGXMMUPTEConfig_64KBDP.uiAddrLog2Align = 16;
+
+       sRGXMMUPTEConfig_64KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_64KBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_64KBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_64KBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_64KBDP
+        */
+       sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_64KBDP.uiPCIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_64KBDP.uiPDIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001f0000);
+       sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexShift = 16;
+       sRGXMMUDevVAddrConfig_64KBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_64KBDP.uiPTIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetMask = IMG_UINT64_C(0x000000ffff);
+       sRGXMMUDevVAddrConfig_64KBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_64KBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig64KB
+        */
+       gsPageSizeConfig64KB.psPDEConfig = &sRGXMMUPDEConfig_64KBDP;
+       gsPageSizeConfig64KB.psPTEConfig = &sRGXMMUPTEConfig_64KBDP;
+       gsPageSizeConfig64KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_64KBDP;
+       gsPageSizeConfig64KB.uiRefCount = 0;
+       gsPageSizeConfig64KB.uiMaxRefCount = 0;
+
+
+       /*
+        *
+        *  Configuration for heaps with 256kB Data-Page size
+        *
+        */
+
+       /*
+        * Setup sRGXMMUPDEConfig_256KBDP
+        */
+       sRGXMMUPDEConfig_256KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_256KBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       sRGXMMUPDEConfig_256KBDP.uiAddrShift = 6;
+       sRGXMMUPDEConfig_256KBDP.uiAddrLog2Align = 6;
+
+       sRGXMMUPDEConfig_256KBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_256KBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_256KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_256KBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_256KBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_256KBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup MMU_PxE_CONFIG sRGXMMUPTEConfig_256KBDP
+        */
+       sRGXMMUPTEConfig_256KBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_256KBDP.uiAddrMask = IMG_UINT64_C(0xfffffc0000);
+       sRGXMMUPTEConfig_256KBDP.uiAddrShift = 18;
+       sRGXMMUPTEConfig_256KBDP.uiAddrLog2Align = 18;
+
+       sRGXMMUPTEConfig_256KBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_256KBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_256KBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_256KBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_256KBDP
+        */
+       sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_256KBDP.uiPCIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_256KBDP.uiPDIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexMask = IMG_UINT64_C(0x00001c0000);
+       sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexShift = 18;
+       sRGXMMUDevVAddrConfig_256KBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_256KBDP.uiPTIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetMask = IMG_UINT64_C(0x000003ffff);
+       sRGXMMUDevVAddrConfig_256KBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_256KBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig256KB
+        */
+       gsPageSizeConfig256KB.psPDEConfig = &sRGXMMUPDEConfig_256KBDP;
+       gsPageSizeConfig256KB.psPTEConfig = &sRGXMMUPTEConfig_256KBDP;
+       gsPageSizeConfig256KB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_256KBDP;
+       gsPageSizeConfig256KB.uiRefCount = 0;
+       gsPageSizeConfig256KB.uiMaxRefCount = 0;
+
+       /*
+        * Setup sRGXMMUPDEConfig_1MBDP
+        */
+       sRGXMMUPDEConfig_1MBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_1MBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       /*
+        * The hardware requires that PT tables need be 1<<6 = 64 byte aligned even
+        * if they contain fewer entries.
+        */
+       sRGXMMUPDEConfig_1MBDP.uiAddrShift = 6;
+       sRGXMMUPDEConfig_1MBDP.uiAddrLog2Align = 6;
+
+       sRGXMMUPDEConfig_1MBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_1MBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_1MBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_1MBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_1MBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_1MBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUPTEConfig_1MBDP
+        */
+       sRGXMMUPTEConfig_1MBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_1MBDP.uiAddrMask = IMG_UINT64_C(0xfffff00000);
+       sRGXMMUPTEConfig_1MBDP.uiAddrShift = 20;
+       sRGXMMUPTEConfig_1MBDP.uiAddrLog2Align = 20;
+
+       sRGXMMUPTEConfig_1MBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_1MBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_1MBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_1MBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_1MBDP
+        */
+       sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_1MBDP.uiPCIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_1MBDP.uiPDIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexMask = IMG_UINT64_C(0x0000100000);
+       sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexShift = 20;
+       sRGXMMUDevVAddrConfig_1MBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_1MBDP.uiPTIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetMask = IMG_UINT64_C(0x00000fffff);
+       sRGXMMUDevVAddrConfig_1MBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_1MBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig1MB
+        */
+       gsPageSizeConfig1MB.psPDEConfig = &sRGXMMUPDEConfig_1MBDP;
+       gsPageSizeConfig1MB.psPTEConfig = &sRGXMMUPTEConfig_1MBDP;
+       gsPageSizeConfig1MB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_1MBDP;
+       gsPageSizeConfig1MB.uiRefCount = 0;
+       gsPageSizeConfig1MB.uiMaxRefCount = 0;
+
+       /*
+        * Setup sRGXMMUPDEConfig_2MBDP
+        */
+       sRGXMMUPDEConfig_2MBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPDEConfig_2MBDP.uiAddrMask = IMG_UINT64_C(0xfffffffff0);
+       /*
+        * The hardware requires that PT tables need be 1<<6 = 64 byte aligned even
+        * if they contain fewer entries.
+        */
+       sRGXMMUPDEConfig_2MBDP.uiAddrShift = 6;
+       sRGXMMUPDEConfig_2MBDP.uiAddrLog2Align = 6;
+
+       sRGXMMUPDEConfig_2MBDP.uiVarCtrlMask = IMG_UINT64_C(0x000000000e);
+       sRGXMMUPDEConfig_2MBDP.uiVarCtrlShift = 1;
+
+       sRGXMMUPDEConfig_2MBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PDE_PROTMASK : RGX_MMUCTRL_PDE_PROTMASK;
+       sRGXMMUPDEConfig_2MBDP.uiProtShift = 0;
+
+       sRGXMMUPDEConfig_2MBDP.uiValidEnMask = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       sRGXMMUPDEConfig_2MBDP.uiValidEnShift = RGX_MMUCTRL_PD_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUPTEConfig_2MBDP
+        */
+       sRGXMMUPTEConfig_2MBDP.uiBytesPerEntry = 8;
+
+       sRGXMMUPTEConfig_2MBDP.uiAddrMask = IMG_UINT64_C(0xffffe00000);
+       sRGXMMUPTEConfig_2MBDP.uiAddrShift = 21;
+       sRGXMMUPTEConfig_2MBDP.uiAddrLog2Align = 21;
+
+       sRGXMMUPTEConfig_2MBDP.uiProtMask = bHaveMMU4 ? RGX_MMU4CTRL_PTE_PROTMASK : RGX_MMUCTRL_PTE_PROTMASK;
+       sRGXMMUPTEConfig_2MBDP.uiProtShift = 0;
+
+       sRGXMMUPTEConfig_2MBDP.uiValidEnMask = RGX_MMUCTRL_PT_DATA_VALID_EN;
+       sRGXMMUPTEConfig_2MBDP.uiValidEnShift = RGX_MMUCTRL_PT_DATA_VALID_SHIFT;
+
+       /*
+        * Setup sRGXMMUDevVAddrConfig_2MBDP
+        */
+       sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexMask = ~RGX_MMUCTRL_VADDR_PC_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexShift = RGX_MMUCTRL_VADDR_PC_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPC = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexMask,
+                       sRGXMMUDevVAddrConfig_2MBDP.uiPCIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexMask = ~RGX_MMUCTRL_VADDR_PD_INDEX_CLRMSK;
+       sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexShift = RGX_MMUCTRL_VADDR_PD_INDEX_SHIFT;
+       sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPD = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexMask,
+                       sRGXMMUDevVAddrConfig_2MBDP.uiPDIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexMask = IMG_UINT64_C(0x0000000000);
+       sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexShift = 21;
+       sRGXMMUDevVAddrConfig_2MBDP.uiNumEntriesPT = TRUNCATE_64BITS_TO_32BITS(UNITS_IN_BITFIELD(sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexMask,
+                       sRGXMMUDevVAddrConfig_2MBDP.uiPTIndexShift));
+
+
+       sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetMask = IMG_UINT64_C(0x00001fffff);
+       sRGXMMUDevVAddrConfig_2MBDP.uiPageOffsetShift = 0;
+       sRGXMMUDevVAddrConfig_2MBDP.uiOffsetInBytes = 0;
+
+       /*
+        * Setup gsPageSizeConfig2MB
+        */
+       gsPageSizeConfig2MB.psPDEConfig = &sRGXMMUPDEConfig_2MBDP;
+       gsPageSizeConfig2MB.psPTEConfig = &sRGXMMUPTEConfig_2MBDP;
+       gsPageSizeConfig2MB.psDevVAddrConfig = &sRGXMMUDevVAddrConfig_2MBDP;
+       gsPageSizeConfig2MB.uiRefCount = 0;
+       gsPageSizeConfig2MB.uiMaxRefCount = 0;
+
+       /*
+        * Setup sRGXMMUDeviceAttributes
+        */
+       sRGXMMUDeviceAttributes.eMMUType = PDUMP_MMU_TYPE_VARPAGE_40BIT;
+       sRGXMMUDeviceAttributes.eTopLevel = MMU_LEVEL_3;
+       sRGXMMUDeviceAttributes.ui32BaseAlign = RGX_MMUCTRL_PC_DATA_PD_BASE_ALIGNSHIFT;
+       sRGXMMUDeviceAttributes.psBaseConfig = &sRGXMMUPCEConfig;
+       sRGXMMUDeviceAttributes.psTopLevelDevVAddrConfig = &sRGXMMUTopLevelDevVAddrConfig;
+
+       /* Functions for deriving page table/dir/cat protection bits */
+       sRGXMMUDeviceAttributes.pfnDerivePCEProt8 = RGXDerivePCEProt8;
+       sRGXMMUDeviceAttributes.pfnDerivePCEProt4 = RGXDerivePCEProt4;
+       sRGXMMUDeviceAttributes.pfnDerivePDEProt8 = RGXDerivePDEProt8;
+       sRGXMMUDeviceAttributes.pfnDerivePDEProt4 = RGXDerivePDEProt4;
+       sRGXMMUDeviceAttributes.pfnDerivePTEProt8 = RGXDerivePTEProt8;
+       sRGXMMUDeviceAttributes.pfnDerivePTEProt4 = RGXDerivePTEProt4;
+
+       /* Functions for establishing configurations for PDE/PTE/DEVVADDR
+          on per-heap basis */
+       sRGXMMUDeviceAttributes.pfnGetPageSizeConfiguration = RGXGetPageSizeConfigCB;
+       sRGXMMUDeviceAttributes.pfnPutPageSizeConfiguration = RGXPutPageSizeConfigCB;
+
+       sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE4 = RGXGetPageSizeFromPDE4;
+       sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE8 = RGXGetPageSizeFromPDE8;
+       sRGXMMUDeviceAttributes.pfnGetPageSizeFromVirtAddr = NULL;
+
+       if (bHaveMMU4)
+       {
+               /* override some of these functions for MMU4 as page size is not stored in PD entries */
+               sRGXMMUDeviceAttributes.pfnDerivePDEProt8 = RGXMMU4DerivePDEProt8;
+               sRGXMMUDeviceAttributes.pfnGetPageSizeFromPDE8 = RGXMMU4GetPageSizeFromPDE8;
+               sRGXMMUDeviceAttributes.pfnGetPageSizeFromVirtAddr = RGXMMU4GetPageSizeFromVirtAddr;
+       }
+
+       psDeviceNode->psMMUDevAttrs = &sRGXMMUDeviceAttributes;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       eError = PVRSRV_OK;
+
+#if defined(PDUMP)
+       psDeviceNode->pfnMMUGetContextID = NULL;
+#endif
+
+       psDeviceNode->psMMUDevAttrs = NULL;
+
+#if defined(DEBUG)
+       PVR_DPF((PVR_DBG_MESSAGE, "Variable Page Size Heap Stats:"));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 4K page heaps: %d",
+                       gsPageSizeConfig4KB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 4K page heaps (should be 0): %d",
+                       gsPageSizeConfig4KB.uiRefCount));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 16K page heaps: %d",
+                       gsPageSizeConfig16KB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 16K page heaps (should be 0): %d",
+                       gsPageSizeConfig16KB.uiRefCount));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 64K page heaps: %d",
+                       gsPageSizeConfig64KB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 64K page heaps (should be 0): %d",
+                       gsPageSizeConfig64KB.uiRefCount));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 256K page heaps: %d",
+                       gsPageSizeConfig256KB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 256K page heaps (should be 0): %d",
+                       gsPageSizeConfig256KB.uiRefCount));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 1M page heaps: %d",
+                       gsPageSizeConfig1MB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 1M page heaps (should be 0): %d",
+                       gsPageSizeConfig1MB.uiRefCount));
+       PVR_DPF((PVR_DBG_MESSAGE, "Max 2M page heaps: %d",
+                       gsPageSizeConfig2MB.uiMaxRefCount));
+       PVR_DPF((PVR_DBG_VERBOSE, "Current 2M page heaps (should be 0): %d",
+                       gsPageSizeConfig2MB.uiRefCount));
+#endif
+       if (gsPageSizeConfig4KB.uiRefCount > 0 ||
+                       gsPageSizeConfig16KB.uiRefCount > 0 ||
+                       gsPageSizeConfig64KB.uiRefCount > 0 ||
+                       gsPageSizeConfig256KB.uiRefCount > 0 ||
+                       gsPageSizeConfig1MB.uiRefCount > 0 ||
+                       gsPageSizeConfig2MB.uiRefCount > 0
+       )
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXMMUInit_Unregister: Unbalanced MMU API Usage (Internal error)"));
+       }
+
+       return eError;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXMMUInit_GetConfigRangeValue
+@Description    Helper Function
+                               For a given virtual address range and page size, return the
+                               value to load into an MMU_PAGE_SIZE_RANGE config register.
+@Return         64-bit register value
+*/ /**************************************************************************/
+IMG_UINT64 RGXMMUInit_GetConfigRangeValue(IMG_UINT32 ui32DataPageSize, IMG_UINT64 ui64BaseAddress, IMG_UINT64 ui64RangeSize)
+{
+       /* end address of range is inclusive */
+       IMG_UINT64 ui64EndAddress = ui64BaseAddress + ui64RangeSize - (1 << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_ALIGNSHIFT);
+       IMG_UINT64 ui64RegValue = 0;
+
+       switch (ui32DataPageSize)
+       {
+               case 16*1024:
+                       ui64RegValue = 1;
+                       break;
+               case 64*1024:
+                       ui64RegValue = 2;
+                       break;
+               case 256*1024:
+                       ui64RegValue = 3;
+                       break;
+               case 1024*1024:
+                       ui64RegValue = 4;
+                       break;
+               case 2*1024*1024:
+                       ui64RegValue = 5;
+                       break;
+               case 4*1024:
+                       /* fall through */
+               default:
+                       /* anything we don't support, use 4K */
+                       break;
+    }
+
+       /* check that the range is defined by valid 40 bit virtual addresses */
+       PVR_ASSERT((ui64BaseAddress & ~((1ULL << 40) - 1)) == 0);
+       PVR_ASSERT((ui64EndAddress  & ~((1ULL << 40) - 1)) == 0);
+
+       /* the range config register addresses are in 2MB chunks so check 21 lsb are zero */
+       PVR_ASSERT((ui64BaseAddress & ((1 << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_ALIGNSHIFT) - 1)) == 0);
+       PVR_ASSERT((ui64EndAddress  & ((1 << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_ALIGNSHIFT)  - 1)) == 0);
+
+       ui64BaseAddress >>= RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_ALIGNSHIFT;
+       ui64EndAddress  >>= RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_ALIGNSHIFT;
+
+       ui64RegValue = (ui64RegValue << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_PAGE_SIZE_SHIFT) |
+                                  (ui64EndAddress  << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_SHIFT) |
+                                  (ui64BaseAddress << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_SHIFT);
+       return ui64RegValue;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePCEProt4
+@Description    calculate the PCE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT32 RGXDerivePCEProt4(IMG_UINT32 uiProtFlags)
+{
+       return (uiProtFlags & MMU_PROTFLAGS_INVALID)?0:RGX_MMUCTRL_PC_DATA_VALID_EN;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePCEProt8
+@Description    calculate the PCE protection flags based on an 8 byte entry
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT64 RGXDerivePCEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+       PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+       PVR_UNREFERENCED_PARAMETER(uiLog2DataPageSize);
+
+       PVR_DPF((PVR_DBG_ERROR, "8-byte PCE not supported on this device"));
+       return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePDEProt4
+@Description    derive the PDE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT32 RGXDerivePDEProt4(IMG_UINT32 uiProtFlags)
+{
+       PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+       PVR_DPF((PVR_DBG_ERROR, "4-byte PDE not supported on this device"));
+       return 0;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePDEProt8
+@Description    derive the PDE protection flags based on an 8 byte entry
+
+@Input          uiLog2DataPageSize The log2 of the required page size.
+                E.g, for 4KiB pages, this parameter must be 12.
+                For 2MiB pages, it must be set to 21.
+
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT64 RGXDerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+       IMG_UINT64 ret_value = 0; /* 0 means invalid */
+
+       if (!(uiProtFlags & MMU_PROTFLAGS_INVALID)) /* if not invalid */
+       {
+               switch (uiLog2DataPageSize)
+               {
+               case RGX_HEAP_4KB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB;
+                       break;
+               case RGX_HEAP_16KB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB;
+                       break;
+               case RGX_HEAP_64KB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB;
+                       break;
+               case RGX_HEAP_256KB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB;
+                       break;
+               case RGX_HEAP_1MB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB;
+                       break;
+               case RGX_HEAP_2MB_PAGE_SHIFT:
+                       ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN | RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB;
+                       break;
+               default:
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s:%d: in function<%s>: Invalid parameter log2_page_size. Expected {12, 14, 16, 18, 20, 21}. Got [%u]",
+                                       __FILE__, __LINE__, __func__, uiLog2DataPageSize));
+               }
+       }
+       return ret_value;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePTEProt4
+@Description    calculate the PTE protection flags based on a 4 byte entry
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT32 RGXDerivePTEProt4(IMG_UINT32 uiProtFlags)
+{
+       PVR_UNREFERENCED_PARAMETER(uiProtFlags);
+       PVR_DPF((PVR_DBG_ERROR, "4-byte PTE not supported on this device"));
+
+       return 0;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXDerivePTEProt8
+@Description    calculate the PTE protection flags based on an 8 byte entry
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static IMG_UINT64 RGXDerivePTEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+       IMG_UINT64 ui64MMUFlags=0;
+
+       PVR_UNREFERENCED_PARAMETER(uiLog2DataPageSize);
+
+       if (((MMU_PROTFLAGS_READABLE|MMU_PROTFLAGS_WRITEABLE) & uiProtFlags) == (MMU_PROTFLAGS_READABLE|MMU_PROTFLAGS_WRITEABLE))
+       {
+               /* read/write */
+       }
+       else if (MMU_PROTFLAGS_READABLE & uiProtFlags)
+       {
+               /* read only */
+               ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_READ_ONLY_EN;
+       }
+       else if (MMU_PROTFLAGS_WRITEABLE & uiProtFlags)
+       {
+               /* write only */
+               PVR_DPF((PVR_DBG_WARNING, "RGXDerivePTEProt8: write-only is not possible on this device"));
+       }
+       else if ((MMU_PROTFLAGS_INVALID & uiProtFlags) == 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXDerivePTEProt8: neither read nor write specified..."));
+       }
+
+       /* cache coherency */
+       if (MMU_PROTFLAGS_CACHE_COHERENT & uiProtFlags)
+       {
+               ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_CC_EN;
+       }
+
+       if ((uiProtFlags & MMU_PROTFLAGS_INVALID) == 0)
+       {
+               ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_VALID_EN;
+       }
+
+       if (MMU_PROTFLAGS_DEVICE(PMMETA_PROTECT) & uiProtFlags)
+       {
+               ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_PM_META_PROTECT_EN;
+       }
+
+       /**
+        * Always enable caching on the fabric level cache irrespective of type of
+        * cache coherent interconnect and memory cache attributes.
+        * This needs to be updated, if selective caching policy needs to be
+        * implemented based on cache attributes requested by caller and based on
+        * cache coherent interconnect.
+        */
+       ui64MMUFlags |= RGX_MMUCTRL_PT_DATA_AXCACHE_WBRWALLOC;
+
+       return ui64MMUFlags;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXGetPageSizeConfig
+@Description    Set up configuration for variable sized data pages.
+                RGXPutPageSizeConfigCB has to be called to ensure correct
+                refcounting.
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static PVRSRV_ERROR RGXGetPageSizeConfigCB(IMG_UINT32 uiLog2DataPageSize,
+               const MMU_PxE_CONFIG **ppsMMUPDEConfig,
+               const MMU_PxE_CONFIG **ppsMMUPTEConfig,
+               const MMU_DEVVADDR_CONFIG **ppsMMUDevVAddrConfig,
+               IMG_HANDLE *phPriv)
+{
+       MMU_PAGESIZECONFIG *psPageSizeConfig;
+
+       switch (uiLog2DataPageSize)
+       {
+       case RGX_HEAP_4KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig4KB;
+               break;
+       case RGX_HEAP_16KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig16KB;
+               break;
+       case RGX_HEAP_64KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig64KB;
+               break;
+       case RGX_HEAP_256KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig256KB;
+               break;
+       case RGX_HEAP_1MB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig1MB;
+               break;
+       case RGX_HEAP_2MB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig2MB;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                               "RGXGetPageSizeConfigCB: Invalid Data Page Size 1<<0x%x",
+                               uiLog2DataPageSize));
+               *phPriv = NULL;
+               return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+       }
+
+       /* Refer caller's pointers to the data */
+       *ppsMMUPDEConfig = psPageSizeConfig->psPDEConfig;
+       *ppsMMUPTEConfig = psPageSizeConfig->psPTEConfig;
+       *ppsMMUDevVAddrConfig = psPageSizeConfig->psDevVAddrConfig;
+
+#if defined(SUPPORT_MMU_PAGESIZECONFIG_REFCOUNT)
+       /* Increment ref-count - not that we're allocating anything here
+       (I'm using static structs), but one day we might, so we want
+       the Get/Put code to be balanced properly */
+       psPageSizeConfig->uiRefCount++;
+
+       /* This is purely for debug statistics */
+       psPageSizeConfig->uiMaxRefCount = MAX(psPageSizeConfig->uiMaxRefCount,
+                       psPageSizeConfig->uiRefCount);
+#endif
+
+       *phPriv = (IMG_HANDLE)(uintptr_t)uiLog2DataPageSize;
+       PVR_ASSERT (uiLog2DataPageSize == (IMG_UINT32)(uintptr_t)*phPriv);
+
+       return PVRSRV_OK;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXPutPageSizeConfig
+@Description    Tells this code that the mmu module is done with the
+                configurations set in RGXGetPageSizeConfig.  This can
+                be a no-op.
+                Called after RGXGetPageSizeConfigCB.
+@Return         PVRSRV_ERROR
+ */ /**************************************************************************/
+static PVRSRV_ERROR RGXPutPageSizeConfigCB(IMG_HANDLE hPriv)
+{
+#if defined(SUPPORT_MMU_PAGESIZECONFIG_REFCOUNT)
+       MMU_PAGESIZECONFIG *psPageSizeConfig;
+       IMG_UINT32 uiLog2DataPageSize;
+
+       uiLog2DataPageSize = (IMG_UINT32)(uintptr_t) hPriv;
+
+       switch (uiLog2DataPageSize)
+       {
+       case RGX_HEAP_4KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig4KB;
+               break;
+       case RGX_HEAP_16KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig16KB;
+               break;
+       case RGX_HEAP_64KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig64KB;
+               break;
+       case RGX_HEAP_256KB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig256KB;
+               break;
+       case RGX_HEAP_1MB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig1MB;
+               break;
+       case RGX_HEAP_2MB_PAGE_SHIFT:
+               psPageSizeConfig = &gsPageSizeConfig2MB;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                               "RGXPutPageSizeConfigCB: Invalid Data Page Size 1<<0x%x",
+                               uiLog2DataPageSize));
+               return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+       }
+
+       /* Ref-count here is not especially useful, but it's an extra
+          check that the API is being used correctly */
+       psPageSizeConfig->uiRefCount--;
+#else
+       PVR_UNREFERENCED_PARAMETER(hPriv);
+#endif
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE4(IMG_UINT32 ui32PDE, IMG_UINT32 *pui32Log2PageSize)
+{
+       PVR_UNREFERENCED_PARAMETER(ui32PDE);
+       PVR_UNREFERENCED_PARAMETER(pui32Log2PageSize);
+       PVR_DPF((PVR_DBG_ERROR, "4-byte PDE not supported on this device"));
+       return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+}
+
+static PVRSRV_ERROR RGXGetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize)
+{
+       IMG_UINT64 ui64PageSizeBits = ui64PDE & (~RGX_MMUCTRL_PD_DATA_PAGE_SIZE_CLRMSK);
+
+       switch (ui64PageSizeBits)
+       {
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_4KB:
+               *pui32Log2PageSize = RGX_HEAP_4KB_PAGE_SHIFT;
+               break;
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_16KB:
+               *pui32Log2PageSize = RGX_HEAP_16KB_PAGE_SHIFT;
+               break;
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_64KB:
+               *pui32Log2PageSize = RGX_HEAP_64KB_PAGE_SHIFT;
+               break;
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_256KB:
+               *pui32Log2PageSize = RGX_HEAP_256KB_PAGE_SHIFT;
+               break;
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_1MB:
+               *pui32Log2PageSize = RGX_HEAP_1MB_PAGE_SHIFT;
+               break;
+       case RGX_MMUCTRL_PD_DATA_PAGE_SIZE_2MB:
+               *pui32Log2PageSize = RGX_HEAP_2MB_PAGE_SHIFT;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR,
+                               "RGXGetPageSizeFromPDE8: Invalid page size bitfield %" IMG_UINT64_FMTSPECx " in PDE",
+                               ui64PageSizeBits));
+
+               return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+       }
+       return PVRSRV_OK;
+}
+
+
+
+
+/*************************************************************************/ /*!
+@Function       RGXMMU4DerivePDEProt8
+@Description    derive the PDE protection flags based on an 8 byte entry
+
+@Input          uiLog2DataPageSize: ignored as MMU4 doesn't put page size in PD entries.
+
+@Return         PVRSRV_ERROR
+*/ /**************************************************************************/
+static IMG_UINT64 RGXMMU4DerivePDEProt8(IMG_UINT32 uiProtFlags, IMG_UINT32 uiLog2DataPageSize)
+{
+       IMG_UINT64 ret_value = 0; /* 0 means invalid */
+       PVR_UNREFERENCED_PARAMETER(uiLog2DataPageSize);
+
+       if (!(uiProtFlags & MMU_PROTFLAGS_INVALID)) /* if not invalid */
+       {
+               /*  page size in range config registers. Bits in PD entries are reserved */
+               ret_value = RGX_MMUCTRL_PD_DATA_VALID_EN;
+       }
+       return ret_value;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXMMU4GetPageSizeFromPDE8
+@Description    The upper layers should be such that this function is never called
+                as pages size are not stored in PD entries for MMU4.
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXMMU4GetPageSizeFromPDE8(IMG_UINT64 ui64PDE, IMG_UINT32 *pui32Log2PageSize)
+{
+       PVR_UNREFERENCED_PARAMETER(ui64PDE);
+       PVR_UNREFERENCED_PARAMETER(pui32Log2PageSize);
+
+       PVR_ASSERT(0 && "RGXMMU4GetPageSizeFromPDE8 called in error. MMU4 does not store page sizes in PDT.");
+       return PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+}
+
+
+/*************************************************************************/ /*!
+@Function       RGXMMU4GetPageSizeFromVirtAddr
+@Description    Get page size by walking through range config registers
+                looking for a match against the virtual address.
+*/ /**************************************************************************/
+static PVRSRV_ERROR RGXMMU4GetPageSizeFromVirtAddr(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+                                                                                                  IMG_DEV_VIRTADDR sDevVAddr,
+                                                                                                  IMG_UINT32 *pui32Log2PageSize)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 i;
+
+       /* assume default of 4KB page size */
+       *pui32Log2PageSize = 12;
+
+       /* Loop through the range registers looking for the given target address */
+       for (i = 0; i < ARRAY_SIZE(psDevInfo->aui64MMUPageSizeRangeValue); ++i)
+       {
+               IMG_UINT64 ui64RangeVal = psDevInfo->aui64MMUPageSizeRangeValue[i];
+
+               if (ui64RangeVal != 0)
+               {
+                       /* end addr in register is inclusive in the range so add 1 to move it over the end */
+                       IMG_UINT64 ui64Base = ((ui64RangeVal & ~RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_CLRMSK)
+                                                                                               >> RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_SHIFT)
+                                                                                               << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_BASE_ADDR_ALIGNSHIFT;
+                       IMG_UINT64 ui64End  = (((ui64RangeVal & ~RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_CLRMSK)
+                                                                                               >> RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_SHIFT) + 1)
+                                                                                               << RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_END_ADDR_ALIGNSHIFT;
+
+                       if ((sDevVAddr.uiAddr >= ui64Base) && (sDevVAddr.uiAddr < ui64End))
+                       {
+                               IMG_UINT32 ui32PageSizeField = (IMG_UINT32)((ui64RangeVal & ~RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_PAGE_SIZE_CLRMSK)
+                                                                                                               >> RGX_CR_MMU_PAGE_SIZE_RANGE_ONE_PAGE_SIZE_SHIFT);
+                               if (ui32PageSizeField < 5)
+                               {
+                                       *pui32Log2PageSize = (ui32PageSizeField << 1) + 12;   /* 12 (4K), 14 (16K), 16 (64K), 18 (256K), 20 (1MB) */
+                               }
+                               else if (ui32PageSizeField == 5)
+                               {
+                                       *pui32Log2PageSize = 21;    /* 2MB */
+                               }
+                               else
+                               {
+                                       eError = PVRSRV_ERROR_MMU_INVALID_PAGE_SIZE_FOR_DEVICE;
+                               }
+                               break;
+                       }
+               }
+       }
+
+       return eError;
+}
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmmuinit.h
new file mode 100644 (file)
index 0000000..6e0c52e
--- /dev/null
@@ -0,0 +1,61 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific MMU initialisation
+@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.
+*/ /**************************************************************************/
+
+/* NB: this file is not to be included arbitrarily.  It exists solely
+   for the linkage between rgxinit.c and rgxmmuinit.c, the former
+   being otherwise cluttered by the contents of the latter */
+
+#ifndef SRVKM_RGXMMUINIT_H
+#define SRVKM_RGXMMUINIT_H
+
+#include "device.h"
+#include "img_types.h"
+#include "mmu_common.h"
+#include "img_defs.h"
+
+PVRSRV_ERROR RGXMMUInit_Register(PVRSRV_DEVICE_NODE *psDeviceNode);
+PVRSRV_ERROR RGXMMUInit_Unregister(PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_UINT64 RGXMMUInit_GetConfigRangeValue(IMG_UINT32 ui32DataPageSize, IMG_UINT64 ui64BaseAddress, IMG_UINT64 ui64RangeSize);
+
+#endif /* #ifndef SRVKM_RGXMMUINIT_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmulticore.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxmulticore.c
new file mode 100644 (file)
index 0000000..ab6fe58
--- /dev/null
@@ -0,0 +1,216 @@
+/*************************************************************************/ /*!
+@File           rgxmulticore.c
+@Title          Functions related to multicore devices
+@Codingstyle    IMG
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Kernel mode workload estimation functionality.
+@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.
+*/ /**************************************************************************/
+
+#include "rgxdevice.h"
+#include "rgxdefs_km.h"
+#include "pdump_km.h"
+#include "rgxmulticore.h"
+#include "multicore_defs.h"
+#include "allocmem.h"
+#include "pvr_debug.h"
+
+
+
+static PVRSRV_ERROR RGXGetMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        IMG_UINT32 ui32CapsSize,
+                                        IMG_UINT32 *pui32NumCores,
+                                        IMG_UINT64 *pui64Caps);
+
+
+/*
+ * RGXInitMultiCoreInfo:
+ * Return multicore information to clients.
+ * Return not supported on cores without multicore.
+ */
+static PVRSRV_ERROR RGXGetMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 IMG_UINT32 ui32CapsSize,
+                                 IMG_UINT32 *pui32NumCores,
+                                 IMG_UINT64 *pui64Caps)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (psDeviceNode->ui32MultiCoreNumCores == 0)
+       {
+               /* MULTICORE not supported on this device */
+               eError = PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+       else
+       {
+               *pui32NumCores = psDeviceNode->ui32MultiCoreNumCores;
+               if (ui32CapsSize > 0)
+               {
+                       if (ui32CapsSize < psDeviceNode->ui32MultiCoreNumCores)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "Multicore caps buffer too small"));
+                               eError = PVRSRV_ERROR_BRIDGE_BUFFER_TOO_SMALL;
+                       }
+                       else
+                       {
+                               IMG_UINT32 i;
+
+                               for (i = 0; i < psDeviceNode->ui32MultiCoreNumCores; ++i)
+                               {
+                                       pui64Caps[i] = psDeviceNode->pui64MultiCoreCapabilities[i];
+                               }
+                       }
+               }
+       }
+
+       return eError;
+}
+
+
+
+/*
+ * RGXInitMultiCoreInfo:
+ * Read multicore HW registers and fill in data structure for clients.
+ * Return not_supported on cores without multicore.
+ */
+PVRSRV_ERROR RGXInitMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       if (psDeviceNode->pfnGetMultiCoreInfo != NULL)
+       {
+               /* we only set this up once */
+               return PVRSRV_OK;
+       }
+
+       /* defaults for non-multicore devices */
+       psDeviceNode->ui32MultiCoreNumCores = 0;
+       psDeviceNode->ui32MultiCorePrimaryId = (IMG_UINT32)(-1);
+       psDeviceNode->pui64MultiCoreCapabilities = NULL;
+       psDeviceNode->pfnGetMultiCoreInfo = NULL;
+
+       if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_MULTICORE_SUPPORT))
+       {
+               IMG_UINT32 ui32MulticoreInfo;
+               IMG_UINT32 ui32PrimaryCoreIds;
+               IMG_UINT32 ui32PrimaryId;
+               IMG_UINT32 ui32TotalCores;
+               IMG_UINT32 ui32NumCores;
+               IMG_UINT32 id, i;
+
+               ui32NumCores = (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MULTICORE_DOMAIN)
+                                                           & ~RGX_CR_MULTICORE_DOMAIN_GPU_COUNT_CLRMSK)
+                                                           >> RGX_CR_MULTICORE_DOMAIN_GPU_COUNT_SHIFT;
+
+               ui32TotalCores = (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MULTICORE_SYSTEM)
+                                                           & ~RGX_CR_MULTICORE_SYSTEM_GPU_COUNT_CLRMSK)
+                                                           >> RGX_CR_MULTICORE_SYSTEM_GPU_COUNT_SHIFT;
+               ui32MulticoreInfo = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MULTICORE);
+#if defined(NO_HARDWARE)
+               /* override to defaults if no hardware */
+               ui32NumCores = 8;//RGX_MULTICORE_MAX_NOHW_CORES;
+               ui32TotalCores = RGX_MULTICORE_MAX_NOHW_CORES;
+               ui32MulticoreInfo = 0;  /* primary id 0 with 7 secondaries */
+#endif
+               /* ID for this primary is in this register */
+               ui32PrimaryId = (ui32MulticoreInfo & ~RGX_CR_MULTICORE_ID_CLRMSK) >> RGX_CR_MULTICORE_ID_SHIFT;
+
+               /* allocate storage for capabilities */
+               psDeviceNode->pui64MultiCoreCapabilities = OSAllocMem(ui32NumCores * sizeof(psDeviceNode->pui64MultiCoreCapabilities[0]));
+               if (psDeviceNode->pui64MultiCoreCapabilities == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to alloc memory for Multicore info", __func__));
+                       return PVRSRV_ERROR_OUT_OF_MEMORY;
+               }
+
+               ui32PrimaryCoreIds = (ui32MulticoreInfo & ~RGX_CR_MULTICORE_PRIMARY_CORE_ID_CLRMSK)
+                                                       >> RGX_CR_MULTICORE_PRIMARY_CORE_ID_SHIFT;
+
+               psDeviceNode->ui32MultiCorePrimaryId = ui32PrimaryId;
+               psDeviceNode->ui32MultiCoreNumCores = ui32NumCores;
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Multicore domain has %d cores with primary id %u\n", ui32NumCores, ui32PrimaryId));
+               PDUMPCOMMENT(psDeviceNode,
+                            "RGX Multicore domain has %d cores with primary id %u\n",
+                            ui32NumCores, ui32PrimaryId);
+               for (i = 0, id = 0; id < ui32TotalCores; ++id)
+               {
+                       if ((ui32PrimaryCoreIds & 0x7) == ui32PrimaryId)
+                       {
+                               /* currently all cores are identical so have the same capabilities */
+                               psDeviceNode->pui64MultiCoreCapabilities[i] = id
+                                                   | ((id == ui32PrimaryId) ? RGX_MULTICORE_CAPABILITY_PRIMARY_EN : 0)
+                                                   | RGX_MULTICORE_CAPABILITY_GEOMETRY_EN
+                                                   | RGX_MULTICORE_CAPABILITY_COMPUTE_EN
+                                                   | RGX_MULTICORE_CAPABILITY_FRAGMENT_EN;
+                               PDUMPCOMMENT(psDeviceNode, "\tCore %u has caps 0x%08x", id,
+                                            (IMG_UINT32)psDeviceNode->pui64MultiCoreCapabilities[i]);
+                               PVR_DPF((PVR_DBG_MESSAGE, "Core %u has caps 0x%08x", id, (IMG_UINT32)psDeviceNode->pui64MultiCoreCapabilities[i]));
+                               ++i;
+                       }
+                       ui32PrimaryCoreIds >>= 3;
+               }
+
+               /* Register callback to return info about multicore setup to client bridge */
+               psDeviceNode->pfnGetMultiCoreInfo = RGXGetMultiCoreInfo;
+       }
+       else
+       {
+               /* MULTICORE not supported on this device */
+               eError = PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       return eError;
+}
+
+
+/*
+ * RGXDeinitMultiCoreInfo:
+ * Release resources and clear the MultiCore values in the DeviceNode.
+ */
+void RGXDeInitMultiCoreInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       if (psDeviceNode->pui64MultiCoreCapabilities != NULL)
+       {
+               OSFreeMem(psDeviceNode->pui64MultiCoreCapabilities);
+               psDeviceNode->pui64MultiCoreCapabilities = NULL;
+               psDeviceNode->ui32MultiCoreNumCores = 0;
+               psDeviceNode->ui32MultiCorePrimaryId = (IMG_UINT32)(-1);
+       }
+       psDeviceNode->pfnGetMultiCoreInfo = NULL;
+}
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpdump.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpdump.c
new file mode 100644 (file)
index 0000000..bca6a9b
--- /dev/null
@@ -0,0 +1,642 @@
+/*************************************************************************/ /*!
+@File           rgxpdump.c
+@Title          Device specific pdump routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific pdump functions
+@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(PDUMP)
+#include "pvrsrv.h"
+#include "devicemem_pdump.h"
+#include "rgxpdump.h"
+#include "pdumpdesc.h"
+#if defined(SUPPORT_VALIDATION)
+#include "validation_soc.h"
+#include "rgxtbdefs.h"
+#endif
+
+/*
+ * There are two different set of functions one for META/RISCV and one for MIPS
+ * because the Pdump player does not implement the support for
+ * the MIPS MMU yet. So for MIPS builds we cannot use DevmemPDumpSaveToFileVirtual,
+ * we have to use DevmemPDumpSaveToFile instead.
+ */
+static PVRSRV_ERROR _FWDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
+                                             PVRSRV_DEVICE_NODE *psDeviceNode,
+                                             IMG_UINT32 ui32PDumpFlags)
+{
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       PDUMPIF(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+       PDUMPELSE(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+
+#if defined(SUPPORT_FIRMWARE_GCOV)
+       /* Gcov */
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Gcov Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psFirmwareGcovBufferMemDesc,
+                                                                        0,
+                                                                        psDevInfo->ui32FirmwareGcovSize,
+                                                                        "firmware_gcov.img",
+                                                                        0,
+                                                                        ui32PDumpFlags);
+#endif
+       /* TDM signatures */
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TDM signatures and checksums Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigTDMChecksMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32SigTDMChecksSize,
+                                                                "out.2dsig",
+                                                                0,
+                                                                ui32PDumpFlags);
+
+       /* TA signatures */
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump TA signatures and checksums Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigTAChecksMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32SigTAChecksSize,
+                                                                "out.tasig",
+                                                                0,
+                                                                ui32PDumpFlags);
+
+       /* 3D signatures */
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump 3D signatures and checksums Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSig3DChecksMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32Sig3DChecksSize,
+                                                                "out.3dsig",
+                                                                0,
+                                                                ui32PDumpFlags);
+       /* CDM signatures */
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump CDM signatures and checksums Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigCDMChecksMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32SigCDMChecksSize,
+                                                                "out.cdmsig",
+                                                                0,
+                                                                ui32PDumpFlags);
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) &&
+               RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) > 1)
+       {
+               /* RDM signatures */
+               PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump RDM signatures and checksums Buffer");
+               DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWSigRDMChecksMemDesc,
+                                                                       0,
+                                                                       psDevInfo->ui32SigRDMChecksSize,
+                                                                       "out.rdmsig",
+                                                                       0,
+                                                                       ui32PDumpFlags);
+       }
+
+       PDUMPFI(psDeviceNode, "DISABLE_SIGNATURE_BUFFER_DUMP", ui32PDumpFlags);
+
+#if defined(SUPPORT_VALIDATION) && (defined(SUPPORT_TRP) || defined(SUPPORT_WGP) || defined(SUPPORT_FBCDC_SIGNATURE_CHECK))
+       /*
+        *  Validation signatures buffer
+        */
+       PDUMPIF(psDeviceNode, "DISABLE_VALIDATION_CHECKSUM_BUFFER_DUMP", ui32PDumpFlags);
+       PDUMPELSE(psDeviceNode, "DISABLE_VALIDATION_CHECKSUM_BUFFER_DUMP", ui32PDumpFlags);
+
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump validation signatures buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWValidationSigMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32ValidationSigSize,
+                                                                "out.trpsig",
+                                                                0,
+                                                                ui32PDumpFlags);
+
+       PDUMPFI(psDeviceNode, "DISABLE_VALIDATION_CHECKSUM_BUFFER_DUMP", ui32PDumpFlags);
+#endif
+
+       return PVRSRV_OK;
+}
+static PVRSRV_ERROR _FWDumpTraceBufferKM(CONNECTION_DATA * psConnection,
+                                                                                PVRSRV_DEVICE_NODE     *psDeviceNode,
+                                                                                IMG_UINT32                     ui32PDumpFlags)
+{
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       IMG_UINT32      ui32ThreadNum, ui32Size, ui32OutFileOffset;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       /* Dump trace buffers */
+       PDUMPIF(psDeviceNode, "ENABLE_TRACEBUF", ui32PDumpFlags);
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump trace buffers");
+       for (ui32ThreadNum = 0, ui32OutFileOffset = 0; ui32ThreadNum < RGXFW_THREAD_NUM; ui32ThreadNum++)
+       {
+               /*
+                * Some compilers cannot cope with the use of offsetof() below - the specific problem being the use of
+                * a non-const variable in the expression, which it needs to be const. Typical compiler error produced is
+                * "expression must have a constant value".
+                */
+               const IMG_DEVMEM_OFFSET_T uiTraceBufThreadNumOff
+               = (IMG_DEVMEM_OFFSET_T)(uintptr_t)&(((RGXFWIF_TRACEBUF *)0)->sTraceBuf[ui32ThreadNum]);
+
+               /* ui32TracePointer tracepointer */
+               ui32Size = sizeof(IMG_UINT32);
+               DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                                               uiTraceBufThreadNumOff,
+                                                               ui32Size,
+                                                               "out.trace",
+                                                               ui32OutFileOffset,
+                                                               ui32PDumpFlags);
+               ui32OutFileOffset += ui32Size;
+
+               /* next, dump size of trace buffer in DWords */
+               ui32Size = sizeof(IMG_UINT32);
+               DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                                               offsetof(RGXFWIF_TRACEBUF, ui32TraceBufSizeInDWords),
+                                                               ui32Size,
+                                                               "out.trace",
+                                                               ui32OutFileOffset,
+                                                               ui32PDumpFlags);
+               ui32OutFileOffset += ui32Size;
+
+               /* trace buffer */
+               ui32Size = psDevInfo->psRGXFWIfTraceBufCtl->ui32TraceBufSizeInDWords * sizeof(IMG_UINT32);
+               PVR_ASSERT(psDevInfo->psRGXFWIfTraceBufferMemDesc[ui32ThreadNum]);
+               DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufferMemDesc[ui32ThreadNum],
+                                                               0, /* 0 offset in the trace buffer mem desc */
+                                                               ui32Size,
+                                                               "out.trace",
+                                                               ui32OutFileOffset,
+                                                               ui32PDumpFlags);
+               ui32OutFileOffset += ui32Size;
+
+               /* assert info buffer */
+               ui32Size = RGXFW_TRACE_BUFFER_ASSERT_SIZE * sizeof(IMG_CHAR)
+                               + RGXFW_TRACE_BUFFER_ASSERT_SIZE * sizeof(IMG_CHAR)
+                               + sizeof(IMG_UINT32);
+               DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfTraceBufCtlMemDesc,
+                                                               offsetof(RGXFWIF_TRACEBUF, sTraceBuf) /* move to first element of sTraceBuf */
+                                                                       + ui32ThreadNum * sizeof(RGXFWIF_TRACEBUF_SPACE) /* skip required number of sTraceBuf elements */
+                                                                       + offsetof(RGXFWIF_TRACEBUF_SPACE, sAssertBuf), /* offset into its sAssertBuf, to be pdumped */
+                                                               ui32Size,
+                                                               "out.trace",
+                                                               ui32OutFileOffset,
+                                                               ui32PDumpFlags);
+               ui32OutFileOffset += ui32Size;
+       }
+       PDUMPFI(psDeviceNode, "ENABLE_TRACEBUF", ui32PDumpFlags);
+
+       /* FW HWPerf buffer is always allocated when PDUMP is defined, irrespective of HWPerf events being enabled/disabled */
+       PVR_ASSERT(psDevInfo->psRGXFWIfHWPerfBufMemDesc);
+
+       /* Dump hwperf buffer */
+       PDUMPIF(psDeviceNode, "ENABLE_HWPERF", ui32PDumpFlags);
+       PDumpCommentWithFlags(psDeviceNode, ui32PDumpFlags, "** Dump HWPerf Buffer");
+       DevmemPDumpSaveToFileVirtual(psDevInfo->psRGXFWIfHWPerfBufMemDesc,
+                                                                0,
+                                                                psDevInfo->ui32RGXFWIfHWPerfBufSize,
+                                                                "out.hwperf",
+                                                                0,
+                                                                ui32PDumpFlags);
+       PDUMPFI(psDeviceNode, "ENABLE_HWPERF", ui32PDumpFlags);
+
+       return PVRSRV_OK;
+
+}
+
+
+/*
+ * PVRSRVPDumpSignatureBufferKM
+ */
+PVRSRV_ERROR PVRSRVPDumpSignatureBufferKM(CONNECTION_DATA * psConnection,
+                                          PVRSRV_DEVICE_NODE   *psDeviceNode,
+                                          IMG_UINT32                   ui32PDumpFlags)
+{
+       if (psDeviceNode->pfnCheckDeviceFeature)
+       {
+               return _FWDumpSignatureBufferKM(psConnection,
+                                                                               psDeviceNode,
+                                                                               ui32PDumpFlags);
+       }
+
+       return PVRSRV_OK;
+}
+
+#if defined(SUPPORT_VALIDATION)
+PVRSRV_ERROR PVRSRVPDumpComputeCRCSignatureCheckKM(CONNECTION_DATA * psConnection,
+                                                   PVRSRV_DEVICE_NODE * psDeviceNode,
+                                                   IMG_UINT32 ui32PDumpFlags)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       if (!(RGX_IS_FEATURE_SUPPORTED(psDevInfo, COMPUTE)))
+       {
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       /*
+        * Add a PDUMP POLL on the KZ signature check status.
+        */
+       if (psDevInfo->ui32ValidationFlags & RGX_VAL_KZ_SIG_CHECK_NOERR_EN)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Verify KZ Signature: match required");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
+                                    RGX_CR_SCRATCH11,
+                                    1U,
+                                    0xFFFFFFFF,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+       }
+       else if (psDevInfo->ui32ValidationFlags & RGX_VAL_KZ_SIG_CHECK_ERR_EN)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Verify KZ Signature: mismatch required");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
+                                    RGX_CR_SCRATCH11,
+                                    2U,
+                                    0xFFFFFFFF,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+       }
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       return PVRSRV_OK;
+}
+#endif
+
+PVRSRV_ERROR PVRSRVPDumpCRCSignatureCheckKM(CONNECTION_DATA * psConnection,
+                                            PVRSRV_DEVICE_NODE * psDeviceNode,
+                                            IMG_UINT32 ui32PDumpFlags)
+{
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_FBCDC_SIGNATURE_CHECK)
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       /*
+        * Add a PDUMP POLL on the FBC/FBDC signature check status.
+        */
+       if (psDevInfo->ui32ValidationFlags & RGX_VAL_FBDC_SIG_CHECK_NOERR_EN)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Verify FBCDC Signature: match required");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
+                                    RGX_CR_FBCDC_STATUS,
+                                    0,
+                                    0xFFFFFFFF,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_PDUMPREG_NAME,
+                                    RGX_CR_FBCDC_SIGNATURE_STATUS,
+                                    0,
+                                    0xFFFFFFFF,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+       }
+       else if (psDevInfo->ui32ValidationFlags & RGX_VAL_FBDC_SIG_CHECK_ERR_EN)
+       {
+               static char pszVar1[] = ":SYSMEM:$2";
+               static char pszVar2[] = ":SYSMEM:$3";
+               char *pszLoopCondition;
+
+               /*
+                * Do:
+                *  v1 = [RGX_CR_FBCDC_STATUS]
+                *  v2 = [RGX_CR_FBCDC_SIGNATURE_STATUS]
+                * While (v1 OR v2) == 0
+                */
+               PDUMPCOMMENT(psDeviceNode, "Verify FBCDC Signature: mismatch required");
+               eError = PDumpInternalValCondStr(&pszLoopCondition,
+                                    pszVar1,
+                                    0,
+                                    0xFFFFFFFF,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Unable to write pdump verification sequence (%d)", __func__, eError));
+               }
+               else
+               {
+                       eError = PDumpStartDoLoopKM(psDeviceNode, ui32PDumpFlags);
+
+                       eError = PDumpRegRead32ToInternalVar(psDeviceNode,
+                                                                RGX_PDUMPREG_NAME,
+                                                                RGX_CR_FBCDC_STATUS,
+                                                                pszVar1,
+                                                                ui32PDumpFlags);
+
+                       eError = PDumpRegRead32ToInternalVar(psDeviceNode,
+                                                                RGX_PDUMPREG_NAME,
+                                                                RGX_CR_FBCDC_SIGNATURE_STATUS,
+                                                                pszVar2,
+                                                                ui32PDumpFlags);
+
+                       eError = PDumpWriteVarORVarOp(psDeviceNode, pszVar1, pszVar2, ui32PDumpFlags);
+                       eError = PDumpEndDoWhileLoopKM(psDeviceNode, pszLoopCondition, ui32PDumpFlags);
+                       OSFreeMem(pszLoopCondition);
+               }
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif /* SUPPORT_VALIDATION */
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       return PVRSRV_OK;
+}
+
+
+/*
+ * PVRSRVPDumpValCheckPreCommand
+ */
+PVRSRV_ERROR PVRSRVPDumpValCheckPreCommandKM(CONNECTION_DATA * psConnection,
+                                             PVRSRV_DEVICE_NODE * psDeviceNode,
+                                             IMG_UINT32 ui32PDumpFlags)
+{
+#if defined(SUPPORT_VALIDATION)
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       //if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_STATE_PIN) &&
+       if    (psDevInfo->ui32ValidationFlags & RGX_VAL_GPUSTATEPIN_EN)
+       {
+               /*
+                * Add a PDUMP POLL on the GPU_STATE inactive status.
+                */
+               PDUMPCOMMENT(psDeviceNode, "Verify GPU system status: INACTIVE");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_TB_PDUMPREG_NAME,
+                                    RGX_TB_SYSTEM_STATUS,
+                                    0,
+                                    ~RGX_TB_SYSTEM_STATUS_GPU_STATE_CLRMSK,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_EQUAL);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVPDumpValCheckPostCommand
+ */
+PVRSRV_ERROR PVRSRVPDumpValCheckPostCommandKM(CONNECTION_DATA * psConnection,
+                                              PVRSRV_DEVICE_NODE * psDeviceNode,
+                                              IMG_UINT32 ui32PDumpFlags)
+{
+#if defined(SUPPORT_VALIDATION)
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       //if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, GPU_STATE_PIN) &&
+       if    (psDevInfo->ui32ValidationFlags & RGX_VAL_GPUSTATEPIN_EN)
+       {
+               /*
+                * Add a PDUMP POLL on the GPU_STATE active status.
+                */
+               PDUMPCOMMENT(psDeviceNode, "Verify GPU system status: ACTIVE");
+               eError = PDUMPREGPOL(psDeviceNode,
+                                    RGX_TB_PDUMPREG_NAME,
+                                    RGX_TB_SYSTEM_STATUS,
+                                    0,
+                                    ~RGX_TB_SYSTEM_STATUS_GPU_STATE_CLRMSK,
+                                    ui32PDumpFlags,
+                                    PDUMP_POLL_OPERATOR_NOTEQUAL);
+       }
+#else
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+#endif
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVPDumpTraceBufferKM(CONNECTION_DATA *psConnection,
+                                      PVRSRV_DEVICE_NODE *psDeviceNode,
+                                      IMG_UINT32 ui32PDumpFlags)
+{
+       if (psDeviceNode->pfnCheckDeviceFeature)
+       {
+               return _FWDumpTraceBufferKM(psConnection, psDeviceNode, ui32PDumpFlags);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXPDumpPrepareOutputImageDescriptorHdr(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                       IMG_UINT32 ui32HeaderSize,
+                                                                       IMG_UINT32 ui32DataSize,
+                                                                       IMG_UINT32 ui32LogicalWidth,
+                                                                       IMG_UINT32 ui32LogicalHeight,
+                                                                       IMG_UINT32 ui32PhysicalWidth,
+                                                                       IMG_UINT32 ui32PhysicalHeight,
+                                                                       PDUMP_PIXEL_FORMAT ePixFmt,
+                                                                       IMG_MEMLAYOUT eMemLayout,
+                                                                       IMG_FB_COMPRESSION eFBCompression,
+                                                                       const IMG_UINT32 *paui32FBCClearColour,
+                                                                       PDUMP_FBC_SWIZZLE eFBCSwizzle,
+                                                                       IMG_PBYTE abyPDumpDesc)
+{
+       IMG_PUINT32 pui32Word;
+       IMG_UINT32 ui32HeaderDataSize;
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       /* Validate parameters */
+       if (((IMAGE_HEADER_SIZE & ~(HEADER_WORD1_SIZE_CLRMSK >> HEADER_WORD1_SIZE_SHIFT)) != 0) ||
+               ((IMAGE_HEADER_VERSION & ~(HEADER_WORD1_VERSION_CLRMSK >> HEADER_WORD1_VERSION_SHIFT)) != 0))
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       memset(abyPDumpDesc, 0, IMAGE_HEADER_SIZE);
+
+       pui32Word = IMG_OFFSET_ADDR(abyPDumpDesc, 0);
+       pui32Word[0] = (IMAGE_HEADER_TYPE << HEADER_WORD0_TYPE_SHIFT);
+       pui32Word[1] = (IMAGE_HEADER_SIZE << HEADER_WORD1_SIZE_SHIFT) |
+                                  (IMAGE_HEADER_VERSION << HEADER_WORD1_VERSION_SHIFT);
+
+       ui32HeaderDataSize = ui32DataSize;
+       if (eFBCompression != IMG_FB_COMPRESSION_NONE)
+       {
+               ui32HeaderDataSize += ui32HeaderSize;
+       }
+       pui32Word[2] = ui32HeaderDataSize << HEADER_WORD2_DATA_SIZE_SHIFT;
+
+       pui32Word[3] = ui32LogicalWidth << IMAGE_HEADER_WORD3_LOGICAL_WIDTH_SHIFT;
+       pui32Word[4] = ui32LogicalHeight << IMAGE_HEADER_WORD4_LOGICAL_HEIGHT_SHIFT;
+
+       pui32Word[5] = ePixFmt << IMAGE_HEADER_WORD5_FORMAT_SHIFT;
+
+       pui32Word[6] = ui32PhysicalWidth << IMAGE_HEADER_WORD6_PHYSICAL_WIDTH_SHIFT;
+       pui32Word[7] = ui32PhysicalHeight << IMAGE_HEADER_WORD7_PHYSICAL_HEIGHT_SHIFT;
+
+       pui32Word[8] = IMAGE_HEADER_WORD8_STRIDE_POSITIVE | IMAGE_HEADER_WORD8_BIFTYPE_NONE;
+
+       switch (eMemLayout)
+       {
+       case IMG_MEMLAYOUT_STRIDED:
+               pui32Word[8] |= IMAGE_HEADER_WORD8_TWIDDLING_STRIDED;
+               break;
+       case IMG_MEMLAYOUT_TWIDDLED:
+               pui32Word[8] |= IMAGE_HEADER_WORD8_TWIDDLING_ZTWIDDLE;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR, "Unsupported memory layout - %d", eMemLayout));
+               return PVRSRV_ERROR_UNSUPPORTED_MEMORY_LAYOUT;
+       }
+
+       switch (eFBCompression)
+       {
+       case IMG_FB_COMPRESSION_NONE:
+               break;
+       case IMG_FB_COMPRESSION_DIRECT_PACKED_8x8:
+       case IMG_FB_COMPRESSION_DIRECT_8x8:
+       case IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8:
+               pui32Word[8] |= IMAGE_HEADER_WORD8_FBCTYPE_8X8;
+               break;
+       case IMG_FB_COMPRESSION_DIRECT_16x4:
+       case IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4:
+               pui32Word[8] |= IMAGE_HEADER_WORD8_FBCTYPE_16x4;
+               break;
+       case IMG_FB_COMPRESSION_DIRECT_32x2:
+       case IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2:
+               /* Services Client guards against unsupported FEATURE_FB_CDC_32x2.
+                  We should never pass through the UM|KM bridge on cores lacking the feature.
+               */
+               pui32Word[8] |= IMAGE_HEADER_WORD8_FBCTYPE_32x2;
+               break;
+       default:
+               PVR_DPF((PVR_DBG_ERROR, "Unsupported compression mode - %d", eFBCompression));
+               return PVRSRV_ERROR_UNSUPPORTED_FB_COMPRESSION_MODE;
+       }
+
+       pui32Word[9] = 0;
+
+       if (eFBCompression != IMG_FB_COMPRESSION_NONE)
+       {
+               if ((RGX_GET_FEATURE_VALUE(psDevInfo, FBCDC) == 4) || (RGX_GET_FEATURE_VALUE(psDevInfo, FBCDC) == 5))
+               {
+                       pui32Word[9] |= IMAGE_HEADER_WORD9_FBCCOMPAT_V4;
+
+                       if (eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_8x8  ||
+                               eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_16x4 ||
+                               eFBCompression == IMG_FB_COMPRESSION_DIRECT_LOSSY50_32x2)
+                       {
+                               pui32Word[9] |= IMAGE_HEADER_WORD9_LOSSY_ON;
+                       }
+
+                       pui32Word[9] |= (eFBCSwizzle << IMAGE_HEADER_WORD9_SWIZZLE_SHIFT) & IMAGE_HEADER_WORD9_SWIZZLE_CLRMSK;
+               }
+               else /* 3 or 3.1 */
+               {
+                       IMG_BOOL bIsFBC31 = psDevInfo->psRGXFWIfFwSysData->
+                                       ui32ConfigFlags & RGXFWIF_INICFG_FBCDC_V3_1_EN;
+
+                       if (bIsFBC31)
+                       {
+                               pui32Word[9] |= IMAGE_HEADER_WORD9_FBCCOMPAT_V3_1_LAYOUT2;
+                       }
+                       else
+                       {
+                               pui32Word[9] |= IMAGE_HEADER_WORD9_FBCCOMPAT_V3_0_LAYOUT2;
+                       }
+               }
+
+               pui32Word[9] |= IMAGE_HEADER_WORD9_FBCDECOR_ENABLE;
+       }
+
+       pui32Word[10] = paui32FBCClearColour[0];
+       pui32Word[11] = paui32FBCClearColour[1];
+       pui32Word[12] = (IMG_UINT32) (psDeviceNode->ui64FBCClearColour & 0xFFFFFFFF);
+       pui32Word[13] = (IMG_UINT32) (psDeviceNode->ui64FBCClearColour >> 32);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXPDumpPrepareOutputDataDescriptorHdr(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                       IMG_UINT32 ui32HeaderType,
+                                                                       IMG_UINT32 ui32DataSize,
+                                                                       IMG_UINT32 ui32ElementType,
+                                                                       IMG_UINT32 ui32ElementCount,
+                                                                       IMG_PBYTE pbyPDumpDataHdr)
+{
+       IMG_PUINT32 pui32Word;
+
+       /* Validate parameters */
+       if (((DATA_HEADER_SIZE & ~(HEADER_WORD1_SIZE_CLRMSK >> HEADER_WORD1_SIZE_SHIFT)) != 0) ||
+               ((DATA_HEADER_VERSION & ~(HEADER_WORD1_VERSION_CLRMSK >> HEADER_WORD1_VERSION_SHIFT)) != 0))
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       pui32Word = IMG_OFFSET_ADDR(pbyPDumpDataHdr, 0);
+
+       if (ui32HeaderType == DATA_HEADER_TYPE)
+       {
+               pui32Word[0] = (ui32HeaderType << HEADER_WORD0_TYPE_SHIFT);
+               pui32Word[1] = (DATA_HEADER_SIZE << HEADER_WORD1_SIZE_SHIFT) |
+                       (DATA_HEADER_VERSION << HEADER_WORD1_VERSION_SHIFT);
+               pui32Word[2] = ui32DataSize << HEADER_WORD2_DATA_SIZE_SHIFT;
+
+               pui32Word[3] = ui32ElementType << DATA_HEADER_WORD3_ELEMENT_TYPE_SHIFT;
+               pui32Word[4] = ui32ElementCount << DATA_HEADER_WORD4_ELEMENT_COUNT_SHIFT;
+       }
+
+       if (ui32HeaderType == IBIN_HEADER_TYPE)
+       {
+               pui32Word[0] = (ui32HeaderType << HEADER_WORD0_TYPE_SHIFT);
+               pui32Word[1] = (IBIN_HEADER_SIZE << HEADER_WORD1_SIZE_SHIFT) |
+                       (IBIN_HEADER_VERSION << HEADER_WORD1_VERSION_SHIFT);
+               pui32Word[2] = ui32DataSize << HEADER_WORD2_DATA_SIZE_SHIFT;
+       }
+
+       return PVRSRV_OK;
+}
+#endif /* PDUMP */
+
+/******************************************************************************
+ End of file (rgxpdump.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.c
new file mode 100644 (file)
index 0000000..94f79ec
--- /dev/null
@@ -0,0 +1,1547 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific power routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@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(__linux__)
+#include <linux/stddef.h>
+#else
+#include <stddef.h>
+#endif
+
+#include "rgxpower.h"
+#include "rgxinit.h"
+#include "rgx_fwif_km.h"
+#include "rgxfwutils.h"
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "rgxdebug.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "rgxtimecorr.h"
+#include "devicemem_utils.h"
+#include "htbserver.h"
+#include "rgxstartstop.h"
+#include "rgxfwimageutils.h"
+#include "sync.h"
+#include "rgxdefs_km.h"
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+#include "process_stats.h"
+#endif
+#if defined(SUPPORT_LINUX_DVFS)
+#include "pvr_dvfs_device.h"
+#endif
+#if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) && defined(PDUMP)
+#include "validation_soc.h"
+#include "oskm_apphint.h"
+#endif
+
+static PVRSRV_ERROR RGXFWNotifyHostTimeout(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_KCCB_CMD sCmd;
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32CmdKCCBSlot;
+
+       /* Send the Timeout notification to the FW */
+       sCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
+       sCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
+       sCmd.uCmdData.sPowData.uPowerReqData.ePowRequestType = RGXFWIF_POWER_HOST_TIMEOUT;
+
+       eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                             &sCmd,
+                                             PDUMP_FLAGS_NONE,
+                                             &ui32CmdKCCBSlot);
+
+       return eError;
+}
+
+static void _RGXUpdateGPUUtilStats(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGXFWIF_GPU_UTIL_FWCB *psUtilFWCb;
+       IMG_UINT64 *paui64StatsCounters;
+       IMG_UINT64 ui64LastPeriod;
+       IMG_UINT64 ui64LastState;
+       IMG_UINT64 ui64LastTime;
+       IMG_UINT64 ui64TimeNow;
+
+       psUtilFWCb = psDevInfo->psRGXFWIfGpuUtilFWCb;
+       paui64StatsCounters = &psUtilFWCb->aui64StatsCounters[0];
+
+       OSLockAcquire(psDevInfo->hGPUUtilLock);
+
+       ui64TimeNow = RGXFWIF_GPU_UTIL_GET_TIME(RGXTimeCorrGetClockns64(psDevInfo->psDeviceNode));
+
+       /* Update counters to account for the time since the last update */
+       ui64LastState  = RGXFWIF_GPU_UTIL_GET_STATE(psUtilFWCb->ui64LastWord);
+       ui64LastTime   = RGXFWIF_GPU_UTIL_GET_TIME(psUtilFWCb->ui64LastWord);
+       ui64LastPeriod = RGXFWIF_GPU_UTIL_GET_PERIOD(ui64TimeNow, ui64LastTime);
+       paui64StatsCounters[ui64LastState] += ui64LastPeriod;
+
+       /* Update state and time of the latest update */
+       psUtilFWCb->ui64LastWord = RGXFWIF_GPU_UTIL_MAKE_WORD(ui64TimeNow, ui64LastState);
+
+       OSLockRelease(psDevInfo->hGPUUtilLock);
+}
+
+static INLINE PVRSRV_ERROR RGXDoStop(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       if (psDevConfig->pfnTDRGXStop == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXPrePowerState: TDRGXStop not implemented!"));
+               return PVRSRV_ERROR_NOT_IMPLEMENTED;
+       }
+
+       eError = psDevConfig->pfnTDRGXStop(psDevConfig->hSysData);
+#else
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       eError = RGXStop(&psDevInfo->sLayerParams);
+#endif
+
+       return eError;
+}
+
+/*
+       RGXPrePowerState
+*/
+PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                               hDevHandle,
+                              PVRSRV_DEV_POWER_STATE   eNewPowerState,
+                              PVRSRV_DEV_POWER_STATE   eCurrentPowerState,
+                              PVRSRV_POWER_FLAGS               ePwrFlags)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE    *psDeviceNode = hDevHandle;
+
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
+       {
+               PVRSRV_RGXDEV_INFO    *psDevInfo = psDeviceNode->pvDevice;
+               RGXFWIF_KCCB_CMD      sPowCmd;
+               IMG_UINT32            ui32CmdKCCBSlot;
+
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+               /* Send the Power off request to the FW */
+               sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
+               sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_OFF_REQ;
+               sPowCmd.uCmdData.sPowData.uPowerReqData.bForced = BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED);
+
+               eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set Power sync prim",
+                                       __func__));
+                       return eError;
+               }
+
+               eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                                     &sPowCmd,
+                                                     PDUMP_FLAGS_NONE,
+                                                     &ui32CmdKCCBSlot);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send Power off request",
+                                       __func__));
+                       return eError;
+               }
+
+               /* Wait for the firmware to complete processing. It cannot use PVRSRVWaitForValueKM as it relies
+                  on the EventObject which is signalled in this MISR */
+               eError = RGXPollForGPCommandCompletion(psDeviceNode,
+                                                                 psDevInfo->psPowSyncPrim->pui32LinAddr,
+                                                                 0x1, 0xFFFFFFFF);
+
+               /* Check the Power state after the answer */
+               if (eError == PVRSRV_OK)
+               {
+                       /* Finally, de-initialise some registers. */
+                       if (psFwSysData->ePowState == RGXFWIF_POW_OFF)
+                       {
+#if !defined(NO_HARDWARE)
+                               IMG_UINT32 ui32TID;
+                               const RGXFWIF_OSDATA *psFwOsData = psDevInfo->psRGXFWIfFwOsData;
+
+                               /* Driver takes the VZ Fw-KM connection down, preventing the
+                               * firmware from submitting further interrupts */
+                               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+
+                               for (ui32TID = 0; ui32TID < RGXFW_THREAD_NUM; ui32TID++)
+                               {
+                                       /* Wait for the pending FW processor to host interrupts to come back. */
+                                       eError = PVRSRVPollForValueKM(psDeviceNode,
+                                                                                         (IMG_UINT32 __iomem *)&psDevInfo->aui32SampleIRQCount[ui32TID],
+                                                                                         psFwOsData->aui32InterruptCount[ui32TID],
+                                                                                         0xffffffff,
+                                                                                         POLL_FLAG_LOG_ERROR);
+
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                               "%s: Wait for pending interrupts failed (DevID %u). Thread %u: Host: %u, FW: %u",
+                                                               __func__,
+                                                               psDeviceNode->sDevId.ui32InternalID,
+                                                               ui32TID,
+                                                               psDevInfo->aui32SampleIRQCount[ui32TID],
+                                                               psFwOsData->aui32InterruptCount[ui32TID]));
+
+                                               RGX_WaitForInterruptsTimeout(psDevInfo);
+                                               break;
+                                       }
+                               }
+#endif /* NO_HARDWARE */
+
+                               /* Update GPU frequency and timer correlation related data */
+                               RGXTimeCorrEnd(psDeviceNode, RGXTIMECORR_EVENT_POWER);
+
+                               /* Update GPU state counters */
+                               _RGXUpdateGPUUtilStats(psDevInfo);
+
+#if defined(SUPPORT_LINUX_DVFS)
+                               eError = SuspendDVFS(psDeviceNode);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to suspend DVFS", __func__));
+                                       return eError;
+                               }
+#endif
+
+                               psDevInfo->bRGXPowered = IMG_FALSE;
+
+                               eError = RGXDoStop(psDeviceNode);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       /* Power down failures are treated as successful since the power was removed but logged. */
+                                       PVR_DPF((PVR_DBG_WARNING, "%s: RGXDoStop failed (%s)",
+                                                       __func__, PVRSRVGetErrorString(eError)));
+                                       psDevInfo->ui32ActivePMReqNonIdle++;
+                                       eError = PVRSRV_OK;
+                               }
+                       }
+                       else
+                       {
+                               /* the sync was updated but the pow state isn't off -> the FW denied the transition */
+                               eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
+
+                               if (BITMASK_HAS(ePwrFlags, PVRSRV_POWER_FLAGS_FORCED))
+                               {       /* It is an error for a forced request to be denied */
+                                       PVR_DPF((PVR_DBG_ERROR,
+                                                        "%s: Failure to power off during a forced power off. FW: %d",
+                                                        __func__, psFwSysData->ePowState));
+                               }
+                       }
+               }
+               else if (eError == PVRSRV_ERROR_TIMEOUT)
+               {
+                       /* timeout waiting for the FW to ack the request: return timeout */
+                       PVR_DPF((PVR_DBG_WARNING,
+                                        "%s: Timeout waiting for powoff ack from the FW",
+                                        __func__));
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Error waiting for powoff ack from the FW (%s)",
+                                        __func__, PVRSRVGetErrorString(eError)));
+                       eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
+               }
+       }
+
+       return eError;
+}
+
+#if defined(SUPPORT_AUTOVZ)
+static PVRSRV_ERROR _RGXWaitForGuestsToDisconnect(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError = PVRSRV_ERROR_TIMEOUT;
+       IMG_UINT32 ui32FwTimeout = (20 * SECONDS_TO_MICROSECONDS);
+
+       LOOP_UNTIL_TIMEOUT(ui32FwTimeout)
+       {
+               IMG_UINT32 ui32OSid;
+               IMG_BOOL bGuestOnline = IMG_FALSE;
+
+               for (ui32OSid = RGXFW_GUEST_OSID_START;
+                        ui32OSid < RGX_NUM_OS_SUPPORTED; ui32OSid++)
+               {
+                       RGXFWIF_CONNECTION_FW_STATE eGuestState = (RGXFWIF_CONNECTION_FW_STATE)
+                                       psDevInfo->psRGXFWIfFwSysData->asOsRuntimeFlagsMirror[ui32OSid].bfOsState;
+
+                       if ((eGuestState == RGXFW_CONNECTION_FW_ACTIVE) ||
+                               (eGuestState == RGXFW_CONNECTION_FW_OFFLOADING))
+                       {
+                               bGuestOnline = IMG_TRUE;
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Guest OS %u still online.", __func__, ui32OSid));
+                       }
+               }
+
+               if (!bGuestOnline)
+               {
+                       /* Allow Guests to finish reading Connection state registers before disconnecting. */
+                       OSSleepms(100);
+
+                       PVR_DPF((PVR_DBG_WARNING, "%s: All Guest connections are down. "
+                                                                         "Host can power down the GPU.", __func__));
+                       eError = PVRSRV_OK;
+                       break;
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Waiting for Guests to disconnect "
+                                                                         "before powering down GPU.", __func__));
+
+                       if (PVRSRVPwrLockIsLockedByMe(psDeviceNode))
+                       {
+                               /* Don't wait with the power lock held as this prevents the vz
+                                * watchdog thread from keeping the fw-km connection alive. */
+                               PVRSRVPowerUnlock(psDeviceNode);
+                       }
+               }
+
+               OSSleepms(10);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (!PVRSRVPwrLockIsLockedByMe(psDeviceNode))
+       {
+               /* Take back power lock after waiting for Guests */
+               eError = PVRSRVPowerLock(psDeviceNode);
+       }
+
+       return eError;
+}
+#endif /* defined(SUPPORT_AUTOVZ) */
+
+/*
+       RGXVzPrePowerState
+*/
+PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                             hDevHandle,
+                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+                                PVRSRV_POWER_FLAGS             ePwrFlags)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+
+       PVR_LOG_RETURN_IF_FALSE((eNewPowerState != eCurrentPowerState), "no power change", eError);
+
+       if (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)
+       {
+               /* powering down */
+#if defined(SUPPORT_AUTOVZ)
+               if (PVRSRV_VZ_MODE_IS(HOST) && (!psDeviceNode->bAutoVzFwIsUp))
+               {
+                       /* The Host must ensure all Guest drivers have disconnected from the GPU before powering it down.
+                        * Guest drivers regularly access hardware registers during runtime. If an attempt is made to
+                        * access a GPU register while the GPU is down, the SoC might lock up. */
+                       eError = _RGXWaitForGuestsToDisconnect(psDeviceNode);
+                       PVR_LOG_RETURN_IF_ERROR(eError, "_RGXWaitForGuestsToDisconnect");
+
+                       /* Temporarily restore all power callbacks used by the driver to fully power down the GPU.
+                        * Under AutoVz, power transitions requests (e.g. on driver deinitialisation and unloading)
+                        * are generally ignored and the GPU power state is unaffected. Special power requests like
+                        * those triggered by Suspend/Resume calls must reinstate the callbacks when needed. */
+                       PVRSRVSetPowerCallbacks(psDeviceNode, psDeviceNode->psPowerDev,
+                                                                       &RGXVzPrePowerState, &RGXVzPostPowerState,
+                                                                       psDeviceNode->psDevConfig->pfnPrePowerState,
+                                                                       psDeviceNode->psDevConfig->pfnPostPowerState,
+                                                                       &RGXForcedIdleRequest, &RGXCancelForcedIdleRequest);
+               }
+               else
+               {
+                       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+                       if (KM_FW_CONNECTION_IS(ACTIVE, psDevInfo) &&
+                               KM_OS_CONNECTION_IS(ACTIVE, psDevInfo))
+                       {
+                               PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+                               PVRSRV_ERROR eError = RGXFWSetFwOsState(psDevInfo, 0, RGXFWIF_OS_OFFLINE);
+                               PVR_LOG_RETURN_IF_ERROR(eError, "RGXFWSetFwOsState");
+                       }
+               }
+#endif
+               PVR_DPF((PVR_DBG_WARNING, "%s: %s driver powering down: bAutoVzFwIsUp = %s",
+                                                               __func__, PVRSRV_VZ_MODE_IS(GUEST)? "GUEST" : "HOST",
+                                                               psDeviceNode->bAutoVzFwIsUp ? "TRUE" : "FALSE"));
+       }
+       else if (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)
+       {
+               /* powering up */
+               PVR_DPF((PVR_DBG_WARNING, "%s: %s driver powering up: bAutoVzFwIsUp = %s",
+                                                               __func__, PVRSRV_VZ_MODE_IS(GUEST)? "GUEST" : "HOST",
+                                                               psDeviceNode->bAutoVzFwIsUp ? "TRUE" : "FALSE"));
+
+       }
+
+       if (!(PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp)))
+       {
+               /* call regular device power function */
+               eError = RGXPrePowerState(hDevHandle, eNewPowerState, eCurrentPowerState, ePwrFlags);
+       }
+
+       return eError;
+}
+
+/*
+       RGXVzPostPowerState
+*/
+PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                            hDevHandle,
+                                 PVRSRV_DEV_POWER_STATE        eNewPowerState,
+                                 PVRSRV_DEV_POWER_STATE        eCurrentPowerState,
+                                 PVRSRV_POWER_FLAGS            ePwrFlags)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       PVR_LOG_RETURN_IF_FALSE((eNewPowerState != eCurrentPowerState), "no power change", eError);
+
+       if (!(PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp)))
+       {
+               /* call regular device power function */
+               eError = RGXPostPowerState(hDevHandle, eNewPowerState, eCurrentPowerState, ePwrFlags);
+       }
+
+       if (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON)
+       {
+               /* powering down */
+               PVR_LOG_RETURN_IF_FALSE((!psDeviceNode->bAutoVzFwIsUp), "AutoVz Fw active, power not changed", eError);
+               PVR_DPF((PVR_DBG_WARNING, "%s: %s driver powering down: bAutoVzFwIsUp = %s",
+                                                               __func__, PVRSRV_VZ_MODE_IS(GUEST)? "GUEST" : "HOST",
+                                                               psDeviceNode->bAutoVzFwIsUp ? "TRUE" : "FALSE"));
+
+#if !defined(SUPPORT_AUTOVZ_HW_REGS)
+               /* The connection states must be reset on a GPU power cycle. If the states are kept
+                * in hardware scratch registers, they will be cleared on power down. When using shared
+                * memory the connection data must be explicitly cleared by the driver. */
+               OSCachedMemSetWMB(psDevInfo->psRGXFWIfConnectionCtl, 0, sizeof(RGXFWIF_CONNECTION_CTL));
+#endif /* defined(SUPPORT_AUTOVZ) && !defined(SUPPORT_AUTOVZ_HW_REGS) */
+
+               if (PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp))
+               {
+#if defined(SUPPORT_AUTOVZ)
+                       /* AutoVz Guests attempting to suspend have updated their connections earlier in RGXVzPrePowerState.
+                        * Skip this redundant register write, as the Host could have powered down the GPU by now. */
+                       if (psDeviceNode->bAutoVzFwIsUp)
+#endif
+                       {
+                               /* Take the VZ connection down to prevent firmware from submitting further interrupts */
+                               KM_SET_OS_CONNECTION(OFFLINE, psDevInfo);
+                       }
+                       /* Power transition callbacks were not executed, update RGXPowered flag here */
+                       psDevInfo->bRGXPowered = IMG_FALSE;
+               }
+       }
+       else if (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON)
+       {
+               /* powering up */
+               IMG_UINT32 ui32FwTimeout = (3 * SECONDS_TO_MICROSECONDS);
+               volatile IMG_BOOL *pbUpdatedFlag = &psDevInfo->psRGXFWIfOsInit->sRGXCompChecks.bUpdated;
+
+               PVR_DPF((PVR_DBG_WARNING, "%s: %s driver powering up: bAutoVzFwIsUp = %s",
+                                                               __func__, PVRSRV_VZ_MODE_IS(GUEST)? "GUEST" : "HOST",
+                                                               psDeviceNode->bAutoVzFwIsUp ? "TRUE" : "FALSE"));
+               if (PVRSRV_VZ_MODE_IS(GUEST))
+               {
+                       /* Guests don't execute the power transition callbacks, so update their RGXPowered flag here */
+                       psDevInfo->bRGXPowered = IMG_TRUE;
+
+#if defined(RGX_VZ_STATIC_CARVEOUT_FW_HEAPS)
+                       /* Guest drivers expect the firmware to have set its end of the
+                        * connection to Ready state by now. Poll indefinitely otherwise. */
+                       if (!KM_FW_CONNECTION_IS(READY, psDevInfo))
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Firmware Connection is not in Ready state. Waiting for Firmware ...", __func__));
+                       }
+                       while (!KM_FW_CONNECTION_IS(READY, psDevInfo))
+                       {
+                               OSSleepms(10);
+                       }
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Firmware Connection is Ready. Initialisation proceeding.", __func__));
+#endif /* RGX_VZ_STATIC_CARVEOUT_FW_HEAPS */
+
+                       /* Guests can only access the register holding the connection states,
+                        * after the GPU is confirmed to be powered up */
+                       KM_SET_OS_CONNECTION(READY, psDevInfo);
+
+                       OSWriteDeviceMem32(pbUpdatedFlag, IMG_FALSE);
+
+                       /* Kick an initial dummy command to make the firmware initialise all
+                        * its internal guest OS data structures and compatibility information.
+                        * Use the lower-level RGXSendCommandAndGetKCCBSlot() for the job, to make
+                        * sure only 1 KCCB command is issued to the firmware.
+                        * The default RGXFWHealthCheckCmd() prefaces each HealthCheck command with
+                        * a pre-kick cache command which can interfere with the FW-KM init handshake. */
+                       {
+                               RGXFWIF_KCCB_CMD sCmpKCCBCmd;
+                               sCmpKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_HEALTH_CHECK;
+
+                               eError = RGXSendCommandAndGetKCCBSlot(psDevInfo, &sCmpKCCBCmd, PDUMP_FLAGS_CONTINUOUS, NULL);
+                               PVR_LOG_RETURN_IF_ERROR(eError, "RGXSendCommandAndGetKCCBSlot()");
+                       }
+               }
+               else
+               {
+                       KM_SET_OS_CONNECTION(READY, psDevInfo);
+
+                       /* Disable power callbacks that should not be run on virtualised drivers after the GPU
+                        * is fully initialised: system layer pre/post functions and driver idle requests.
+                        * The original device RGX Pre/Post functions are called from this Vz wrapper. */
+                       PVRSRVSetPowerCallbacks(psDeviceNode, psDeviceNode->psPowerDev,
+                                                                       &RGXVzPrePowerState, &RGXVzPostPowerState,
+                                                                       NULL, NULL, NULL, NULL);
+
+#if defined(SUPPORT_AUTOVZ)
+                       /* During first-time boot the flag is set here, while subsequent reboots will already
+                        * have set it earlier in RGXInit. Set to true from this point onwards in any case. */
+                       psDeviceNode->bAutoVzFwIsUp = IMG_TRUE;
+#endif
+               }
+
+               /* Wait for the firmware to accept and enable the connection with this OS by setting its state to Active */
+               while (!KM_FW_CONNECTION_IS(ACTIVE, psDevInfo))
+               {
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Firmware Connection is not in Active state. Waiting for Firmware ...", __func__));
+                       OSSleepms(100);
+               }
+               PVR_DPF((PVR_DBG_WARNING, "%s: Firmware Connection is Active. Initialisation proceeding.", __func__));
+
+               /* poll on the Firmware supplying the compatibility data */
+               LOOP_UNTIL_TIMEOUT(ui32FwTimeout)
+               {
+                       if (*pbUpdatedFlag)
+                       {
+                               break;
+                       }
+                       OSSleepms(10);
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               PVR_LOG_RETURN_IF_FALSE(*pbUpdatedFlag, "Firmware does not respond with compatibility data. ", PVRSRV_ERROR_TIMEOUT);
+
+               KM_SET_OS_CONNECTION(ACTIVE, psDevInfo);
+       }
+
+       return PVRSRV_OK;
+}
+
+#if defined(TRACK_FW_BOOT)
+static INLINE void RGXCheckFWBootStage(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       FW_BOOT_STAGE eStage;
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               /* Boot stage temporarily stored to the register below */
+               eStage = OSReadHWReg32(psDevInfo->pvRegsBaseKM,
+                                      RGX_FW_BOOT_STAGE_REGISTER);
+       }
+       else if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, RISCV_FW_PROCESSOR))
+       {
+               eStage = OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_SCRATCH14);
+       }
+       else
+       {
+               return;
+       }
+
+       PVR_LOG(("%s: FW reached boot stage %i/%i.",
+                __func__, eStage, FW_BOOT_INIT_DONE));
+}
+#endif
+
+static INLINE PVRSRV_ERROR RGXDoStart(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+
+       if (psDevConfig->pfnTDRGXStart == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: TDRGXStart not implemented!"));
+               return PVRSRV_ERROR_NOT_IMPLEMENTED;
+       }
+
+       eError = psDevConfig->pfnTDRGXStart(psDevConfig->hSysData);
+#else
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+       eError = RGXStart(&psDevInfo->sLayerParams);
+#endif
+
+       return eError;
+}
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION) && !defined(NO_HARDWARE)
+/*
+ * To validate the MTS unit we do the following:
+ *  - Immediately after firmware loading for each OSID
+ *    - Write the OSid to a memory location shared with FW
+ *    - Kick the register of that OSid
+ *         (Uncounted, DM 0)
+ *    - FW clears the memory location if OSid matches
+ *    - Host checks that memory location is cleared
+ *
+ *  See firmware/devices/rgx/rgxfw_bg.c
+ */
+static PVRSRV_ERROR RGXVirtualisationPowerupSidebandTest(PVRSRV_DEVICE_NODE     *psDeviceNode,
+                                                                                                                RGXFWIF_SYSINIT *psFwSysInit,
+                                                                                                                PVRSRV_RGXDEV_INFO      *psDevInfo)
+{
+       IMG_UINT32 ui32ScheduleRegister;
+       IMG_UINT32 ui32OSid;
+       IMG_UINT32 ui32KickType;
+       IMG_UINT32 ui32OsRegBanksMapped = (psDeviceNode->psDevConfig->ui32RegsSize / RGX_VIRTUALISATION_REG_SIZE_PER_OS);
+
+       /* Nothing to do if device does not support GPU_VIRTUALISATION */
+       if (!PVRSRV_IS_FEATURE_SUPPORTED(psDeviceNode, GPU_VIRTUALISATION))
+       {
+               return PVRSRV_OK;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE, "Testing per-os kick registers:"));
+
+       ui32OsRegBanksMapped = MIN(ui32OsRegBanksMapped, GPUVIRT_VALIDATION_NUM_OS);
+
+       if (ui32OsRegBanksMapped != RGXFW_MAX_NUM_OS)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "The register bank mapped into kernel VA does not cover all OS' registers:"));
+               PVR_DPF((PVR_DBG_WARNING, "Maximum OS count = %d / Per-os register banks mapped = %d", RGXFW_MAX_NUM_OS, ui32OsRegBanksMapped));
+               PVR_DPF((PVR_DBG_WARNING, "Only first %d MTS registers will be tested", ui32OsRegBanksMapped));
+       }
+
+       ui32KickType = RGX_CR_MTS_SCHEDULE_DM_DM0 | RGX_CR_MTS_SCHEDULE_TASK_NON_COUNTED;
+
+       for (ui32OSid = 0; ui32OSid < ui32OsRegBanksMapped; ui32OSid++)
+       {
+               /* set Test field */
+               psFwSysInit->ui32OSKickTest = (ui32OSid << RGXFWIF_KICK_TEST_OSID_SHIFT) | RGXFWIF_KICK_TEST_ENABLED_BIT;
+
+#if defined(PDUMP)
+               DevmemPDumpLoadMem(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                  offsetof(RGXFWIF_SYSINIT, ui32OSKickTest),
+                                                  sizeof(psFwSysInit->ui32OSKickTest),
+                                                  PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+               OSWriteMemoryBarrier(&psFwSysInit->ui32OSKickTest);
+
+               /* kick register */
+               ui32ScheduleRegister = RGX_CR_MTS_SCHEDULE + (ui32OSid * RGX_VIRTUALISATION_REG_SIZE_PER_OS);
+               PVR_DPF((PVR_DBG_MESSAGE, "  Testing OS: %u, Kick Reg: %X",
+                                ui32OSid,
+                                ui32ScheduleRegister));
+               OSWriteHWReg32(psDevInfo->pvRegsBaseKM, ui32ScheduleRegister, ui32KickType);
+               OSMemoryBarrier((IMG_BYTE*) psDevInfo->pvRegsBaseKM + ui32ScheduleRegister);
+
+#if defined(PDUMP)
+               PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "VZ sideband test, kicking MTS register %u", ui32OSid);
+
+               PDUMPREG32(psDeviceNode, RGX_PDUMPREG_NAME,
+                               ui32ScheduleRegister, ui32KickType, PDUMP_FLAGS_CONTINUOUS);
+
+               DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                          offsetof(RGXFWIF_SYSINIT, ui32OSKickTest),
+                                                          0,
+                                                          0xFFFFFFFF,
+                                                          PDUMP_POLL_OPERATOR_EQUAL,
+                                                          PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+               /* Wait test enable bit to be unset */
+               if (PVRSRVPollForValueKM(psDeviceNode,
+                                                                (IMG_UINT32 *)&psFwSysInit->ui32OSKickTest,
+                                                                0,
+                                                                RGXFWIF_KICK_TEST_ENABLED_BIT,
+                                                                POLL_FLAG_LOG_ERROR | POLL_FLAG_DEBUG_DUMP) != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Testing OS %u kick register failed: firmware did not clear test location (contents: 0x%X)",
+                                        ui32OSid,
+                                        psFwSysInit->ui32OSKickTest));
+
+                       return PVRSRV_ERROR_TIMEOUT;
+               }
+
+               /* Check that the value is what we expect */
+               if (psFwSysInit->ui32OSKickTest != 0)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Testing OS %u kick register failed: firmware wrote 0x%X to test location",
+                                        ui32OSid,
+                                        psFwSysInit->ui32OSKickTest));
+                       return PVRSRV_ERROR_INIT_FAILURE;
+               }
+
+               PVR_DPF((PVR_DBG_MESSAGE, "    PASS"));
+       }
+
+       PVR_LOG(("MTS passed sideband tests"));
+       return PVRSRV_OK;
+}
+#endif /* defined(SUPPORT_GPUVIRT_VALIDATION) && !defined(NO_HARDWARE) */
+
+#if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) && defined(PDUMP)
+#define SCRATCH_VALUE  (0x12345678U)
+
+static void RGXRiscvDebugModuleTest(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       void *pvAppHintState = NULL;
+       IMG_UINT32 ui32AppHintDefault = 0;
+       IMG_BOOL bRunRiscvDmiTest;
+
+       IMG_UINT32 *pui32FWCode = NULL;
+       PVRSRV_ERROR eError;
+
+       OSCreateKMAppHintState(&pvAppHintState);
+       OSGetKMAppHintBOOL(APPHINT_NO_DEVICE, pvAppHintState, RiscvDmiTest,
+                          &ui32AppHintDefault, &bRunRiscvDmiTest);
+       OSFreeKMAppHintState(pvAppHintState);
+
+       if (bRunRiscvDmiTest == IMG_FALSE)
+       {
+               return;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc, (void **)&pui32FWCode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "%s: Error acquiring FW code memory pointer (%s)",
+                        __func__,
+                        PVRSRVGetErrorString(eError)));
+       }
+
+       PDumpIfKM(psDevInfo->psDeviceNode, "ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "DMI_TEST BEGIN");
+
+       RGXRiscvHalt(psDevInfo);
+
+       /*
+        * Test RISC-V register reads/writes.
+        * RGXRiscv[Write/Poll]Reg are used to access internal RISC-V registers
+        * via debug module.
+        */
+
+       /* Write RISC-V mscratch register */
+       RGXRiscvWriteReg(psDevInfo, RGXRISCVFW_MSCRATCH_ADDR, SCRATCH_VALUE);
+       /* Read RISC-V misa register (compare against default standard value) */
+       RGXRiscvPollReg(psDevInfo,  RGXRISCVFW_MISA_ADDR,     RGXRISCVFW_MISA_VALUE);
+       /* Read RISC-V mscratch register (compare against previously written value) */
+       RGXRiscvPollReg(psDevInfo,  RGXRISCVFW_MSCRATCH_ADDR, SCRATCH_VALUE);
+
+       /*
+        * Test RISC-V memory reads/writes.
+        * RGXRiscv[Write/Poll]Mem are used to access system memory via debug module
+        * (from RISC-V point of view).
+        */
+
+       if (pui32FWCode != NULL)
+       {
+               IMG_UINT32 ui32Tmp;
+
+               /* Acquire pointer to FW code (bootloader) */
+               pui32FWCode += RGXGetFWImageSectionOffset(NULL, RISCV_UNCACHED_CODE) / sizeof(IMG_UINT32);
+               /* Save FW code at address (bootloader) */
+               ui32Tmp = *pui32FWCode;
+
+               /* Write FW code at address (bootloader) */
+               RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     SCRATCH_VALUE);
+               /* Read FW code at address (bootloader + 4) (compare against value read from Host) */
+               RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_BOOTLDR_CODE_BASE + 4, *(pui32FWCode + 1));
+               /* Read FW code at address (bootloader) (compare against previously written value) */
+               RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_BOOTLDR_CODE_BASE,     SCRATCH_VALUE);
+               /* Restore FW code at address (bootloader) */
+               RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_BOOTLDR_CODE_BASE,     ui32Tmp);
+
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+       }
+
+       /*
+        * Test GPU register reads/writes.
+        * RGXRiscv[Write/Poll]Mem are used to access GPU registers via debug module
+        * (from RISC-V point of view).
+        * Note that system memory and GPU register accesses both use the same
+        * debug module interface, targeting different address ranges.
+        */
+
+       /* Write SCRATCH0 from the Host */
+       PDUMPREG32(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0, SCRATCH_VALUE, PDUMP_FLAGS_CONTINUOUS);
+       /* Read SCRATCH0 */
+       RGXRiscvPollMem(psDevInfo,  RGXRISCVFW_SOCIF_BASE | RGX_CR_SCRATCH0, SCRATCH_VALUE);
+       /* Write SCRATCH0 */
+       RGXWriteFWModuleAddr(psDevInfo, RGXRISCVFW_SOCIF_BASE | RGX_CR_SCRATCH0, ~SCRATCH_VALUE);
+       /* Read SCRATCH0 from the Host */
+       PDUMPREGPOL(psDevInfo->psDeviceNode, RGX_PDUMPREG_NAME, RGX_CR_SCRATCH0, ~SCRATCH_VALUE, 0xFFFFFFFFU,
+                   PDUMP_FLAGS_CONTINUOUS, PDUMP_POLL_OPERATOR_EQUAL);
+
+       RGXRiscvResume(psDevInfo);
+
+       PDUMPCOMMENTWITHFLAGS(psDevInfo->psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "DMI_TEST END");
+       PDumpFiKM(psDevInfo->psDeviceNode, "ENABLE_RISCV_DMI_TEST", PDUMP_FLAGS_CONTINUOUS);
+}
+#endif
+
+/*
+       RGXPostPowerState
+*/
+PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                              hDevHandle,
+                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
+                               PVRSRV_POWER_FLAGS              ePwrFlags)
+{
+       PVRSRV_DEVICE_NODE       *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO       *psDevInfo = psDeviceNode->pvDevice;
+
+       if ((eNewPowerState != eCurrentPowerState) &&
+           (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
+       {
+               PVRSRV_ERROR             eError;
+
+               if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
+               {
+                       /* Update timer correlation related data */
+                       RGXTimeCorrBegin(psDeviceNode, RGXTIMECORR_EVENT_POWER);
+
+                       /* Update GPU state counters */
+                       _RGXUpdateGPUUtilStats(psDevInfo);
+
+                       eError = RGXDoStart(psDeviceNode);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: RGXDoStart failed"));
+                               return eError;
+                       }
+
+                       OSMemoryBarrier(NULL);
+
+                       /*
+                        * Check whether the FW has started by polling on bFirmwareStarted flag
+                        */
+                       if (PVRSRVPollForValueKM(psDeviceNode,
+                                                (IMG_UINT32 __iomem *)&psDevInfo->psRGXFWIfSysInit->bFirmwareStarted,
+                                                IMG_TRUE,
+                                                0xFFFFFFFF,
+                                                POLL_FLAG_LOG_ERROR | POLL_FLAG_DEBUG_DUMP) != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: Polling for 'FW started' flag failed."));
+                               eError = PVRSRV_ERROR_TIMEOUT;
+
+#if defined(TRACK_FW_BOOT)
+                               RGXCheckFWBootStage(psDevInfo);
+#endif
+
+                               /*
+                                * When bFirmwareStarted fails some info may be gained by doing the following
+                                * debug dump but unfortunately it could be potentially dangerous if the reason
+                                * for not booting is the GPU power is not ON. However, if we have reached this
+                                * point the System Layer has returned without errors, we assume the GPU power
+                                * is indeed ON.
+                                */
+                               RGXDumpRGXDebugSummary(NULL, NULL, psDeviceNode->pvDevice, IMG_TRUE);
+                               RGXDumpRGXRegisters(NULL, NULL, psDeviceNode->pvDevice);
+
+                               return eError;
+                       }
+
+#if defined(PDUMP)
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS, "Wait for the Firmware to start.");
+                       eError = DevmemPDumpDevmemPol32(psDevInfo->psRGXFWIfSysInitMemDesc,
+                                                       offsetof(RGXFWIF_SYSINIT, bFirmwareStarted),
+                                                       IMG_TRUE,
+                                                       0xFFFFFFFFU,
+                                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                        "RGXPostPowerState: problem pdumping POL for psRGXFWIfSysInitMemDesc (%d)",
+                                        eError));
+                               return eError;
+                       }
+
+#if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE)
+                       /* Check if the Validation IRQ flag is set */
+                       if ((psDevInfo->psRGXFWIfFwSysData->ui32ConfigFlags & RGXFWIF_INICFG_VALIDATE_IRQ) != 0)
+                       {
+                               eError = PVRSRVValidateIrqs(psDeviceNode);
+                               if (eError != PVRSRV_OK)
+                               {
+                                       return eError;
+                               }
+                       }
+#endif /* defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) */
+
+#endif /* defined(PDUMP) */
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION) && !defined(NO_HARDWARE)
+                       eError = RGXVirtualisationPowerupSidebandTest(psDeviceNode, psDevInfo->psRGXFWIfSysInit, psDevInfo);
+                       if (eError != PVRSRV_OK)
+                       {
+                               return eError;
+                       }
+#endif
+
+#if defined(SUPPORT_VALIDATION) && defined(NO_HARDWARE) && defined(PDUMP)
+                       RGXRiscvDebugModuleTest(psDevInfo);
+#endif
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+                       SetFirmwareStartTime(psDevInfo->psRGXFWIfSysInit->ui32FirmwareStartedTimeStamp);
+#endif
+
+                       HTBSyncPartitionMarker(psDevInfo->psRGXFWIfSysInit->ui32MarkerVal);
+
+                       psDevInfo->bRGXPowered = IMG_TRUE;
+
+#if defined(SUPPORT_LINUX_DVFS)
+                       eError = ResumeDVFS(psDeviceNode);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "RGXPostPowerState: Failed to resume DVFS"));
+                               return eError;
+                       }
+#endif
+               }
+       }
+
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXPostPowerState: Current state: %d, New state: %d",
+                    eCurrentPowerState, eNewPowerState);
+
+       return PVRSRV_OK;
+}
+
+/*
+       RGXPreClockSpeedChange
+*/
+PVRSRV_ERROR RGXPreClockSpeedChange(IMG_HANDLE                         hDevHandle,
+                                    PVRSRV_DEV_POWER_STATE     eCurrentPowerState)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       const PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+       PVR_UNREFERENCED_PARAMETER(psRGXData);
+
+       PVR_DPF((PVR_DBG_MESSAGE, "RGXPreClockSpeedChange: RGX clock speed was %uHz",
+                       psRGXData->psRGXTimingInfo->ui32CoreClockSpeed));
+
+       if ((eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF) &&
+           (psFwSysData->ePowState != RGXFWIF_POW_OFF))
+       {
+               /* Update GPU frequency and timer correlation related data */
+               RGXTimeCorrEnd(psDeviceNode, RGXTIMECORR_EVENT_DVFS);
+       }
+
+       return eError;
+}
+
+/*
+       RGXPostClockSpeedChange
+*/
+PVRSRV_ERROR RGXPostClockSpeedChange(IMG_HANDLE                                hDevHandle,
+                                     PVRSRV_DEV_POWER_STATE    eCurrentPowerState)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       const PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGX_DATA *psRGXData = (RGX_DATA*)psDeviceNode->psDevConfig->hDevData;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32NewClockSpeed = psRGXData->psRGXTimingInfo->ui32CoreClockSpeed;
+
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_ERROR_NOT_SUPPORTED);
+
+       /* Update runtime configuration with the new value */
+       OSWriteDeviceMem32WithWMB(&psDevInfo->psRGXFWIfRuntimeCfg->ui32CoreClockSpeed,
+                                 ui32NewClockSpeed);
+
+       if ((eCurrentPowerState != PVRSRV_DEV_POWER_STATE_OFF) &&
+           (psFwSysData->ePowState != RGXFWIF_POW_OFF))
+       {
+               RGXFWIF_KCCB_CMD sCOREClkSpeedChangeCmd;
+               IMG_UINT32 ui32CmdKCCBSlot;
+
+               RGXTimeCorrBegin(psDeviceNode, RGXTIMECORR_EVENT_DVFS);
+
+               sCOREClkSpeedChangeCmd.eCmdType = RGXFWIF_KCCB_CMD_CORECLKSPEEDCHANGE;
+               sCOREClkSpeedChangeCmd.uCmdData.sCoreClkSpeedChangeData.ui32NewClockSpeed = ui32NewClockSpeed;
+
+               PDUMPCOMMENT(psDeviceNode, "Scheduling CORE clock speed change command");
+
+               PDUMPPOWCMDSTART(psDeviceNode);
+               eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
+                                                     &sCOREClkSpeedChangeCmd,
+                                                     PDUMP_FLAGS_NONE,
+                                                     &ui32CmdKCCBSlot);
+               PDUMPPOWCMDEND(psDeviceNode);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PDUMPCOMMENT(psDeviceNode, "Scheduling CORE clock speed change command failed");
+                       PVR_DPF((PVR_DBG_ERROR, "RGXPostClockSpeedChange: Scheduling KCCB command failed. Error:%u", eError));
+                       return eError;
+               }
+
+               PVR_DPF((PVR_DBG_MESSAGE, "RGXPostClockSpeedChange: RGX clock speed changed to %uHz",
+                               psRGXData->psRGXTimingInfo->ui32CoreClockSpeed));
+       }
+
+       return eError;
+}
+
+/*************************************************************************/ /*!
+@Function       RGXPowUnitsStateMaskChange
+@Description    Changes power state of power units/islands
+@Input          hDevHandle         RGX Device Node.
+@Input          ui32PowUnitsStateMask   Mask containing power state of PUs.
+                                        Each bit corresponds to an PU.
+                                        Bit position corresponds to PU number i.e. Bit0 is PU0, Bit1 is PU1 etc.
+                                        '1' indicates ON and '0' indicates OFF.
+                                        Value must be non-zero.
+@Return         PVRSRV_ERROR.
+*/ /**************************************************************************/
+PVRSRV_ERROR RGXPowUnitsStateMaskChange(IMG_HANDLE hDevHandle, IMG_UINT32 ui32PowUnitsStateMask)
+{
+
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR            eError;
+       RGXFWIF_KCCB_CMD        sPowUnitsStateMaskChange;
+       IMG_UINT32 ui32PowUnitsMask = psDevInfo->ui32AvailablePowUnitsMask;
+       IMG_UINT32                      ui32CmdKCCBSlot;
+       RGXFWIF_RUNTIME_CFG *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       /**
+        * Validate the input. At-least one PU must be powered on and all requested
+        * PU's must be a subset of full PU mask.
+        */
+       if ((ui32PowUnitsStateMask == 0) || (ui32PowUnitsStateMask & ~ui32PowUnitsMask))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Invalid Power Units mask requested (0x%X). Value should be non-zero and sub-set of 0x%X mask",
+                               __func__,
+                               ui32PowUnitsStateMask,
+                               ui32PowUnitsMask));
+               return PVRSRV_ERROR_INVALID_SPU_MASK;
+       }
+
+       psRuntimeCfg->ui32PowUnitsStateMask = ui32PowUnitsStateMask;
+       OSWriteMemoryBarrier(&psRuntimeCfg->ui32PowUnitsStateMask);
+
+#if !defined(NO_HARDWARE)
+       {
+               const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+               if (psFwSysData->ePowState == RGXFWIF_POW_OFF)
+               {
+                       return PVRSRV_OK;
+               }
+
+               if (psFwSysData->ePowState != RGXFWIF_POW_FORCED_IDLE)
+               {
+                       eError = PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED;
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Powered units state can not be changed, when not IDLE",
+                                        __func__));
+                       return eError;
+               }
+       }
+#endif
+
+       eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set Power sync prim",
+                               __func__));
+               return eError;
+       }
+
+       sPowUnitsStateMaskChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
+       sPowUnitsStateMaskChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_NUM_UNITS_CHANGE;
+       sPowUnitsStateMaskChange.uCmdData.sPowData.uPowerReqData.ui32PowUnitsStateMask = ui32PowUnitsStateMask;
+
+       PDUMPCOMMENT(psDeviceNode,
+                    "Scheduling command to change power units state to 0x%X",
+                    ui32PowUnitsStateMask);
+       eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
+                                             &sPowUnitsStateMaskChange,
+                                             PDUMP_FLAGS_NONE,
+                                             &ui32CmdKCCBSlot);
+
+       if (eError != PVRSRV_OK)
+       {
+               PDUMPCOMMENT(psDeviceNode,
+                            "Scheduling command to change power units state. Error:%u",
+                            eError);
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Scheduling KCCB to change power units state. Error:%u",
+                                __func__, eError));
+               return eError;
+       }
+
+       /* Wait for the firmware to answer. */
+       eError = RGXPollForGPCommandCompletion(psDeviceNode,
+                                     psDevInfo->psPowSyncPrim->pui32LinAddr,
+                                                                 0x1, 0xFFFFFFFF);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Timeout waiting for idle request", __func__));
+               return eError;
+       }
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode,
+                    "%s: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    __func__, psDevInfo->psPowSyncPrim->pui32LinAddr,
+                    RGXFWIF_DM_GP);
+
+       SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
+                                       1,
+                                       0xffffffff,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0);
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*
+ @Function     RGXAPMLatencyChange
+*/
+PVRSRV_ERROR RGXAPMLatencyChange(IMG_HANDLE            hDevHandle,
+                                 IMG_UINT32            ui32ActivePMLatencyms,
+                                 IMG_BOOL              bActivePMLatencyPersistant)
+{
+
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR            eError;
+       RGXFWIF_RUNTIME_CFG     *psRuntimeCfg = psDevInfo->psRGXFWIfRuntimeCfg;
+       IMG_UINT32                      ui32CmdKCCBSlot;
+       PVRSRV_DEV_POWER_STATE  ePowerState;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       eError = PVRSRVPowerLock(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "RGXAPMLatencyChange: Failed to acquire power lock"));
+               return eError;
+       }
+
+       /* Update runtime configuration with the new values and ensure the
+        * new APM latency is written to memory before requesting the FW to
+        * read it
+        */
+       psRuntimeCfg->ui32ActivePMLatencyms = ui32ActivePMLatencyms;
+       psRuntimeCfg->bActivePMLatencyPersistant = bActivePMLatencyPersistant;
+       OSWriteMemoryBarrier(&psRuntimeCfg->bActivePMLatencyPersistant);
+
+       eError = PVRSRVGetDevicePowerState(psDeviceNode, &ePowerState);
+
+       if ((eError == PVRSRV_OK) && (ePowerState != PVRSRV_DEV_POWER_STATE_OFF))
+       {
+               RGXFWIF_KCCB_CMD        sActivePMLatencyChange;
+               sActivePMLatencyChange.eCmdType = RGXFWIF_KCCB_CMD_POW;
+               sActivePMLatencyChange.uCmdData.sPowData.ePowType = RGXFWIF_POW_APM_LATENCY_CHANGE;
+
+               PDUMPCOMMENT(psDeviceNode,
+                            "Scheduling command to change APM latency to %u",
+                            ui32ActivePMLatencyms);
+               eError = RGXSendCommandAndGetKCCBSlot(psDeviceNode->pvDevice,
+                                                     &sActivePMLatencyChange,
+                                                     PDUMP_FLAGS_NONE,
+                                                     &ui32CmdKCCBSlot);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PDUMPCOMMENT(psDeviceNode,
+                                    "Scheduling command to change APM latency failed. Error:%u",
+                                    eError);
+                       PVR_DPF((PVR_DBG_ERROR, "RGXAPMLatencyChange: Scheduling KCCB to change APM latency failed. Error:%u", eError));
+                       goto ErrorExit;
+               }
+       }
+
+ErrorExit:
+       PVRSRVPowerUnlock(psDeviceNode);
+
+       return eError;
+}
+
+/*
+       RGXActivePowerRequest
+*/
+PVRSRV_ERROR RGXActivePowerRequest(IMG_HANDLE hDevHandle)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       const RGXFWIF_SYSDATA *psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+
+       psDevInfo->ui32ActivePMReqTotal++;
+
+       /* Powerlock to avoid further requests from racing with the FW hand-shake
+        * from now on (previous kicks to this point are detected by the FW)
+        * PVRSRVPowerLock is replaced with PVRSRVPowerTryLock to avoid
+        * potential dead lock between PDumpWriteLock and PowerLock
+        * during 'DriverLive + PDUMP=1 + EnableAPM=1'.
+        */
+       eError = PVRSRVPowerTryLock(psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       PVR_LOG_ERROR(eError, "PVRSRVPowerTryLock");
+               }
+               else
+               {
+                       psDevInfo->ui32ActivePMReqRetry++;
+               }
+               goto _RGXActivePowerRequest_PowerLock_failed;
+       }
+
+       /* Check again for IDLE once we have the power lock */
+       if (psFwSysData->ePowState == RGXFWIF_POW_IDLE)
+       {
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+               SetFirmwareHandshakeIdleTime(RGXReadHWTimerReg(psDevInfo)-psFwSysData->ui64StartIdleTime);
+#endif
+
+               PDUMPPOWCMDSTART(psDeviceNode);
+               eError = PVRSRVSetDevicePowerStateKM(psDeviceNode,
+                                                    PVRSRV_DEV_POWER_STATE_OFF,
+                                                    PVRSRV_POWER_FLAGS_NONE);
+               PDUMPPOWCMDEND(psDeviceNode);
+
+               if (eError == PVRSRV_OK)
+               {
+                       psDevInfo->ui32ActivePMReqOk++;
+               }
+               else if (eError == PVRSRV_ERROR_DEVICE_POWER_CHANGE_DENIED)
+               {
+                       psDevInfo->ui32ActivePMReqDenied++;
+               }
+       }
+       else
+       {
+               psDevInfo->ui32ActivePMReqNonIdle++;
+       }
+
+       PVRSRVPowerUnlock(psDeviceNode);
+
+_RGXActivePowerRequest_PowerLock_failed:
+
+       return eError;
+}
+/*
+       RGXForcedIdleRequest
+*/
+
+#define RGX_FORCED_IDLE_RETRY_COUNT 10
+
+PVRSRV_ERROR RGXForcedIdleRequest(IMG_HANDLE hDevHandle, IMG_BOOL bDeviceOffPermitted)
+{
+       PVRSRV_DEVICE_NODE    *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO    *psDevInfo = psDeviceNode->pvDevice;
+       RGXFWIF_KCCB_CMD      sPowCmd;
+       PVRSRV_ERROR          eError;
+       IMG_UINT32            ui32RetryCount = 0;
+       IMG_UINT32            ui32CmdKCCBSlot;
+#if !defined(NO_HARDWARE)
+       const RGXFWIF_SYSDATA *psFwSysData;
+#endif
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+#if !defined(NO_HARDWARE)
+       psFwSysData = psDevInfo->psRGXFWIfFwSysData;
+
+       /* Firmware already forced idle */
+       if (psFwSysData->ePowState == RGXFWIF_POW_FORCED_IDLE)
+       {
+               return PVRSRV_OK;
+       }
+
+       /* Firmware is not powered. Sometimes this is permitted, for instance we were forcing idle to power down. */
+       if (psFwSysData->ePowState == RGXFWIF_POW_OFF)
+       {
+               return (bDeviceOffPermitted) ? PVRSRV_OK : PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED;
+       }
+#endif
+
+       eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set Power sync prim",
+                               __func__));
+               return eError;
+       }
+       sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
+       sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
+       sPowCmd.uCmdData.sPowData.uPowerReqData.ePowRequestType = RGXFWIF_POWER_FORCE_IDLE;
+
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Sending forced idle command");
+
+       /* Send one forced IDLE command to GP */
+       eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                             &sPowCmd,
+                                             PDUMP_FLAGS_NONE,
+                                             &ui32CmdKCCBSlot);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to send idle request", __func__));
+               return eError;
+       }
+
+       /* Wait for GPU to finish current workload */
+       do {
+               eError = RGXPollForGPCommandCompletion(psDeviceNode,
+                                             psDevInfo->psPowSyncPrim->pui32LinAddr,
+                                                                         0x1, 0xFFFFFFFF);
+               if ((eError == PVRSRV_OK) || (ui32RetryCount == RGX_FORCED_IDLE_RETRY_COUNT))
+               {
+                       break;
+               }
+               ui32RetryCount++;
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: Request timeout. Retry %d of %d",
+                                __func__, ui32RetryCount, RGX_FORCED_IDLE_RETRY_COUNT));
+       } while (IMG_TRUE);
+
+       if (eError != PVRSRV_OK)
+       {
+               RGXFWNotifyHostTimeout(psDevInfo);
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Idle request failed. Firmware potentially left in forced idle state",
+                                __func__));
+               return eError;
+       }
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
+
+       SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
+                                       1,
+                                       0xffffffff,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0);
+#endif
+
+#if !defined(NO_HARDWARE)
+       /* Check the firmware state for idleness */
+       if (psFwSysData->ePowState != RGXFWIF_POW_FORCED_IDLE)
+       {
+               return PVRSRV_ERROR_DEVICE_IDLE_REQUEST_DENIED;
+       }
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*
+       RGXCancelForcedIdleRequest
+*/
+PVRSRV_ERROR RGXCancelForcedIdleRequest(IMG_HANDLE hDevHandle)
+{
+       PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
+       RGXFWIF_KCCB_CMD        sPowCmd;
+       PVRSRV_ERROR            eError = PVRSRV_OK;
+       IMG_UINT32                      ui32CmdKCCBSlot;
+       PVRSRV_VZ_RET_IF_MODE(GUEST, PVRSRV_OK);
+
+       eError = SyncPrimSet(psDevInfo->psPowSyncPrim, 0);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set Power sync prim",
+                               __func__));
+               goto ErrorExit;
+       }
+
+       /* Send the IDLE request to the FW */
+       sPowCmd.eCmdType = RGXFWIF_KCCB_CMD_POW;
+       sPowCmd.uCmdData.sPowData.ePowType = RGXFWIF_POW_FORCED_IDLE_REQ;
+       sPowCmd.uCmdData.sPowData.uPowerReqData.ePowRequestType = RGXFWIF_POWER_CANCEL_FORCED_IDLE;
+
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXForcedIdleRequest: Sending cancel forced idle command");
+
+       /* Send cancel forced IDLE command to GP */
+       eError = RGXSendCommandAndGetKCCBSlot(psDevInfo,
+                                             &sPowCmd,
+                                             PDUMP_FLAGS_NONE,
+                                             &ui32CmdKCCBSlot);
+
+       if (eError != PVRSRV_OK)
+       {
+               PDUMPCOMMENT(psDeviceNode,
+                            "RGXCancelForcedIdleRequest: Failed to send cancel IDLE request for DM%d",
+                            RGXFWIF_DM_GP);
+               goto ErrorExit;
+       }
+
+       /* Wait for the firmware to answer. */
+       eError = RGXPollForGPCommandCompletion(psDeviceNode,
+                                     psDevInfo->psPowSyncPrim->pui32LinAddr,
+                                                                 1, 0xFFFFFFFF);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Timeout waiting for cancel idle request", __func__));
+               goto ErrorExit;
+       }
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGXCancelForcedIdleRequest: Poll for Kernel SyncPrim [0x%p] on DM %d",
+                    psDevInfo->psPowSyncPrim->pui32LinAddr, RGXFWIF_DM_GP);
+
+       SyncPrimPDumpPol(psDevInfo->psPowSyncPrim,
+                                       1,
+                                       0xffffffff,
+                                       PDUMP_POLL_OPERATOR_EQUAL,
+                                       0);
+#endif
+
+       return eError;
+
+ErrorExit:
+       PVR_DPF((PVR_DBG_ERROR, "%s: Firmware potentially left in forced idle state", __func__));
+       return eError;
+}
+
+#if defined(SUPPORT_VALIDATION)
+#define RGX_POWER_DOMAIN_STATE_INVALID (0xFFFFFFFF)
+
+PVRSRV_ERROR RGXPowerDomainInitState(RGX_POWER_DOMAIN_STATE *psState,
+                                                                               IMG_UINT32 ui32MaxPowUnitsCount)
+{
+       /*
+        * Total power domain states = 2^(Max power unit count)
+        */
+       IMG_UINT32 ui32TotalStates = 1 << ui32MaxPowUnitsCount;
+       IMG_UINT32 i;
+
+       /**
+        * Allocate memory for storing last transition for each power domain
+        * state.
+        */
+       psState->paui32LastTransition = OSAllocMem(ui32TotalStates *
+                                                                                          sizeof(*psState->paui32LastTransition));
+
+       if (!psState->paui32LastTransition)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: failed to allocate memory ", __func__));
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       /**
+        * Initialize last transition of each state to invalid
+        */
+       for (i=0; i<ui32TotalStates; i++)
+       {
+               psState->paui32LastTransition[i] = RGX_POWER_DOMAIN_STATE_INVALID;
+       }
+
+       psState->ui32PowUnitsCount = ui32MaxPowUnitsCount;
+       psState->ui32CurrentState = RGX_POWER_DOMAIN_STATE_INVALID;
+
+       return PVRSRV_OK;
+}
+
+void RGXPowerDomainDeInitState(RGX_POWER_DOMAIN_STATE *psState)
+{
+       psState->ui32PowUnitsCount = 0;
+
+       if (psState->paui32LastTransition)
+       {
+               OSFreeMem(psState->paui32LastTransition);
+       }
+}
+
+IMG_UINT32 RGXPowerDomainGetNextState(RGX_POWER_DOMAIN_STATE *psState)
+{
+       IMG_UINT32 ui32NextState, ui32CurrentState = psState->ui32CurrentState;
+       IMG_UINT32 ui32TotalStates = 1 << psState->ui32PowUnitsCount;
+
+       if (ui32CurrentState == RGX_POWER_DOMAIN_STATE_INVALID)
+       {
+               /**
+                * Start with all units powered off.
+                */
+               ui32NextState = 0;
+       }
+       else if (psState->paui32LastTransition[ui32CurrentState] == RGX_POWER_DOMAIN_STATE_INVALID)
+       {
+               ui32NextState = ui32CurrentState;
+               psState->paui32LastTransition[ui32CurrentState] = ui32CurrentState;
+       }
+       else
+       {
+               ui32NextState = (psState->paui32LastTransition[ui32CurrentState] + 1) % ui32TotalStates;
+               psState->paui32LastTransition[ui32CurrentState] = ui32NextState;
+       }
+
+       psState->ui32CurrentState = ui32NextState;
+       return ui32NextState;
+}
+#endif
+/******************************************************************************
+ End of file (rgxpower.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxpower.h
new file mode 100644 (file)
index 0000000..e92938d
--- /dev/null
@@ -0,0 +1,272 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX power header file
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX power
+@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(RGXPOWER_H)
+#define RGXPOWER_H
+
+#include "pvrsrv_error.h"
+#include "img_types.h"
+#include "servicesext.h"
+#include "rgxdevice.h"
+
+
+/*!
+******************************************************************************
+
+ @Function     RGXPrePowerState
+
+ @Description
+
+ does necessary preparation before power state transition
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eNewPowerState : New power state
+ @Input           eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPrePowerState(IMG_HANDLE                               hDevHandle,
+                                                         PVRSRV_DEV_POWER_STATE        eNewPowerState,
+                                                         PVRSRV_DEV_POWER_STATE        eCurrentPowerState,
+                                                         PVRSRV_POWER_FLAGS            ePwrFlags);
+
+/*!
+******************************************************************************
+
+ @Function     RGXPostPowerState
+
+ @Description
+
+ does necessary preparation after power state transition
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eNewPowerState : New power state
+ @Input           eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPostPowerState(IMG_HANDLE                              hDevHandle,
+                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState,
+                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState,
+                                                          PVRSRV_POWER_FLAGS           ePwrFlags);
+
+/*!
+******************************************************************************
+
+ @Function     RGXVzPrePowerState
+
+ @Description
+
+ does necessary preparation before power state transition on a vz driver
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eNewPowerState : New power state
+ @Input           eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXVzPrePowerState(IMG_HANDLE                             hDevHandle,
+                                                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                                                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
+                                                               PVRSRV_POWER_FLAGS              ePwrFlags);
+
+/*!
+******************************************************************************
+
+ @Function     RGXVzPostPowerState
+
+ @Description
+
+ does necessary preparation after power state transition on a vz driver
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eNewPowerState : New power state
+ @Input           eCurrentPowerState : Current power state
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXVzPostPowerState(IMG_HANDLE                            hDevHandle,
+                                                                PVRSRV_DEV_POWER_STATE eNewPowerState,
+                                                                PVRSRV_DEV_POWER_STATE eCurrentPowerState,
+                                                                PVRSRV_POWER_FLAGS             ePwrFlags);
+
+/*!
+******************************************************************************
+
+ @Function     RGXPreClockSpeedChange
+
+ @Description
+
+       Does processing required before an RGX clock speed change.
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eCurrentPowerState : Power state of the device
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPreClockSpeedChange(IMG_HANDLE                         hDevHandle,
+                                                                       PVRSRV_DEV_POWER_STATE  eCurrentPowerState);
+
+/*!
+******************************************************************************
+
+ @Function     RGXPostClockSpeedChange
+
+ @Description
+
+       Does processing required after an RGX clock speed change.
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           eCurrentPowerState : Power state of the device
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXPostClockSpeedChange(IMG_HANDLE                                hDevHandle,
+                                                                        PVRSRV_DEV_POWER_STATE eCurrentPowerState);
+
+
+/*!
+******************************************************************************
+
+ @Function     RGXPowUnitsStateMaskChange
+
+ @Description Changes power state of SPUs
+
+ @Input           hDevHandle              RGX Device Node.
+ @Input           ui32PowUnitsStateMask   Mask containing power state of SPUs.
+                                   Each bit corresponds to an SPU.
+                                   Bit position corresponds to SPU number
+                                   i.e. Bit0 is SPU0, Bit1 is SPU1 etc.
+                                   '1' indicates ON and '0' indicates OFF.
+                                   Value must be non-zero.
+ @Return   PVRSRV_ERROR.
+
+******************************************************************************/
+PVRSRV_ERROR RGXPowUnitsStateMaskChange(IMG_HANDLE hDevHandle,
+                                                                               IMG_UINT32 ui32PowUnitsStateMask);
+
+/*!
+******************************************************************************
+
+ @Function     RGXAPMLatencyChange
+
+ @Description
+
+       Changes the wait duration used before firmware indicates IDLE.
+       Reducing this value will cause the firmware to shut off faster and
+       more often but may increase bubbles in GPU scheduling due to the added
+       power management activity. If bPersistent is NOT set, APM latency will
+       return back to system default on power up.
+
+ @Input           hDevHandle : RGX Device Node
+ @Input           ui32ActivePMLatencyms : Number of milliseconds to wait
+ @Input           bActivePMLatencyPersistant : Set to ensure new value is not reset
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXAPMLatencyChange(IMG_HANDLE                            hDevHandle,
+                               IMG_UINT32                              ui32ActivePMLatencyms,
+                               IMG_BOOL                                bActivePMLatencyPersistant);
+
+/*!
+******************************************************************************
+
+ @Function     RGXActivePowerRequest
+
+ @Description Initiate a handshake with the FW to power off the GPU
+
+ @Input           hDevHandle : RGX Device Node
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXActivePowerRequest(IMG_HANDLE hDevHandle);
+
+/*!
+******************************************************************************
+
+ @Function     RGXForcedIdleRequest
+
+ @Description Initiate a handshake with the FW to idle the GPU
+
+ @Input           hDevHandle : RGX Device Node
+
+ @Input    bDeviceOffPermitted : Set to indicate device state being off is not
+                                 erroneous.
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXForcedIdleRequest(IMG_HANDLE hDevHandle, IMG_BOOL bDeviceOffPermitted);
+
+/*!
+******************************************************************************
+
+ @Function     RGXCancelForcedIdleRequest
+
+ @Description Send a request to cancel idle to the firmware.
+
+ @Input           hDevHandle : RGX Device Node
+
+ @Return   PVRSRV_ERROR :
+
+******************************************************************************/
+PVRSRV_ERROR RGXCancelForcedIdleRequest(IMG_HANDLE hDevHandle);
+
+
+#if defined(SUPPORT_VALIDATION)
+PVRSRV_ERROR RGXPowerDomainInitState(RGX_POWER_DOMAIN_STATE *psState,
+                                                                        IMG_UINT32 ui32MaxPowUnitsCount);
+
+void RGXPowerDomainDeInitState(RGX_POWER_DOMAIN_STATE *psState);
+
+IMG_UINT32 RGXPowerDomainGetNextState(RGX_POWER_DOMAIN_STATE *psState);
+#endif
+#endif /* RGXPOWER_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.c
new file mode 100644 (file)
index 0000000..a4ebb9e
--- /dev/null
@@ -0,0 +1,767 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX Ray routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX Ray routines
+@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.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "srvkm.h"
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxray.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "rgxccb.h"
+#include "rgxhwperf.h"
+#include "ospvr_gputrace.h"
+#include "htbuffer.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+#include "rgx_memallocflags.h"
+
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_internal.h"
+
+#include "rgxtimerquery.h"
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+
+/* Enable this to dump the compiled list of UFOs prior to kick call */
+#define ENABLE_CMP_UFO_DUMP    0
+
+//#define CMP_CHECKPOINT_DEBUG 1
+//#define CMP_CHECKPOINT_DEBUG 1
+
+#if defined(CMP_CHECKPOINT_DEBUG)
+#define CHKPT_DBG(X) PVR_DPF(X)
+#else
+#define CHKPT_DBG(X)
+#endif
+
+struct _RGX_SERVER_RAY_CONTEXT_ {
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       DEVMEM_MEMDESC                          *psFWRayContextMemDesc;
+       DEVMEM_MEMDESC                          *psContextStateMemDesc;
+       POS_LOCK                                        hLock;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WORKEST_HOST_DATA                       sWorkEstData;
+#endif
+       RGX_SERVER_COMMON_CONTEXT       *psServerCommonContext;
+       SYNC_ADDR_LIST                          sSyncAddrListFence;
+       SYNC_ADDR_LIST                          sSyncAddrListUpdate;
+};
+
+PVRSRV_ERROR PVRSRVRGXCreateRayContextKM(CONNECTION_DATA                       *psConnection,
+                                                                                        PVRSRV_DEVICE_NODE             *psDeviceNode,
+                                                                                        IMG_UINT32                             ui32Priority,
+                                                                                        IMG_HANDLE                             hMemCtxPrivData,
+                                                                                        IMG_UINT32                             ui32ContextFlags,
+                                                                                        IMG_UINT32                             ui32StaticRayContextStateSize,
+                                                                                        IMG_PBYTE                              pStaticRayContextState,
+                                                                                        IMG_UINT64                             ui64RobustnessAddress,
+                                                                                        IMG_UINT32                             ui32MaxDeadlineMS,
+                                                                                        RGX_SERVER_RAY_CONTEXT **ppsRayContext)
+{
+       DEVMEM_MEMDESC                          *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+       RGX_SERVER_RAY_CONTEXT          *psRayContext;
+       RGXFWIF_FWRAYCONTEXT            *psFWRayContext;
+       RGX_COMMON_CONTEXT_INFO         sInfo = {NULL};
+       PVRSRV_ERROR                            eError;
+
+       *ppsRayContext = NULL;
+
+       psRayContext = OSAllocZMem(sizeof(*psRayContext));
+       if (psRayContext == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psRayContext->psDeviceNode = psDeviceNode;
+       /*
+               Create the FW ray context, this has the RDM common
+               context embedded within it
+        */
+       eError = DevmemFwAllocate(psDevInfo,
+                       sizeof(RGXFWIF_FWRAYCONTEXT),
+                       RGX_FWCOMCTX_ALLOCFLAGS,
+                       "FwRayContext",
+                       &psRayContext->psFWRayContextMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_fwraycontext;
+       }
+
+       eError = OSLockCreate(&psRayContext->hLock);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to create lock (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError)));
+               goto fail_createlock;
+       }
+
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware ray context suspend state");
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         sizeof(RGXFWIF_COMPUTECTX_STATE),
+                                                         RGX_FWCOMCTX_ALLOCFLAGS,
+                                                         "FwRayContextState",
+                                                         &psRayContext->psContextStateMemDesc);
+
+       eError = FWCommonContextAllocate(psConnection,
+                                                                        psDeviceNode,
+                                                                        REQ_TYPE_RAY,
+                                                                        RGXFWIF_DM_RAY,
+                                                                        hMemCtxPrivData,
+                                                                        psRayContext->psFWRayContextMemDesc,
+                                                                        offsetof(RGXFWIF_FWRAYCONTEXT, sRDMContext),
+                                                                        psFWMemContextMemDesc,
+                                                                        psRayContext->psContextStateMemDesc,
+                                                                        RGX_RDM_CCB_SIZE_LOG2,
+                                                                        RGX_RDM_CCB_MAX_SIZE_LOG2,
+                                                                        ui32ContextFlags,
+                                                                        ui32Priority,
+                                                                        ui32MaxDeadlineMS,
+                                                                        ui64RobustnessAddress,
+                                                                        &sInfo,
+                                                                        &psRayContext->psServerCommonContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to init Ray fw common context (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError)));
+               goto fail_raycommoncontext;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psRayContext->psFWRayContextMemDesc,
+                       (void **)&psFWRayContext);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_acquire_cpu_mapping;
+       }
+
+       OSDeviceMemCopy(&psFWRayContext->sStaticRayContextState, pStaticRayContextState, ui32StaticRayContextStateSize);
+       DevmemPDumpLoadMem(psRayContext->psFWRayContextMemDesc, 0, sizeof(RGXFWIF_FWCOMPUTECONTEXT), PDUMP_FLAGS_CONTINUOUS);
+       DevmemReleaseCpuVirtAddr(psRayContext->psFWRayContextMemDesc);
+
+       SyncAddrListInit(&psRayContext->sSyncAddrListFence);
+       SyncAddrListInit(&psRayContext->sSyncAddrListUpdate);
+
+       *ppsRayContext = psRayContext;
+
+       return PVRSRV_OK;
+fail_acquire_cpu_mapping:
+fail_raycommoncontext:
+       OSLockDestroy(psRayContext->hLock);
+fail_createlock:
+       DevmemFwUnmapAndFree(psDevInfo, psRayContext->psFWRayContextMemDesc);
+fail_fwraycontext:
+       OSFreeMem(psRayContext);
+
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXDestroyRayContextKM(RGX_SERVER_RAY_CONTEXT *psRayContext)
+{
+
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psRayContext->psDeviceNode->pvDevice;
+
+
+       /* Check if the FW has finished with this resource ... */
+       eError = RGXFWRequestCommonContextCleanUp(psRayContext->psDeviceNode,
+                                                                                         psRayContext->psServerCommonContext,
+                                                                                         RGXFWIF_DM_RAY,
+                                                                                         PDUMP_FLAGS_NONE);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               return eError;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+                                __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       /* ... it has so we can free its resources */
+       FWCommonContextFree(psRayContext->psServerCommonContext);
+       DevmemFwUnmapAndFree(psDevInfo, psRayContext->psContextStateMemDesc);
+       psRayContext->psServerCommonContext = NULL;
+
+
+       DevmemFwUnmapAndFree(psDevInfo, psRayContext->psFWRayContextMemDesc);
+
+       OSLockDestroy(psRayContext->hLock);
+       OSFreeMem(psRayContext);
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXKickRDMKM(RGX_SERVER_RAY_CONTEXT *psRayContext,
+                                                               IMG_UINT32                              ui32ClientUpdateCount,
+                                                               SYNC_PRIMITIVE_BLOCK    **pauiClientUpdateUFODevVarBlock,
+                                                               IMG_UINT32                              *paui32ClientUpdateSyncOffset,
+                                                               IMG_UINT32                              *paui32ClientUpdateValue,
+                                                               PVRSRV_FENCE                    iCheckFence,
+                                                               PVRSRV_TIMELINE                 iUpdateTimeline,
+                                                               PVRSRV_FENCE                    *piUpdateFence,
+                                                               IMG_CHAR                                pcszUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH],
+                                                               IMG_UINT32                              ui32CmdSize,
+                                                               IMG_PBYTE                               pui8DMCmd,
+                                                               IMG_UINT32                              ui32PDumpFlags,
+                                                               IMG_UINT32                              ui32ExtJobRef)
+{
+
+       RGXFWIF_KCCB_CMD                sRayKCCBCmd;
+       RGX_CCB_CMD_HELPER_DATA asCmdHelperData[1];
+       PVRSRV_ERROR                    eError, eError2;
+       IMG_UINT32                              ui32FWCtx;
+
+       PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+       PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+       PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+       PVRSRV_RGXDEV_INFO      *psDevInfo;
+       RGX_CLIENT_CCB          *psClientCCB;
+       IMG_UINT32              ui32IntJobRef;
+
+       IMG_BOOL                                bCCBStateOpen = IMG_FALSE;
+       IMG_UINT64 ui64FBSCEntryMask;
+       IMG_UINT32 ui32IntClientFenceCount = 0;
+       PRGXFWIF_UFO_ADDR *pauiIntFenceUFOAddress = NULL;
+       IMG_UINT32 ui32IntClientUpdateCount = 0;
+       PRGXFWIF_UFO_ADDR *pauiIntUpdateUFOAddress = NULL;
+       IMG_UINT32 *paui32IntUpdateValue = NULL;
+       PVRSRV_FENCE  iUpdateFence = PVRSRV_NO_FENCE;
+       IMG_UINT64               uiCheckFenceUID = 0;
+       IMG_UINT64               uiUpdateFenceUID = 0;
+       PSYNC_CHECKPOINT psUpdateSyncCheckpoint = NULL;
+       PSYNC_CHECKPOINT *apsFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32FenceSyncCheckpointCount = 0;
+       IMG_UINT32 *pui32IntAllocatedUpdateValues = NULL;
+       PVRSRV_CLIENT_SYNC_PRIM *psFenceTimelineUpdateSync = NULL;
+       IMG_UINT32 ui32FenceTimelineUpdateValue = 0;
+       void *pvUpdateFenceFinaliseData = NULL;
+
+       psDevInfo = FWCommonContextGetRGXDevInfo(psRayContext->psServerCommonContext);
+       psClientCCB = FWCommonContextGetClientCCB(psRayContext->psServerCommonContext);
+       ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
+
+       if (iUpdateTimeline >= 0 && !piUpdateFence)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       /* Ensure we haven't been given a null ptr to
+        * update values if we have been told we
+        * have updates
+        */
+       if (ui32ClientUpdateCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32ClientUpdateValue != NULL,
+                                       "paui32ClientUpdateValue NULL but "
+                                       "ui32ClientUpdateCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       /* Ensure the string is null-terminated (Required for safety) */
+       pcszUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH-1] = '\0';
+
+       OSLockAcquire(psRayContext->hLock);
+
+       eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListFence,
+                                                                       0,
+                                                                       NULL,
+                                                                       NULL);
+       if (eError != PVRSRV_OK)
+       {
+               goto err_populate_sync_addr_list;
+       }
+
+       ui32IntClientUpdateCount = ui32ClientUpdateCount;
+
+       eError = SyncAddrListPopulate(&psRayContext->sSyncAddrListUpdate,
+                                                                       ui32ClientUpdateCount,
+                                                                       pauiClientUpdateUFODevVarBlock,
+                                                                       paui32ClientUpdateSyncOffset);
+       if (eError != PVRSRV_OK)
+       {
+               goto err_populate_sync_addr_list;
+       }
+       if (ui32IntClientUpdateCount && !pauiIntUpdateUFOAddress)
+       {
+               pauiIntUpdateUFOAddress = psRayContext->sSyncAddrListUpdate.pasFWAddrs;
+       }
+       paui32IntUpdateValue = paui32ClientUpdateValue;
+
+       CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointResolveFence (iCheckFence=%d), psRayContext->psDeviceNode->hSyncCheckpointContext=<%p>...", __func__, iCheckFence, (void*)psRayContext->psDeviceNode->hSyncCheckpointContext));
+       /* Resolve the sync checkpoints that make up the input fence */
+       eError = SyncCheckpointResolveFence(psRayContext->psDeviceNode->hSyncCheckpointContext,
+                                                                               iCheckFence,
+                                                                               &ui32FenceSyncCheckpointCount,
+                                                                               &apsFenceSyncCheckpoints,
+                                           &uiCheckFenceUID, ui32PDumpFlags);
+       if (eError != PVRSRV_OK)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, returned ERROR (eError=%d)", __func__, eError));
+               goto fail_resolve_input_fence;
+       }
+       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, fence %d contained %d checkpoints (apsFenceSyncCheckpoints=<%p>)", __func__, iCheckFence, ui32FenceSyncCheckpointCount, (void*)apsFenceSyncCheckpoints));
+#if defined(CMP_CHECKPOINT_DEBUG)
+       if (ui32FenceSyncCheckpointCount > 0)
+       {
+               IMG_UINT32 ii;
+               for (ii=0; ii<ui32FenceSyncCheckpointCount; ii++)
+               {
+                       PSYNC_CHECKPOINT psNextCheckpoint = *(apsFenceSyncCheckpoints + ii);
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:    apsFenceSyncCheckpoints[%d]=<%p>", __func__, ii, (void*)psNextCheckpoint));
+               }
+       }
+#endif
+       /* Create the output fence (if required) */
+       if (iUpdateTimeline != PVRSRV_NO_TIMELINE)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointCreateFence (iUpdateFence=%d, iUpdateTimeline=%d,  psRayContext->psDeviceNode->hSyncCheckpointContext=<%p>)...", __func__, iUpdateFence, iUpdateTimeline, (void*)psRayContext->psDeviceNode->hSyncCheckpointContext));
+               eError = SyncCheckpointCreateFence(psRayContext->psDeviceNode,
+                                                  pcszUpdateFenceName,
+                                                                                  iUpdateTimeline,
+                                                                                  psRayContext->psDeviceNode->hSyncCheckpointContext,
+                                                                                  &iUpdateFence,
+                                                                                  &uiUpdateFenceUID,
+                                                                                  &pvUpdateFenceFinaliseData,
+                                                                                  &psUpdateSyncCheckpoint,
+                                                                                  (void*)&psFenceTimelineUpdateSync,
+                                                                                  &ui32FenceTimelineUpdateValue,
+                                                                                  ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...returned error (%d)", __func__, eError));
+                       goto fail_create_output_fence;
+               }
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...returned from SyncCheckpointCreateFence (iUpdateFence=%d, psFenceTimelineUpdateSync=<%p>, ui32FenceTimelineUpdateValue=%u)", __func__, iUpdateFence, psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue));
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u, psFenceTimelineUpdateSync=<%p>", __func__, ui32IntClientUpdateCount, (void*)psFenceTimelineUpdateSync));
+               /* Append the sync prim update for the timeline (if required) */
+               if (psFenceTimelineUpdateSync)
+               {
+                       IMG_UINT32 *pui32TimelineUpdateWp = NULL;
+
+                       /* Allocate memory to hold the list of update values (including our timeline update) */
+                       pui32IntAllocatedUpdateValues = OSAllocMem(sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                       if (!pui32IntAllocatedUpdateValues)
+                       {
+                               /* Failed to allocate memory */
+                               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                               goto fail_alloc_update_values_mem;
+                       }
+                       OSCachedMemSet(pui32IntAllocatedUpdateValues, 0xbb, sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                       /* Copy the update values into the new memory, then append our timeline update value */
+                       OSCachedMemCopy(pui32IntAllocatedUpdateValues, paui32IntUpdateValue, sizeof(*pui32IntAllocatedUpdateValues) * ui32IntClientUpdateCount);
+#if defined(CMP_CHECKPOINT_DEBUG)
+                       if (ui32IntClientUpdateCount > 0)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u:", __func__, ui32IntClientUpdateCount));
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+                       /* Now set the additional update value */
+                       pui32TimelineUpdateWp = pui32IntAllocatedUpdateValues + ui32IntClientUpdateCount;
+                       *pui32TimelineUpdateWp = ui32FenceTimelineUpdateValue;
+                       ui32IntClientUpdateCount++;
+                       /* Now make sure paui32ClientUpdateValue points to pui32IntAllocatedUpdateValues */
+                       paui32ClientUpdateValue = pui32IntAllocatedUpdateValues;
+
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: append the timeline sync prim addr <%p> to the compute context update list", __func__,  (void*)psFenceTimelineUpdateSync));
+                       /* Now append the timeline sync prim addr to the compute context update list */
+                       SyncAddrListAppendSyncPrim(&psRayContext->sSyncAddrListUpdate,
+                                                  psFenceTimelineUpdateSync);
+#if defined(CMP_CHECKPOINT_DEBUG)
+                       if (ui32IntClientUpdateCount > 0)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: ui32IntClientUpdateCount=%u:", __func__, ui32IntClientUpdateCount));
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+                       /* Ensure paui32IntUpdateValue is now pointing to our new array of update values */
+                       paui32IntUpdateValue = pui32IntAllocatedUpdateValues;
+               }
+       }
+
+       /* Append the checks (from input fence) */
+       if (ui32FenceSyncCheckpointCount > 0)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append %d sync checkpoints to Ray RDM Fence (&psRayContext->sSyncAddrListFence=<%p>)...", __func__, ui32FenceSyncCheckpointCount, (void*)&psRayContext->sSyncAddrListFence));
+#if defined(CMP_CHECKPOINT_DEBUG)
+               if (ui32IntClientUpdateCount > 0)
+               {
+                       IMG_UINT32 iii;
+                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pauiIntFenceUFOAddress;
+
+                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                               pui32Tmp++;
+                       }
+               }
+#endif
+               SyncAddrListAppendCheckpoints(&psRayContext->sSyncAddrListFence,
+                                                                         ui32FenceSyncCheckpointCount,
+                                                                         apsFenceSyncCheckpoints);
+               if (!pauiIntFenceUFOAddress)
+               {
+                       pauiIntFenceUFOAddress = psRayContext->sSyncAddrListFence.pasFWAddrs;
+               }
+               ui32IntClientFenceCount += ui32FenceSyncCheckpointCount;
+       }
+#if defined(CMP_CHECKPOINT_DEBUG)
+       if (ui32IntClientUpdateCount > 0)
+       {
+               IMG_UINT32 iii;
+               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)paui32IntUpdateValue;
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Dumping %d update values (paui32IntUpdateValue=<%p>)...", __func__, ui32IntClientUpdateCount, (void*)paui32IntUpdateValue));
+               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: paui32IntUpdateValue[%d] = <%p>", __func__, iii, (void*)pui32Tmp));
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: *paui32IntUpdateValue[%d] = 0x%x", __func__, iii, *pui32Tmp));
+                       pui32Tmp++;
+               }
+       }
+#endif
+
+       if (psUpdateSyncCheckpoint)
+       {
+               /* Append the update (from output fence) */
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append 1 sync checkpoint to Ray RDM Update (&psRayContext->sSyncAddrListUpdate=<%p>, psUpdateSyncCheckpoint=<%p>)...", __func__, (void*)&psRayContext->sSyncAddrListUpdate , (void*)psUpdateSyncCheckpoint));
+               SyncAddrListAppendCheckpoints(&psRayContext->sSyncAddrListUpdate,
+                                                                         1,
+                                                                         &psUpdateSyncCheckpoint);
+               if (!pauiIntUpdateUFOAddress)
+               {
+                       pauiIntUpdateUFOAddress = psRayContext->sSyncAddrListUpdate.pasFWAddrs;
+               }
+               ui32IntClientUpdateCount++;
+#if defined(CMP_CHECKPOINT_DEBUG)
+               if (ui32IntClientUpdateCount > 0)
+               {
+                       IMG_UINT32 iii;
+                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pauiIntUpdateUFOAddress;
+
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pauiIntUpdateUFOAddress=<%p>, pui32Tmp=<%p>, ui32IntClientUpdateCount=%u", __func__, (void*)pauiIntUpdateUFOAddress, (void*)pui32Tmp, ui32IntClientUpdateCount));
+                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pauiIntUpdateUFOAddress[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                               pui32Tmp++;
+                       }
+               }
+#endif
+       }
+       CHKPT_DBG((PVR_DBG_ERROR, "%s:   (after pvr_sync) ui32IntClientFenceCount=%d, ui32IntClientUpdateCount=%d", __func__, ui32IntClientFenceCount, ui32IntClientUpdateCount));
+
+#if (ENABLE_CMP_UFO_DUMP == 1)
+               PVR_DPF((PVR_DBG_ERROR, "%s: dumping Ray (RDM) fence/updates syncs...", __func__));
+               {
+                       IMG_UINT32 ii;
+                       PRGXFWIF_UFO_ADDR *psTmpIntFenceUFOAddress = pauiIntFenceUFOAddress;
+                       PRGXFWIF_UFO_ADDR *psTmpIntUpdateUFOAddress = pauiIntUpdateUFOAddress;
+                       IMG_UINT32 *pui32TmpIntUpdateValue = paui32IntUpdateValue;
+
+                       /* Dump Fence syncs and Update syncs */
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d Ray (RDM) fence syncs (&psRayContext->sSyncAddrListFence=<%p>, pauiIntFenceUFOAddress=<%p>):", __func__, ui32IntClientFenceCount, (void*)&psRayContext->sSyncAddrListFence, (void*)pauiIntFenceUFOAddress));
+                       for (ii=0; ii<ui32IntClientFenceCount; ii++)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, CheckValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientFenceCount, (void*)psTmpIntFenceUFOAddress, psTmpIntFenceUFOAddress->ui32Addr));
+                               psTmpIntFenceUFOAddress++;
+                       }
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d Ray (RDM) update syncs (&psRayContext->sSyncAddrListUpdate=<%p>, pauiIntUpdateUFOAddress=<%p>):", __func__, ui32IntClientUpdateCount, (void*)&psRayContext->sSyncAddrListUpdate, (void*)pauiIntUpdateUFOAddress));
+                       for (ii=0; ii<ui32IntClientUpdateCount; ii++)
+                       {
+                               if (psTmpIntUpdateUFOAddress->ui32Addr & 0x1)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=%d", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr, *pui32TmpIntUpdateValue));
+                                       pui32TmpIntUpdateValue++;
+                               }
+                               psTmpIntUpdateUFOAddress++;
+                       }
+               }
+#endif
+
+       RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRayContext->psDeviceNode->pvDevice,
+                                 &pPreAddr,
+                                 &pPostAddr,
+                                 &pRMWUFOAddr);
+
+       /*
+       * Extract the FBSC entries from MMU Context for the deferred FBSC invalidate command,
+       * in other words, take the value and set it to zero afterwards.
+       * FBSC Entry Mask must be extracted from MMU ctx and updated just before the kick starts
+       * as it must be ready at the time of context activation.
+       */
+       {
+               eError = RGXExtractFBSCEntryMaskFromMMUContext(psRayContext->psDeviceNode,
+                                                                                                               FWCommonContextGetServerMMUCtx(psRayContext->psServerCommonContext),
+                                                                                                               &ui64FBSCEntryMask);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Failed to extract FBSC Entry Mask (%d)", eError));
+                       goto fail_invalfbsc;
+               }
+       }
+
+       RGXCmdHelperInitCmdCCB(psDevInfo,
+                              psClientCCB,
+                              ui64FBSCEntryMask,
+                              ui32IntClientFenceCount,
+                              pauiIntFenceUFOAddress,
+                              NULL,
+                              ui32IntClientUpdateCount,
+                              pauiIntUpdateUFOAddress,
+                              paui32IntUpdateValue,
+                              ui32CmdSize,
+                              pui8DMCmd,
+                           &pPreAddr,
+                           &pPostAddr,
+                           &pRMWUFOAddr,
+                              RGXFWIF_CCB_CMD_TYPE_RAY,
+                              ui32ExtJobRef,
+                              ui32IntJobRef,
+                              ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+                              NULL,
+#else
+                              NULL,
+#endif
+                              "Ray",
+                              bCCBStateOpen,
+                              asCmdHelperData);
+       eError = RGXCmdHelperAcquireCmdCCB(ARRAY_SIZE(asCmdHelperData), asCmdHelperData);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_cmdaquire;
+       }
+
+       if (eError == PVRSRV_OK)
+       {
+               /*
+                       All the required resources are ready at this point, we can't fail so
+                       take the required server sync operations and commit all the resources
+               */
+               RGXCmdHelperReleaseCmdCCB(1, asCmdHelperData, "RDM", FWCommonContextGetFWAddress(psRayContext->psServerCommonContext).ui32Addr);
+       }
+
+       /* Construct the kernel compute CCB command. */
+       sRayKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+       sRayKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psRayContext->psServerCommonContext);
+       sRayKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+       sRayKCCBCmd.uCmdData.sCmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+       sRayKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+       sRayKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+
+       ui32FWCtx = FWCommonContextGetFWAddress(psRayContext->psServerCommonContext).ui32Addr;
+
+       RGXSRV_HWPERF_ENQ(psRayContext,
+                         OSGetCurrentClientProcessIDKM(),
+                         ui32FWCtx,
+                         ui32ExtJobRef,
+                         ui32IntJobRef,
+                         RGX_HWPERF_KICK_TYPE_RS,
+                         iCheckFence,
+                         iUpdateFence,
+                         iUpdateTimeline,
+                         uiCheckFenceUID,
+                         uiUpdateFenceUID,
+                         NO_DEADLINE,
+                         NO_CYCEST);
+
+       /*
+        * Submit the compute command to the firmware.
+        */
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError2 = RGXScheduleCommand(psRayContext->psDeviceNode->pvDevice,
+                                                                       RGXFWIF_DM_RAY,
+                                                                       &sRayKCCBCmd,
+                                                                       ui32PDumpFlags);
+               if (eError2 != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError2 != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s failed to schedule kernel CCB command (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError2)));
+               if (eError == PVRSRV_OK)
+               {
+                       eError = eError2;
+               }
+       }
+       else
+       {
+               PVRGpuTraceEnqueueEvent(psRayContext->psDeviceNode->pvDevice,
+                                       ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
+                                       RGX_HWPERF_KICK_TYPE_RS);
+       }
+       /*
+        * Now check eError (which may have returned an error from our earlier call
+        * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
+        * so we check it now...
+        */
+       if (eError != PVRSRV_OK )
+       {
+               goto fail_cmdaquire;
+       }
+
+#if defined(NO_HARDWARE)
+       /* If NO_HARDWARE, signal the output fence's sync checkpoint and sync prim */
+       if (psUpdateSyncCheckpoint)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Signalling NOHW sync checkpoint<%p>, ID:%d, FwAddr=0x%x", __func__, (void*)psUpdateSyncCheckpoint, SyncCheckpointGetId(psUpdateSyncCheckpoint), SyncCheckpointGetFirmwareAddr(psUpdateSyncCheckpoint)));
+               SyncCheckpointSignalNoHW(psUpdateSyncCheckpoint);
+       }
+       if (psFenceTimelineUpdateSync)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Updating NOHW sync prim<%p> to %d", __func__, (void*)psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue));
+               SyncPrimNoHwUpdate(psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue);
+       }
+       SyncCheckpointNoHWUpdateTimelines(NULL);
+#endif /* defined(NO_HARDWARE) */
+
+       *piUpdateFence = iUpdateFence;
+
+       if (pvUpdateFenceFinaliseData && (iUpdateFence != PVRSRV_NO_FENCE))
+       {
+               SyncCheckpointFinaliseFence(psRayContext->psDeviceNode, iUpdateFence,
+                                           pvUpdateFenceFinaliseData,
+                                                                       psUpdateSyncCheckpoint, pcszUpdateFenceName);
+       }
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                                                apsFenceSyncCheckpoints);
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       /* Free memory allocated to hold the internal list of update values */
+       if (pui32IntAllocatedUpdateValues)
+       {
+               OSFreeMem(pui32IntAllocatedUpdateValues);
+               pui32IntAllocatedUpdateValues = NULL;
+       }
+       OSLockRelease(psRayContext->hLock);
+
+       return PVRSRV_OK;
+
+fail_cmdaquire:
+fail_invalfbsc:
+       SyncAddrListRollbackCheckpoints(psRayContext->psDeviceNode, &psRayContext->sSyncAddrListFence);
+       SyncAddrListRollbackCheckpoints(psRayContext->psDeviceNode, &psRayContext->sSyncAddrListUpdate);
+fail_alloc_update_values_mem:
+       if (iUpdateFence != PVRSRV_NO_FENCE)
+       {
+               SyncCheckpointRollbackFenceData(iUpdateFence, pvUpdateFenceFinaliseData);
+       }
+fail_create_output_fence:
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                                                apsFenceSyncCheckpoints);
+fail_resolve_input_fence:
+
+err_populate_sync_addr_list:
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       /* Free memory allocated to hold the internal list of update values */
+       if (pui32IntAllocatedUpdateValues)
+       {
+               OSFreeMem(pui32IntAllocatedUpdateValues);
+               pui32IntAllocatedUpdateValues = NULL;
+       }
+
+       OSLockRelease(psRayContext->hLock);
+       return eError;
+}
+
+/******************************************************************************
+ End of file (rgxray.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxray.h
new file mode 100644 (file)
index 0000000..3855a42
--- /dev/null
@@ -0,0 +1,113 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX ray functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX compute functionality
+@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(RGXRAY_H_)
+#define RGXRAY_H_
+
+#include "devicemem.h"
+#include "device.h"
+#include "rgxfwutils.h"
+#include "rgxdebug.h"
+#include "pvr_notifier.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "connection_server.h"
+
+
+typedef struct _RGX_SERVER_RAY_CONTEXT_ RGX_SERVER_RAY_CONTEXT;
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXCreateRayContextKM
+
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXCreateRayContextKM(CONNECTION_DATA               *psConnection,
+                                                                                PVRSRV_DEVICE_NODE             *psDeviceNode,
+                                                                                IMG_UINT32                             ui32Priority,
+                                                                                IMG_HANDLE                             hMemCtxPrivData,
+                                                                                IMG_UINT32                             ui32ContextFlags,
+                                                                                IMG_UINT32                             ui32StaticRayContextStateSize,
+                                                                                IMG_PBYTE                              pStaticRayContextState,
+                                                                                IMG_UINT64                             ui64RobustnessAddress,
+                                                                                IMG_UINT32                             ui32MaxDeadlineMS,
+                                                                                RGX_SERVER_RAY_CONTEXT **ppsRayContext);
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXDestroyRayContextKM
+
+ @Description
+       Server-side implementation of RGXDestroyRayContext
+
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXDestroyRayContextKM(RGX_SERVER_RAY_CONTEXT *psRayContext);
+
+
+/*!
+*******************************************************************************
+ @Function     PVRSRVRGXKickRDMKM
+
+ @Description
+       Server-side implementation of RGXKickRDM
+
+ @Return   PVRSRV_ERROR
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXKickRDMKM(RGX_SERVER_RAY_CONTEXT *psRayContext,
+                                                               IMG_UINT32                              ui32ClientUpdateCount,
+                                                               SYNC_PRIMITIVE_BLOCK    **pauiClientUpdateUFODevVarBlock,
+                                                               IMG_UINT32                              *paui32ClientUpdateSyncOffset,
+                                                               IMG_UINT32                              *paui32ClientUpdateValue,
+                                                               PVRSRV_FENCE                    iCheckFence,
+                                                               PVRSRV_TIMELINE                 iUpdateTimeline,
+                                                               PVRSRV_FENCE                    *piUpdateFence,
+                                                               IMG_CHAR                                pcszUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH],
+                                                               IMG_UINT32                              ui32CmdSize,
+                                                               IMG_PBYTE                               pui8DMCmd,
+                                                               IMG_UINT32                              ui32PDumpFlags,
+                                                               IMG_UINT32                              ui32ExtJobRef);
+
+
+#endif /* RGXRAY_H_ */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxsrvinit.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxsrvinit.c
new file mode 100644 (file)
index 0000000..a4f4d1c
--- /dev/null
@@ -0,0 +1,1537 @@
+/*************************************************************************/ /*!
+@File
+@Title          Services initialisation routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@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.
+*/ /**************************************************************************/
+
+#include "img_defs.h"
+#include "srvinit.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "km_apphint_defs.h"
+
+#include "htbuffer_types.h"
+#include "htbuffer_init.h"
+
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+
+#include "rgx_fwif_km.h"
+#include "pdump_km.h"
+#include "rgx_compat_bvnc.h"
+
+#include "rgxdefs_km.h"
+#include "pvrsrv.h"
+
+#include "rgxinit.h"
+#include "rgxmulticore.h"
+
+#include "rgx_compat_bvnc.h"
+
+#include "osfunc.h"
+
+#include "rgxdefs_km.h"
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+#include "virt_validation_defs.h"
+#endif
+
+#include "rgx_fwif_hwperf.h"
+#include "rgx_hwperf_table.h"
+
+static const RGXFW_HWPERF_CNTBLK_TYPE_MODEL gasCntBlkTypeModel[] =
+{
+#define X(a, b, c, d, e, f, g)  {a, b, 0xFF, d, e, f, NULL}
+RGX_CNT_BLK_TYPE_MODEL_DIRECT_LIST,
+RGX_CNT_BLK_TYPE_MODEL_INDIRECT_LIST
+#undef X
+};
+
+#include "fwload.h"
+#include "rgxlayer_impl.h"
+#include "rgxfwimageutils.h"
+#include "rgxfwutils.h"
+
+#include "rgx_bvnc_defs_km.h"
+
+#include "rgxdevice.h"
+#include "pvrsrv.h"
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+#include "rgxdevice.h"
+#include "pvrsrv_device.h"
+#endif
+
+#define DRIVER_MODE_HOST               0          /* AppHint value for host driver mode */
+
+#define        HW_PERF_FILTER_DEFAULT         0x00000000 /* Default to no HWPerf */
+#define HW_PERF_FILTER_DEFAULT_ALL_ON  0xFFFFFFFF /* All events */
+#define AVAIL_POW_UNITS_MASK_DEFAULT   (PVRSRV_APPHINT_HWVALAVAILABLESPUMASK)
+#define AVAIL_RAC_MASK_DEFAULT         (PVRSRV_APPHINT_HWVALAVAILABLERACMASK)
+
+/* Kernel CCB size */
+
+#if !defined(PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE)
+#define PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE 4
+#endif
+#if !defined(PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE)
+#define PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE 16
+#endif
+
+#if PVRSRV_APPHINT_KCCB_SIZE_LOG2 < PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE
+#error PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too low.
+#elif PVRSRV_APPHINT_KCCB_SIZE_LOG2 > PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE
+#error PVRSRV_APPHINT_KCCB_SIZE_LOG2 is too high.
+#endif
+
+#if defined(SUPPORT_VALIDATION)
+#include "pvrsrv_apphint.h"
+#endif
+
+#include "os_srvinit_param.h"
+
+#if defined(__linux__)
+#include "km_apphint.h"
+#else
+/*!
+*******************************************************************************
+ * AppHint mnemonic data type helper tables
+******************************************************************************/
+/* apphint map of name vs. enable flag */
+static SRV_INIT_PARAM_UINT32_LOOKUP htb_loggroup_tbl[] = {
+#define X(a, b) { #b, HTB_LOG_GROUP_FLAG(a) },
+       HTB_LOG_SFGROUPLIST
+#undef X
+};
+/* apphint map of arg vs. OpMode */
+static SRV_INIT_PARAM_UINT32_LOOKUP htb_opmode_tbl[] = {
+       { "droplatest", HTB_OPMODE_DROPLATEST},
+       { "dropoldest", HTB_OPMODE_DROPOLDEST},
+       /* HTB should never be started in HTB_OPMODE_BLOCK
+        * as this can lead to deadlocks
+        */
+};
+
+static SRV_INIT_PARAM_UINT32_LOOKUP fwt_logtype_tbl[] = {
+       { "trace", 0},
+       { "none", 0}
+#if defined(SUPPORT_TBI_INTERFACE)
+       , { "tbi", 1}
+#endif
+};
+
+static SRV_INIT_PARAM_UINT32_LOOKUP timecorr_clk_tbl[] = {
+       { "mono", 0 },
+       { "mono_raw", 1 },
+       { "sched", 2 }
+};
+
+static SRV_INIT_PARAM_UINT32_LOOKUP fwt_loggroup_tbl[] = { RGXFWIF_LOG_GROUP_NAME_VALUE_MAP };
+
+/*
+ * Services AppHints initialisation
+ */
+#define X(a, b, c, d, e) SrvInitParamInit ## b(a, d, e)
+APPHINT_LIST_ALL
+#undef X
+#endif /* defined(__linux__) */
+
+/*
+ * Container for all the apphints used by this module
+ */
+typedef struct _RGX_SRVINIT_APPHINTS_
+{
+       IMG_UINT32 ui32DriverMode;
+       IMG_BOOL   bEnableSignatureChecks;
+       IMG_UINT32 ui32SignatureChecksBufSize;
+
+       IMG_BOOL   bAssertOnOutOfMem;
+       IMG_BOOL   bAssertOnHWRTrigger;
+#if defined(SUPPORT_VALIDATION)
+       IMG_UINT32 ui32RenderKillingCtl;
+       IMG_UINT32 ui32CDMTDMKillingCtl;
+       IMG_BOOL   bValidateIrq;
+       IMG_BOOL   bValidateSOCUSCTimer;
+       IMG_UINT32 ui32AvailablePowUnitsMask;
+       IMG_UINT32 ui32AvailableRACMask;
+       IMG_BOOL   bInjectPowUnitsStateMaskChange;
+       IMG_BOOL   bEnablePowUnitsStateMaskChange;
+       IMG_UINT32 ui32FBCDCVersionOverride;
+       IMG_UINT32 aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_LAST];
+       IMG_UINT32 aui32USRMNumRegions[RGXFWIF_USRM_DM_LAST];
+       IMG_UINT64 aui64UVBRMNumRegions[RGXFWIF_UVBRM_DM_LAST];
+#endif
+       IMG_BOOL   bCheckMlist;
+       IMG_BOOL   bDisableClockGating;
+       IMG_BOOL   bDisableDMOverlap;
+       IMG_BOOL   bDisableFEDLogging;
+       IMG_BOOL   bDisablePDP;
+       IMG_BOOL   bEnableDMKillRand;
+       IMG_BOOL   bEnableRandomCsw;
+       IMG_BOOL   bEnableSoftResetCsw;
+       IMG_BOOL   bFilteringMode;
+       IMG_BOOL   bHWPerfDisableCounterFilter;
+       IMG_BOOL   bZeroFreelist;
+       IMG_UINT32 ui32EnableFWContextSwitch;
+       IMG_UINT32 ui32FWContextSwitchProfile;
+       IMG_UINT32 ui32ISPSchedulingLatencyMode;
+       IMG_UINT32 ui32HWPerfFWBufSize;
+       IMG_UINT32 ui32HWPerfHostBufSize;
+       IMG_UINT32 ui32HWPerfFilter0;
+       IMG_UINT32 ui32HWPerfFilter1;
+       IMG_UINT32 ui32HWPerfHostFilter;
+       IMG_UINT32 ui32TimeCorrClock;
+       IMG_UINT32 ui32HWRDebugDumpLimit;
+       IMG_UINT32 ui32JonesDisableMask;
+       IMG_UINT32 ui32LogType;
+       IMG_UINT32 ui32TruncateMode;
+       IMG_UINT32 ui32KCCBSizeLog2;
+       IMG_UINT32 ui32CDMArbitrationMode;
+       FW_PERF_CONF eFirmwarePerf;
+       RGX_ACTIVEPM_CONF eRGXActivePMConf;
+       RGX_RD_POWER_ISLAND_CONF eRGXRDPowerIslandConf;
+
+       IMG_BOOL   bEnableTrustedDeviceAceConfig;
+       IMG_UINT32 ui32FWContextSwitchCrossDM;
+#if defined(SUPPORT_PHYSMEM_TEST) && !defined(INTEGRITY_OS) && !defined(__QNXNTO__)
+       IMG_UINT32 ui32PhysMemTestPasses;
+#endif
+} RGX_SRVINIT_APPHINTS;
+
+/*!
+*******************************************************************************
+
+ @Function      GetApphints
+
+ @Description   Read init time apphints and initialise internal variables
+
+ @Input         psHints : Pointer to apphints container
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void GetApphints(PVRSRV_RGXDEV_INFO *psDevInfo, RGX_SRVINIT_APPHINTS *psHints)
+{
+       void *pvParamState = SrvInitParamOpen();
+       IMG_UINT32 ui32ParamTemp;
+
+       /*
+        * NB AppHints initialised to a default value via SrvInitParamInit* macros above
+        */
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    DriverMode,                         psHints->ui32DriverMode);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    EnableSignatureChecks,      psHints->bEnableSignatureChecks);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    SignatureChecksBufSize, psHints->ui32SignatureChecksBufSize);
+
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,      pvParamState,    AssertOutOfMemory,               psHints->bAssertOnOutOfMem);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,      pvParamState,    AssertOnHWRTrigger,            psHints->bAssertOnHWRTrigger);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,      pvParamState,    CheckMList,                            psHints->bCheckMlist);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    DisableClockGating,            psHints->bDisableClockGating);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    DisableDMOverlap,                psHints->bDisableDMOverlap);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,      pvParamState,    DisableFEDLogging,              psHints->bDisableFEDLogging);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,    pvParamState,    EnableAPM,                                    ui32ParamTemp);
+       psHints->eRGXActivePMConf = ui32ParamTemp;
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    EnableGenericDMKillingRandMode,  psHints->bEnableDMKillRand);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    EnableRandomContextSwitch,        psHints->bEnableRandomCsw);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,    EnableSoftResetContextSwitch,  psHints->bEnableSoftResetCsw);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    EnableFWContextSwitch,   psHints->ui32EnableFWContextSwitch);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    EnableRDPowerIsland,                          ui32ParamTemp);
+       psHints->eRGXRDPowerIslandConf = ui32ParamTemp;
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    FirmwarePerf,                                 ui32ParamTemp);
+       psHints->eFirmwarePerf = ui32ParamTemp;
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    FWContextSwitchProfile, psHints->ui32FWContextSwitchProfile);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,
+               HWPerfDisableCounterFilter, psHints->bHWPerfDisableCounterFilter);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    HWPerfHostBufSizeInKB,       psHints->ui32HWPerfHostBufSize);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,    HWPerfFWBufSizeInKB,           psHints->ui32HWPerfFWBufSize);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,    pvParamState,    KernelCCBSizeLog2,                psHints->ui32KCCBSizeLog2);
+
+       if (psHints->ui32KCCBSizeLog2 < PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "KCCB size %u is too low, setting to %u",
+                        psHints->ui32KCCBSizeLog2, PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE));
+               psHints->ui32KCCBSizeLog2 = PVRSRV_RGX_LOG2_KERNEL_CCB_MIN_SIZE;
+       }
+       else if (psHints->ui32KCCBSizeLog2 > PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE)
+       {
+               PVR_DPF((PVR_DBG_WARNING, "KCCB size %u is too high, setting to %u",
+                        psHints->ui32KCCBSizeLog2, PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE));
+               psHints->ui32KCCBSizeLog2 = PVRSRV_RGX_LOG2_KERNEL_CCB_MAX_SIZE;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       if (psHints->ui32KCCBSizeLog2 != PVRSRV_APPHINT_KCCB_SIZE_LOG2)
+       {
+               PVR_LOG(("KernelCCBSizeLog2 set to %u", psHints->ui32KCCBSizeLog2));
+       }
+#endif
+
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,
+               ISPSchedulingLatencyMode, psHints->ui32ISPSchedulingLatencyMode);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,     CDMArbitrationOverride,    psHints->ui32CDMArbitrationMode);
+#if defined(__linux__)
+       /* name changes */
+       {
+               IMG_UINT64 ui64Tmp;
+               SrvInitParamGetBOOL(psDevInfo->psDeviceNode,    pvParamState,    DisablePDumpPanic,                 psHints->bDisablePDP);
+               SrvInitParamGetUINT64(psDevInfo->psDeviceNode,  pvParamState,    HWPerfFWFilter,                                 ui64Tmp);
+               psHints->ui32HWPerfFilter0 = (IMG_UINT32)(ui64Tmp & 0xffffffffllu);
+               psHints->ui32HWPerfFilter1 = (IMG_UINT32)((ui64Tmp >> 32) & 0xffffffffllu);
+       }
+#else
+       SrvInitParamUnreferenced(DisablePDumpPanic);
+       SrvInitParamUnreferenced(HWPerfFWFilter);
+       SrvInitParamUnreferenced(RGXBVNC);
+#endif
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,      pvParamState,    HWPerfHostFilter,             psHints->ui32HWPerfHostFilter);
+       SrvInitParamGetUINT32List(psDevInfo->psDeviceNode,  pvParamState,    TimeCorrClock,                   psHints->ui32TimeCorrClock);
+       SrvInitParamGetUINT32(psDevInfo->psDeviceNode,      pvParamState,    HWRDebugDumpLimit,                            ui32ParamTemp);
+       psHints->ui32HWRDebugDumpLimit = MIN(ui32ParamTemp, RGXFWIF_HWR_DEBUG_DUMP_ALL);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    JonesDisableMask,                             ui32ParamTemp);
+       psHints->ui32JonesDisableMask = ui32ParamTemp & RGX_CR_JONES_FIX__ROGUE3__DISABLE_CLRMSK;
+
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,            pvParamState,    NewFilteringMode,                   psHints->bFilteringMode);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    TruncateMode,                     psHints->ui32TruncateMode);
+
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,        pvParamState,    ZeroFreelist,                        psHints->bZeroFreelist);
+#if defined(__linux__)
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    FWContextSwitchCrossDM, psHints->ui32FWContextSwitchCrossDM);
+#else
+       SrvInitParamUnreferenced(FWContextSwitchCrossDM);
+#endif
+
+#if defined(SUPPORT_PHYSMEM_TEST) && !defined(INTEGRITY_OS) && !defined(__QNXNTO__)
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    PhysMemTestPasses,           psHints->ui32PhysMemTestPasses);
+#endif
+
+#if defined(SUPPORT_VALIDATION)
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  KillingCtl,                              psHints->ui32RenderKillingCtl);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  CDMTDMKillingCtl,                        psHints->ui32CDMTDMKillingCtl);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,  ValidateIrq,                                     psHints->bValidateIrq);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,  ValidateSOCUSCTimer,                     psHints->bValidateSOCUSCTimer);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  HWValAvailableSPUMask,              psHints->ui32AvailablePowUnitsMask);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  HWValAvailableRACMask,                   psHints->ui32AvailableRACMask);
+       SrvInitParamGetBOOL(psDevInfo->psDeviceNode,      pvParamState,  GPUUnitsPowerChange,           psHints->bInjectPowUnitsStateMaskChange);
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,          pvParamState,  HWValEnableSPUPowerMaskChange, psHints->bEnablePowUnitsStateMaskChange);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  FBCDCVersionOverride,                psHints->ui32FBCDCVersionOverride);
+
+       /* Apphints for Unified Store virtual partitioning. */
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  USRMNumRegionsVDM,   psHints->aui32USRMNumRegions[RGXFWIF_USRM_DM_VDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  USRMNumRegionsDDM,   psHints->aui32USRMNumRegions[RGXFWIF_USRM_DM_DDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  USRMNumRegionsCDM,   psHints->aui32USRMNumRegions[RGXFWIF_USRM_DM_CDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  USRMNumRegionsPDM,   psHints->aui32USRMNumRegions[RGXFWIF_USRM_DM_PDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  USRMNumRegionsTDM,   psHints->aui32USRMNumRegions[RGXFWIF_USRM_DM_TDM]);
+
+       /* Apphints for UVB virtual partitioning. */
+       SrvInitParamGetUINT64(INITPARAM_NO_DEVICE,        pvParamState,  UVBRMNumRegionsVDM, psHints->aui64UVBRMNumRegions[RGXFWIF_UVBRM_DM_VDM]);
+       SrvInitParamGetUINT64(INITPARAM_NO_DEVICE,        pvParamState,  UVBRMNumRegionsDDM, psHints->aui64UVBRMNumRegions[RGXFWIF_UVBRM_DM_DDM]);
+
+       /* Apphints for TPU trilinear frac masking */
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  TPUTrilinearFracMaskPDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_PDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  TPUTrilinearFracMaskVDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_VDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  TPUTrilinearFracMaskCDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_CDM]);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,        pvParamState,  TPUTrilinearFracMaskTDM, psHints->aui32TPUTrilinearFracMask[RGXFWIF_TPU_DM_TDM]);
+#endif
+
+       /*
+        * FW logs apphints
+        */
+       {
+               IMG_UINT32 ui32LogGroup, ui32TraceOrTBI;
+
+               SrvInitParamGetUINT32BitField(psDevInfo->psDeviceNode,  pvParamState,    EnableLogGroup,    ui32LogGroup);
+               SrvInitParamGetUINT32List(psDevInfo->psDeviceNode,      pvParamState,    FirmwareLogType, ui32TraceOrTBI);
+
+               /* Defaulting to TRACE */
+               BITMASK_SET(ui32LogGroup, RGXFWIF_LOG_TYPE_TRACE);
+
+#if defined(SUPPORT_TBI_INTERFACE)
+               if (ui32TraceOrTBI == 1 /* TBI */)
+               {
+                       if ((ui32LogGroup & RGXFWIF_LOG_TYPE_GROUP_MASK) == 0)
+                       {
+                               /* No groups configured - defaulting to MAIN group */
+                               BITMASK_SET(ui32LogGroup, RGXFWIF_LOG_TYPE_GROUP_MAIN);
+                       }
+                       BITMASK_UNSET(ui32LogGroup, RGXFWIF_LOG_TYPE_TRACE);
+               }
+#endif
+
+               psHints->ui32LogType = ui32LogGroup;
+       }
+
+       SrvInitParamGetBOOL(INITPARAM_NO_DEVICE,  pvParamState,  EnableTrustedDeviceAceConfig,  psHints->bEnableTrustedDeviceAceConfig);
+
+       SrvInitParamClose(pvParamState);
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetFWConfigFlags
+
+ @Description   Initialise and return FW config flags
+
+ @Input         psHints            : Apphints container
+ @Input         pui32FWConfigFlags : Pointer to config flags
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void GetFWConfigFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    RGX_SRVINIT_APPHINTS *psHints,
+                                    IMG_UINT32 *pui32FWConfigFlags,
+                                    IMG_UINT32 *pui32FWConfigFlagsExt,
+                                    IMG_UINT32 *pui32FwOsCfgFlags)
+{
+       IMG_UINT32 ui32FWConfigFlags = 0;
+       IMG_UINT32 ui32FWConfigFlagsExt = 0;
+       IMG_UINT32 ui32FwOsCfgFlags = psHints->ui32FWContextSwitchCrossDM |
+                                     (psHints->ui32EnableFWContextSwitch & ~RGXFWIF_INICFG_OS_CTXSWITCH_CLRMSK);
+
+       if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               ui32FWConfigFlags = 0;
+               ui32FWConfigFlagsExt = 0;
+       }
+       else
+       {
+               ui32FWConfigFlags |= psHints->bAssertOnOutOfMem ? RGXFWIF_INICFG_ASSERT_ON_OUTOFMEMORY : 0;
+               ui32FWConfigFlags |= psHints->bAssertOnHWRTrigger ? RGXFWIF_INICFG_ASSERT_ON_HWR_TRIGGER : 0;
+               ui32FWConfigFlags |= psHints->bCheckMlist ? RGXFWIF_INICFG_CHECK_MLIST_EN : 0;
+               ui32FWConfigFlags |= psHints->bDisableClockGating ? RGXFWIF_INICFG_DISABLE_CLKGATING_EN : 0;
+               ui32FWConfigFlags |= psHints->bDisableDMOverlap ? RGXFWIF_INICFG_DISABLE_DM_OVERLAP : 0;
+               ui32FWConfigFlags |= psHints->bDisablePDP ? RGXFWIF_INICFG_DISABLE_PDP_EN : 0;
+               ui32FWConfigFlags |= psHints->bEnableDMKillRand ? RGXFWIF_INICFG_DM_KILL_MODE_RAND_EN : 0;
+               ui32FWConfigFlags |= psHints->bEnableRandomCsw ? RGXFWIF_INICFG_CTXSWITCH_MODE_RAND : 0;
+               ui32FWConfigFlags |= psHints->bEnableSoftResetCsw ? RGXFWIF_INICFG_CTXSWITCH_SRESET_EN : 0;
+               ui32FWConfigFlags |= (psHints->ui32HWPerfFilter0 != 0 || psHints->ui32HWPerfFilter1 != 0) ? RGXFWIF_INICFG_HWPERF_EN : 0;
+               ui32FWConfigFlags |= (psHints->ui32ISPSchedulingLatencyMode << RGXFWIF_INICFG_ISPSCHEDMODE_SHIFT) & RGXFWIF_INICFG_ISPSCHEDMODE_MASK;
+#if defined(SUPPORT_VALIDATION)
+#if defined(NO_HARDWARE) && defined(PDUMP)
+               ui32FWConfigFlags |= psHints->bValidateIrq ? RGXFWIF_INICFG_VALIDATE_IRQ : 0;
+#endif
+#endif
+               ui32FWConfigFlags |= psHints->bHWPerfDisableCounterFilter ? RGXFWIF_INICFG_HWP_DISABLE_FILTER : 0;
+               ui32FWConfigFlags |= (psHints->ui32FWContextSwitchProfile << RGXFWIF_INICFG_CTXSWITCH_PROFILE_SHIFT) & RGXFWIF_INICFG_CTXSWITCH_PROFILE_MASK;
+
+#if defined(SUPPORT_VALIDATION)
+               ui32FWConfigFlags |= psHints->bEnablePowUnitsStateMaskChange ? RGXFWIF_INICFG_SPU_POWER_STATE_MASK_CHANGE_EN : 0;
+               ui32FWConfigFlags |= psHints->bValidateSOCUSCTimer ? RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER : 0;
+
+               if ((ui32FWConfigFlags & RGXFWIF_INICFG_VALIDATE_SOCUSC_TIMER) &&
+                   ((psHints->eRGXActivePMConf != 0) || (psHints->eRGXRDPowerIslandConf != 0)))
+               {
+                       psHints->eRGXActivePMConf = 0;
+                       psHints->eRGXRDPowerIslandConf = 0;
+                       PVR_DPF((PVR_DBG_WARNING, "SoC/USC Timer test needs to run with both EnableAPM and EnableRDPowerIsland disabled.\n"
+                                "Overriding current value for both with new value 0."));
+               }
+#endif
+               ui32FWConfigFlags |= psDeviceNode->pfnHasFBCDCVersion31(psDeviceNode) ? RGXFWIF_INICFG_FBCDC_V3_1_EN : 0;
+               ui32FWConfigFlags |= (psHints->ui32CDMArbitrationMode << RGXFWIF_INICFG_CDM_ARBITRATION_SHIFT) & RGXFWIF_INICFG_CDM_ARBITRATION_MASK;
+       }
+
+       if ((ui32FwOsCfgFlags & RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN) &&
+               ((ui32FWConfigFlags & RGXFWIF_INICFG_ISPSCHEDMODE_MASK) == RGXFWIF_INICFG_ISPSCHEDMODE_NONE))
+       {
+               ui32FwOsCfgFlags &= ~RGXFWIF_INICFG_OS_CTXSWITCH_3D_EN;
+               PVR_DPF((PVR_DBG_WARNING, "ISPSchedulingLatencyMode=0 implies context switching is inoperable on DM_3D.\n"
+                                "Overriding current value EnableFWContextSwitch=0x%x with new value 0x%x",
+                                psHints->ui32EnableFWContextSwitch,
+                                ui32FwOsCfgFlags & RGXFWIF_INICFG_OS_CTXSWITCH_DM_ALL));
+       }
+
+       *pui32FWConfigFlags    = ui32FWConfigFlags;
+       *pui32FWConfigFlagsExt = ui32FWConfigFlagsExt;
+       *pui32FwOsCfgFlags     = ui32FwOsCfgFlags;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      GetFilterFlags
+
+ @Description   Initialise and return filter flags
+
+ @Input         psHints : Apphints container
+
+ @Return        IMG_UINT32 : Filter flags
+
+******************************************************************************/
+static INLINE IMG_UINT32 GetFilterFlags(RGX_SRVINIT_APPHINTS *psHints)
+{
+       IMG_UINT32 ui32FilterFlags = 0;
+
+       ui32FilterFlags |= psHints->bFilteringMode ? RGXFWIF_FILTCFG_NEW_FILTER_MODE : 0;
+       if (psHints->ui32TruncateMode == 2)
+       {
+               ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_INT;
+       }
+       else if (psHints->ui32TruncateMode == 3)
+       {
+               ui32FilterFlags |= RGXFWIF_FILTCFG_TRUNCATE_HALF;
+       }
+
+       return ui32FilterFlags;
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      InitDeviceFlags
+
+ @Description   Initialise and return device flags
+
+ @Input         psHints          : Apphints container
+ @Input         pui32DeviceFlags : Pointer to device flags
+
+ @Return        void
+
+******************************************************************************/
+static INLINE void InitDeviceFlags(RGX_SRVINIT_APPHINTS *psHints,
+                                  IMG_UINT32 *pui32DeviceFlags)
+{
+       IMG_UINT32 ui32DeviceFlags = 0;
+
+#if defined(SUPPORT_VALIDATION)
+       ui32DeviceFlags |= psHints->bInjectPowUnitsStateMaskChange? RGXKM_DEVICE_STATE_GPU_UNITS_POWER_CHANGE_EN : 0;
+#endif
+       ui32DeviceFlags |= psHints->bZeroFreelist ? RGXKM_DEVICE_STATE_ZERO_FREELIST : 0;
+       ui32DeviceFlags |= psHints->bDisableFEDLogging ? RGXKM_DEVICE_STATE_DISABLE_DW_LOGGING_EN : 0;
+#if defined(SUPPORT_VALIDATION)
+       ui32DeviceFlags |= psHints->bEnablePowUnitsStateMaskChange ? RGXKM_DEVICE_STATE_ENABLE_SPU_UNITS_POWER_MASK_CHANGE_EN : 0;
+#endif
+#if defined(PVRSRV_ENABLE_CCCB_GROW)
+       BITMASK_SET(ui32DeviceFlags, RGXKM_DEVICE_STATE_CCB_GROW_EN);
+#endif
+
+       *pui32DeviceFlags = ui32DeviceFlags;
+}
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
+/*!
+*******************************************************************************
+
+ @Function      RGXTDProcessFWImage
+
+ @Description   Fetch and send data used by the trusted device to complete
+                the FW image setup
+
+ @Input         psDeviceNode : Device node
+ @Input         psRGXFW      : Firmware blob
+ @Input         puFWParams   : Parameters used by the FW at boot time
+
+ @Return        PVRSRV_ERROR
+******************************************************************************/
+static PVRSRV_ERROR RGXTDProcessFWImage(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        OS_FW_IMAGE *psRGXFW,
+                                        PVRSRV_FW_BOOT_PARAMS *puFWParams)
+{
+       PVRSRV_DEVICE_CONFIG *psDevConfig = psDeviceNode->psDevConfig;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_TD_FW_PARAMS sTDFWParams;
+       PVRSRV_ERROR eError;
+
+       if (psDevConfig->pfnTDSendFWImage == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: TDSendFWImage not implemented!", __func__));
+               return PVRSRV_ERROR_NOT_IMPLEMENTED;
+       }
+
+       sTDFWParams.pvFirmware       = OSFirmwareData(psRGXFW);
+       sTDFWParams.ui32FirmwareSize = OSFirmwareSize(psRGXFW);
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               sTDFWParams.uFWP.sMeta = puFWParams->sMeta;
+       }
+       else
+       {
+               sTDFWParams.uFWP.sRISCV = puFWParams->sRISCV;
+       }
+
+       eError = psDevConfig->pfnTDSendFWImage(psDevConfig->hSysData, &sTDFWParams);
+
+       return eError;
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function      InitFirmware
+
+ @Description   Allocate, initialise and pdump Firmware code and data memory
+
+ @Input         psDeviceNode : Device Node
+ @Input         psHints      : Apphints
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR InitFirmware(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 RGX_SRVINIT_APPHINTS *psHints)
+{
+       OS_FW_IMAGE       *psRGXFW = NULL;
+       const IMG_BYTE    *pbRGXFirmware = NULL;
+
+       /* FW code memory */
+       IMG_DEVMEM_SIZE_T uiFWCodeAllocSize;
+       void              *pvFWCodeHostAddr;
+
+       /* FW data memory */
+       IMG_DEVMEM_SIZE_T uiFWDataAllocSize;
+       void              *pvFWDataHostAddr;
+
+       /* FW coremem code memory */
+       IMG_DEVMEM_SIZE_T uiFWCorememCodeAllocSize;
+       void              *pvFWCorememCodeHostAddr = NULL;
+
+       /* FW coremem data memory */
+       IMG_DEVMEM_SIZE_T uiFWCorememDataAllocSize;
+       void              *pvFWCorememDataHostAddr = NULL;
+
+       PVRSRV_FW_BOOT_PARAMS uFWParams;
+       RGX_LAYER_PARAMS sLayerParams;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       /*
+        * Get pointer to Firmware image
+        */
+       eError = RGXLoadAndGetFWData(psDeviceNode, &psRGXFW, &pbRGXFirmware);
+
+       if (eError != PVRSRV_OK)
+       {
+               /* Error or confirmation message generated in RGXLoadAndGetFWData */
+               goto fw_load_fail;
+       }
+
+       sLayerParams.psDevInfo = psDevInfo;
+
+       /*
+        * Allocate Firmware memory
+        */
+
+       eError = RGXGetFWImageAllocSize(&sLayerParams,
+                                       pbRGXFirmware,
+                                       OSFirmwareSize(psRGXFW),
+                                       &uiFWCodeAllocSize,
+                                       &uiFWDataAllocSize,
+                                       &uiFWCorememCodeAllocSize,
+                                       &uiFWCorememDataAllocSize);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: RGXGetFWImageAllocSize failed",
+                       __func__));
+               goto cleanup_initfw;
+       }
+
+       psDevInfo->ui32FWCodeSizeInBytes = uiFWCodeAllocSize;
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+       if (!RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_DMA))
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                       "%s: META DMA not available, disabling core memory code/data",
+                       __func__));
+               uiFWCorememCodeAllocSize = 0;
+               uiFWCorememDataAllocSize = 0;
+       }
+#endif
+
+       psDevInfo->ui32FWCorememCodeSizeInBytes = uiFWCorememCodeAllocSize;
+
+       eError = RGXInitAllocFWImgMem(psDeviceNode,
+                                     uiFWCodeAllocSize,
+                                     uiFWDataAllocSize,
+                                     uiFWCorememCodeAllocSize,
+                                     uiFWCorememDataAllocSize);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: PVRSRVRGXInitAllocFWImgMem failed (%d)",
+                       __func__,
+                       eError));
+               goto cleanup_initfw;
+       }
+
+       /*
+        * Acquire pointers to Firmware allocations
+        */
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc, &pvFWCodeHostAddr);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", cleanup_initfw);
+
+#else
+       /* We can't get a pointer to a secure FW allocation from within the DDK */
+       pvFWCodeHostAddr = NULL;
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc, &pvFWDataHostAddr);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", release_code);
+
+#else
+       /* We can't get a pointer to a secure FW allocation from within the DDK */
+       pvFWDataHostAddr = NULL;
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       if (uiFWCorememCodeAllocSize != 0)
+       {
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc, &pvFWCorememCodeHostAddr);
+               PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", release_data);
+       }
+       else
+       {
+               pvFWCorememCodeHostAddr = NULL;
+       }
+#else
+       /* We can't get a pointer to a secure FW allocation from within the DDK */
+       pvFWCorememCodeHostAddr = NULL;
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       if (uiFWCorememDataAllocSize != 0)
+       {
+               eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc, &pvFWCorememDataHostAddr);
+               PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", release_corememcode);
+       }
+       else
+#endif
+       {
+               pvFWCorememDataHostAddr = NULL;
+       }
+
+       /*
+        * Prepare FW boot parameters
+        */
+
+       if (RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, META))
+       {
+               uFWParams.sMeta.sFWCodeDevVAddr =  psDevInfo->sFWCodeDevVAddrBase;
+               uFWParams.sMeta.sFWDataDevVAddr =  psDevInfo->sFWDataDevVAddrBase;
+               uFWParams.sMeta.sFWCorememCodeDevVAddr =  psDevInfo->sFWCorememCodeDevVAddrBase;
+               uFWParams.sMeta.sFWCorememCodeFWAddr = psDevInfo->sFWCorememCodeFWAddr;
+               uFWParams.sMeta.uiFWCorememCodeSize = uiFWCorememCodeAllocSize;
+               uFWParams.sMeta.sFWCorememDataDevVAddr = psDevInfo->sFWCorememDataStoreDevVAddrBase;
+               uFWParams.sMeta.sFWCorememDataFWAddr = psDevInfo->sFWCorememDataStoreFWAddr;
+#if defined(RGXFW_META_SUPPORT_2ND_THREAD)
+               uFWParams.sMeta.ui32NumThreads = 2;
+#else
+               uFWParams.sMeta.ui32NumThreads = 1;
+#endif
+       }
+       else
+       {
+               uFWParams.sRISCV.sFWCorememCodeDevVAddr = psDevInfo->sFWCorememCodeDevVAddrBase;
+               uFWParams.sRISCV.sFWCorememCodeFWAddr   = psDevInfo->sFWCorememCodeFWAddr;
+               uFWParams.sRISCV.uiFWCorememCodeSize    = uiFWCorememCodeAllocSize;
+
+               uFWParams.sRISCV.sFWCorememDataDevVAddr = psDevInfo->sFWCorememDataStoreDevVAddrBase;
+               uFWParams.sRISCV.sFWCorememDataFWAddr   = psDevInfo->sFWCorememDataStoreFWAddr;
+               uFWParams.sRISCV.uiFWCorememDataSize    = uiFWCorememDataAllocSize;
+       }
+
+
+       /*
+        * Process the Firmware image and setup code and data segments.
+        *
+        * When the trusted device is enabled and the FW code lives
+        * in secure memory we will only setup the data segments here,
+        * while the code segments will be loaded to secure memory
+        * by the trusted device.
+        */
+       if (!psDeviceNode->bAutoVzFwIsUp)
+       {
+               eError = RGXProcessFWImage(&sLayerParams,
+                                                                  pbRGXFirmware,
+                                                                  pvFWCodeHostAddr,
+                                                                  pvFWDataHostAddr,
+                                                                  pvFWCorememCodeHostAddr,
+                                                                  pvFWCorememDataHostAddr,
+                                                                  &uFWParams);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: RGXProcessFWImage failed (%d)",
+                                __func__,
+                                eError));
+                       goto release_corememdata;
+               }
+       }
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(NO_HARDWARE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       if (psRGXFW)
+       {
+               RGXTDProcessFWImage(psDeviceNode, psRGXFW, &uFWParams);
+       }
+#endif
+
+
+       /*
+        * PDump Firmware allocations
+        */
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Dump firmware code image");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWCodeMemDesc,
+                          0,
+                          uiFWCodeAllocSize,
+                          PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Dump firmware data image");
+       DevmemPDumpLoadMem(psDevInfo->psRGXFWDataMemDesc,
+                          0,
+                          uiFWDataAllocSize,
+                          PDUMP_FLAGS_CONTINUOUS);
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       if (uiFWCorememCodeAllocSize != 0)
+       {
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Dump firmware coremem code image");
+               DevmemPDumpLoadMem(psDevInfo->psRGXFWCorememCodeMemDesc,
+                                                  0,
+                                                  uiFWCorememCodeAllocSize,
+                                                  PDUMP_FLAGS_CONTINUOUS);
+       }
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       if (uiFWCorememDataAllocSize != 0)
+       {
+               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                     "Dump firmware coremem data store image");
+               DevmemPDumpLoadMem(psDevInfo->psRGXFWIfCorememDataStoreMemDesc,
+                                                  0,
+                                                  uiFWCorememDataAllocSize,
+                                                  PDUMP_FLAGS_CONTINUOUS);
+       }
+#endif
+
+       /*
+        * Release Firmware allocations and clean up
+        */
+release_corememdata:
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+       if (uiFWCorememDataAllocSize !=0)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfCorememDataStoreMemDesc);
+       }
+
+release_corememcode:
+       if (uiFWCorememCodeAllocSize != 0)
+       {
+               DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCorememCodeMemDesc);
+       }
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+release_data:
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWDataMemDesc);
+#endif
+
+#if !defined(SUPPORT_TRUSTED_DEVICE) || defined(NO_HARDWARE) || defined(SUPPORT_SECURITY_VALIDATION)
+release_code:
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWCodeMemDesc);
+#endif
+cleanup_initfw:
+       OSUnloadFirmware(psRGXFW);
+fw_load_fail:
+
+       return eError;
+}
+
+IMG_INTERNAL static inline IMG_UINT32 RGXHWPerfMaxDefinedBlks(PVRSRV_RGXDEV_INFO *);
+IMG_INTERNAL /*static inline*/ IMG_UINT32 RGXGetHWPerfBlockConfig(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL **);
+
+IMG_INTERNAL /*static inline*/ IMG_UINT32
+RGXGetHWPerfBlockConfig(const RGXFW_HWPERF_CNTBLK_TYPE_MODEL **ppsModel)
+{
+    *ppsModel = gasCntBlkTypeModel;
+    return ARRAY_SIZE(gasCntBlkTypeModel);
+}
+
+/*!
+*******************************************************************************
+ @Function    RGXHWPerfMaxDefinedBlks
+
+ @Description Return the number of valid block-IDs for the given device node
+
+ @Input       (PVRSRV_RGXDEV_INFO *)   pvDevice    device-node to query
+
+ @Returns     (IMG_UINT32)             Number of block-IDs (RGX_CNTBLK_ID)
+                                       valid for this device.
+******************************************************************************/
+IMG_INTERNAL static inline IMG_UINT32
+RGXHWPerfMaxDefinedBlks(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       RGX_HWPERF_CNTBLK_RT_INFO sRtInfo;
+       IMG_UINT32  uiRetVal;
+       const RGXFW_HWPERF_CNTBLK_TYPE_MODEL *psHWPBlkConfig;
+       IMG_UINT32  uiNumArrayEls, ui;
+
+       uiRetVal = RGX_CNTBLK_ID_DIRECT_LAST;
+
+       uiNumArrayEls = RGXGetHWPerfBlockConfig(&psHWPBlkConfig);
+
+       if (psHWPBlkConfig == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Unexpected NULL Config Block", __func__));
+               return 0;
+       }
+       PVR_ASSERT(uiNumArrayEls > 0);
+
+       /* Iterate over each block-ID and find the number of instances of each
+        * block which are present for this device type. We only query the
+        * Indirect blocks as their presence varies according to GPU. All direct
+        * blocks have an entry - but they may not be physically present.
+        */
+       for (ui = RGX_CNTBLK_ID_DIRECT_LAST; ui < uiNumArrayEls; ui++)
+       {
+               if (rgx_hwperf_blk_present(&psHWPBlkConfig[ui], (void *)psDevInfo, &sRtInfo))
+               {
+                       uiRetVal += sRtInfo.uiNumUnits;
+                       PVR_DPF((PVR_DBG_VERBOSE, "%s: Block %u, NumUnits %u, Total %u",
+                               __func__, ui, sRtInfo.uiNumUnits, uiRetVal));
+               }
+#ifdef DEBUG
+               else
+               {
+                       if (psHWPBlkConfig[ui].uiCntBlkIdBase == RGX_CNTBLK_ID_RAC0)
+                       {
+                               if (PVRSRV_GET_DEVICE_FEATURE_VALUE(psDevInfo->psDeviceNode,
+                                   RAY_TRACING_ARCH) > 2U)
+                               {
+                                       PVR_DPF((PVR_DBG_WARNING, "%s: Block %u *NOT* present",
+                                               __func__, ui));
+                               }
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_WARNING, "%s: Block %u *NOT* present",
+                                       __func__, ui));
+                       }
+               }
+#endif
+       }
+
+       PVR_DPF((PVR_DBG_VERBOSE, "%s: Num Units = %u", __func__, uiRetVal));
+
+       return uiRetVal;
+}
+
+/*!
+*******************************************************************************
+
+ @Function      InitialiseHWPerfCounters
+
+ @Description   Initialisation of hardware performance counters and dumping
+                them out to pdump, so that they can be modified at a later
+                point.
+
+ @Input         pvDevice
+ @Input         psHWPerfDataMemDesc
+ @Input         psHWPerfInitDataInt
+
+ @Return        void
+
+******************************************************************************/
+
+static void InitialiseHWPerfCounters(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     void *pvDevice,
+                                     DEVMEM_MEMDESC *psHWPerfDataMemDesc,
+                                     RGXFWIF_HWPERF_CTL *psHWPerfInitDataInt)
+{
+       RGXFWIF_HWPERF_CTL_BLK *psHWPerfInitBlkData;
+       IMG_UINT32 ui32CntBlkModelLen;
+       const RGXFW_HWPERF_CNTBLK_TYPE_MODEL *asCntBlkTypeModel;
+       const RGXFW_HWPERF_CNTBLK_TYPE_MODEL* psBlkTypeDesc;
+       IMG_UINT32 ui32BlockID, ui32BlkCfgIdx, ui32CounterIdx;
+       RGX_HWPERF_CNTBLK_RT_INFO sCntBlkRtInfo;
+       IMG_UINT32 uiUnit;
+       IMG_BOOL bDirect;
+
+       ui32CntBlkModelLen = RGXGetHWPerfBlockConfig(&asCntBlkTypeModel);
+
+       PVR_DPF((PVR_DBG_VERBOSE, "%s: #BlockConfig entries = %d", __func__, ui32CntBlkModelLen));
+
+       /* Initialise the number of blocks in the RGXFWIF_HWPERF_CTL structure.
+        * This allows Firmware to validate that it has been correctly configured.
+        */
+       psHWPerfInitDataInt->ui32NumBlocks = RGXHWPerfMaxDefinedBlks(pvDevice);
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+           "HWPerf Block count = %u.",
+           psHWPerfInitDataInt->ui32NumBlocks);
+#if defined(PDUMP)
+       /* Ensure that we record the BVNC specific ui32NumBlocks in the PDUMP data
+        * so that when we playback we have the correct value present.
+        */
+       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+           (size_t)&(psHWPerfInitDataInt->ui32NumBlocks) - (size_t)(psHWPerfInitDataInt),
+           psHWPerfInitDataInt->ui32NumBlocks, PDUMP_FLAGS_CONTINUOUS);
+#endif /* defined(PDUMP) */
+
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+           "HWPerf Counter config starts here.");
+
+       /* Simply iterate over all the RGXFWIW_HWPERF_CTL blocks in order */
+       psHWPerfInitBlkData = &psHWPerfInitDataInt->sBlkCfg[0];
+
+       for (ui32BlkCfgIdx = 0; ui32BlkCfgIdx < ui32CntBlkModelLen;
+            ui32BlkCfgIdx++, psHWPerfInitBlkData++)
+       {
+               IMG_BOOL bSingleton;
+
+               /* Exit early if this core does not have any of these counter blocks
+                * due to core type/BVNC features.... */
+               psBlkTypeDesc = &asCntBlkTypeModel[ui32BlkCfgIdx];
+
+               if (psBlkTypeDesc == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Unexpected NULL - Index %d / %d",
+                           __func__, ui32BlkCfgIdx, ui32CntBlkModelLen));
+                       continue;
+               }
+
+               PVR_DPF((PVR_DBG_VERBOSE,
+                       "%s: CfgIdx = %u, InitBlkData @ 0x%p, BlkTypeDesc @ 0x%p",
+                       __func__, ui32BlkCfgIdx, psHWPerfInitBlkData, psBlkTypeDesc));
+
+               if (psBlkTypeDesc->pfnIsBlkPresent(psBlkTypeDesc, pvDevice, &sCntBlkRtInfo) == IMG_FALSE)
+               {
+                       PVR_DPF((PVR_DBG_VERBOSE, "%s: %s [ID 0x%x] NOT present", __func__,
+                           psBlkTypeDesc->pszBlockNameComment,
+                           psBlkTypeDesc->uiCntBlkIdBase ));
+                       /* Block isn't present, but has an entry in the table. Populate
+                        * the Init data so that we can track the block later.
+                        */
+                       psHWPerfInitBlkData->uiBlockID = psBlkTypeDesc->uiCntBlkIdBase;
+                       continue;
+               }
+#ifdef DEBUG
+               else
+               {
+                       PVR_DPF((PVR_DBG_VERBOSE, "%s: %s has %d %s", __func__,
+                               psBlkTypeDesc->pszBlockNameComment, sCntBlkRtInfo.uiNumUnits,
+                           (sCntBlkRtInfo.uiNumUnits > 1) ? "units" : "unit"));
+               }
+#endif /* DEBUG */
+
+               /* Program all counters in one block so those already on may
+                * be configured off and vice-versa. */
+               bDirect = psBlkTypeDesc->uiIndirectReg == 0;
+
+               /* Set if there is only one instance of this block-ID present */
+               bSingleton = sCntBlkRtInfo.uiNumUnits == 1;
+
+               for (ui32BlockID = psBlkTypeDesc->uiCntBlkIdBase, uiUnit = 0;
+                    ui32BlockID < psBlkTypeDesc->uiCntBlkIdBase+sCntBlkRtInfo.uiNumUnits;
+                    ui32BlockID++, uiUnit++)
+               {
+
+                       if (bDirect)
+                       {
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                                   "Block : %s", psBlkTypeDesc->pszBlockNameComment);
+                       }
+                       else
+                       {
+                               PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                   PDUMP_FLAGS_CONTINUOUS,
+                                   "Unit %d Block : %s%d",
+                                   ui32BlockID-psBlkTypeDesc->uiCntBlkIdBase,
+                                   psBlkTypeDesc->pszBlockNameComment, uiUnit);
+                       }
+
+                       psHWPerfInitBlkData->uiBlockID = ui32BlockID;
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                           "uiBlockID: The Block ID for the layout block. See RGX_CNTBLK_ID for further information.");
+#if defined(PDUMP)
+                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                                       (size_t)&(psHWPerfInitBlkData->uiBlockID) - (size_t)(psHWPerfInitDataInt),
+                                                       psHWPerfInitBlkData->uiBlockID,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+#endif /* PDUMP */
+
+                       psHWPerfInitBlkData->uiNumCounters = 0;
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                           "uiNumCounters (X): Specifies the number of valid counters"
+                           " [0..%d] which follow.", RGX_CNTBLK_COUNTERS_MAX);
+#if defined(PDUMP)
+                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                           (size_t)&(psHWPerfInitBlkData->uiNumCounters) - (size_t)(psHWPerfInitDataInt),
+                           psHWPerfInitBlkData->uiNumCounters,
+                           PDUMP_FLAGS_CONTINUOUS);
+#endif /* PDUMP */
+
+                       psHWPerfInitBlkData->uiEnabled = 0;
+                       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                           "uiEnabled: Set to 0x1 if the block needs to be enabled during playback.");
+#if defined(PDUMP)
+                       DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                           (size_t)&(psHWPerfInitBlkData->uiEnabled) - (size_t)(psHWPerfInitDataInt),
+                           psHWPerfInitBlkData->uiEnabled,
+                           PDUMP_FLAGS_CONTINUOUS);
+#endif /* PDUMP */
+
+                       for (ui32CounterIdx = 0; ui32CounterIdx < RGX_CNTBLK_COUNTERS_MAX; ui32CounterIdx++)
+                       {
+                               psHWPerfInitBlkData->aui32CounterCfg[ui32CounterIdx] = IMG_UINT32_C(0x00000000);
+
+                               if (bDirect)
+                               {
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                           PDUMP_FLAGS_CONTINUOUS,
+                                           "%s_COUNTER_%d",
+                                           psBlkTypeDesc->pszBlockNameComment, ui32CounterIdx);
+                               }
+                               else
+                               {
+                                       PDUMPCOMMENTWITHFLAGS(psDeviceNode,
+                                           PDUMP_FLAGS_CONTINUOUS,
+                                           "%s%d_COUNTER_%d",
+                                           psBlkTypeDesc->pszBlockNameComment,
+                                           uiUnit, ui32CounterIdx);
+                               }
+#if defined(PDUMP)
+                               DevmemPDumpLoadMemValue32(psHWPerfDataMemDesc,
+                                   (size_t)&(psHWPerfInitBlkData->aui32CounterCfg[ui32CounterIdx]) - (size_t)(psHWPerfInitDataInt),
+                                   psHWPerfInitBlkData->aui32CounterCfg[ui32CounterIdx],
+                                   PDUMP_FLAGS_CONTINUOUS);
+#endif /* PDUMP */
+
+                       }
+
+                       /* Update our block reference for indirect units which have more
+                        * than a single unit present. Only increment if we have more than
+                        * one unit left to process as the external loop counter will be
+                        * incremented after final unit is processed.
+                        */
+                       if (!bSingleton && (uiUnit < (sCntBlkRtInfo.uiNumUnits - 1)))
+                       {
+                               psHWPerfInitBlkData++;
+                       }
+               }
+       }
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "HWPerf Counter config finishes here.");
+}
+
+/*!
+*******************************************************************************
+
+ @Function      InitialiseAllCounters
+
+ @Description   Initialise HWPerf and custom counters
+
+ @Input         psDeviceNode : Device Node
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+static PVRSRV_ERROR InitialiseAllCounters(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+       RGXFWIF_HWPERF_CTL *psHWPerfInitData;
+       PVRSRV_ERROR eError;
+
+       eError = DevmemAcquireCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfCountersMemDesc, (void **)&psHWPerfInitData);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", failHWPerfCountersMemDescAqCpuVirt);
+
+       InitialiseHWPerfCounters(psDeviceNode, psDevInfo, psDevInfo->psRGXFWIfHWPerfCountersMemDesc, psHWPerfInitData);
+
+failHWPerfCountersMemDescAqCpuVirt:
+       DevmemReleaseCpuVirtAddr(psDevInfo->psRGXFWIfHWPerfCountersMemDesc);
+
+       return eError;
+}
+
+/*
+ * _ParseHTBAppHints:
+ *
+ * Generate necessary references to the globally visible AppHints which are
+ * declared in the above #include "km_apphint_defs.h"
+ * Without these local references some compiler tool-chains will treat
+ * unreferenced declarations as fatal errors. This function duplicates the
+ * HTB_specific apphint references which are made in htbserver.c:HTBInit()
+ * However, it makes absolutely *NO* use of these hints.
+ */
+static void
+_ParseHTBAppHints(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       void *pvParamState = NULL;
+       IMG_UINT32 ui32LogType;
+       IMG_BOOL bAnyLogGroupConfigured;
+       IMG_UINT32 ui32BufferSize;
+       IMG_UINT32 ui32OpMode;
+
+       /* Services initialisation parameters */
+       pvParamState = SrvInitParamOpen();
+       if (pvParamState == NULL)
+               return;
+
+       SrvInitParamGetUINT32BitField(INITPARAM_NO_DEVICE,  pvParamState,    EnableHTBLogGroup,    ui32LogType);
+       bAnyLogGroupConfigured = ui32LogType ? IMG_TRUE : IMG_FALSE;
+       SrvInitParamGetUINT32List(INITPARAM_NO_DEVICE,      pvParamState,    HTBOperationMode,      ui32OpMode);
+       SrvInitParamGetUINT32(INITPARAM_NO_DEVICE,          pvParamState,    HTBufferSizeInKB,  ui32BufferSize);
+
+       SrvInitParamClose(pvParamState);
+}
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+static PVRSRV_ERROR RGXValidateTDHeap(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                                         PVRSRV_PHYS_HEAP ePhysHeap,
+                                                                         PHYS_HEAP_USAGE_FLAGS ui32RequiredFlags)
+{
+       PHYS_HEAP *psHeap = psDeviceNode->apsPhysHeap[ePhysHeap];
+       PHYS_HEAP_USAGE_FLAGS ui32HeapFlags = PhysHeapGetFlags(psHeap);
+       PHYS_HEAP_USAGE_FLAGS ui32InvalidFlags = ~(PHYS_HEAP_USAGE_FW_PRIV_DATA | PHYS_HEAP_USAGE_FW_CODE
+                                                                                          | PHYS_HEAP_USAGE_GPU_SECURE);
+
+       PVR_LOG_RETURN_IF_FALSE_VA((ui32HeapFlags & ui32RequiredFlags) != 0,
+                                                          PVRSRV_ERROR_NOT_SUPPORTED,
+                                                          "TD heap is missing required flags. flags: 0x%x / required:0x%x",
+                                                          ui32HeapFlags,
+                                                          ui32RequiredFlags);
+
+       PVR_LOG_RETURN_IF_FALSE_VA((ui32HeapFlags & ui32InvalidFlags) == 0,
+                                                          PVRSRV_ERROR_NOT_SUPPORTED,
+                                                          "TD heap uses invalid flags. flags: 0x%x / invalid:0x%x",
+                                                          ui32HeapFlags,
+                                                          ui32InvalidFlags);
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXValidateTDHeaps(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       eError = RGXValidateTDHeap(psDeviceNode, PVRSRV_PHYS_HEAP_FW_PRIV_DATA, PHYS_HEAP_USAGE_FW_PRIV_DATA);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXValidateTDHeap:FW_PRIV_DATA");
+
+       eError = RGXValidateTDHeap(psDeviceNode, PVRSRV_PHYS_HEAP_FW_CODE, PHYS_HEAP_USAGE_FW_CODE);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXValidateTDHeap:FW_CODE");
+
+       eError = RGXValidateTDHeap(psDeviceNode, PVRSRV_PHYS_HEAP_GPU_SECURE, PHYS_HEAP_USAGE_GPU_SECURE);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXValidateTDHeap:GPU_SECURE");
+
+       return PVRSRV_OK;
+}
+#endif
+
+/*!
+*******************************************************************************
+
+ @Function      RGXInit
+
+ @Description   RGX Initialisation
+
+ @Input         psDeviceNode
+
+ @Return        PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR RGXInit(PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       /* Services initialisation parameters */
+       RGX_SRVINIT_APPHINTS sApphints = {0};
+       IMG_UINT32 ui32FWConfigFlags, ui32FWConfigFlagsExt, ui32FwOsCfgFlags;
+       IMG_UINT32 ui32DeviceFlags;
+       IMG_UINT32 ui32AvailablePowUnitsMask, ui32AvailableRACMask;
+
+       PVRSRV_RGXDEV_INFO *psDevInfo = (PVRSRV_RGXDEV_INFO *)psDeviceNode->pvDevice;
+
+       /* Number of HWPerf Block-IDs (RGX_CNTBLK_ID) which are available */
+       IMG_UINT32 ui32NumHWPerfBlocks;
+
+       /* Size of the RGXFWIF_HWPERF_CTL_BLK structure - varies by BVNC */
+       IMG_UINT32 ui32HWPerfBlkSize;
+       RGX_LAYER_PARAMS sLayerParams;
+
+       PDUMPCOMMENT(psDeviceNode, "RGX Initialisation Part 1");
+
+       PDUMPCOMMENT(psDeviceNode, "Device Name: %s",
+                    psDeviceNode->psDevConfig->pszName);
+       PDUMPCOMMENT(psDeviceNode, "Device ID: %u (%d)",
+                    psDeviceNode->sDevId.ui32InternalID,
+                    psDeviceNode->sDevId.i32OsDeviceID);
+
+       if (psDeviceNode->psDevConfig->pszVersion)
+       {
+               PDUMPCOMMENT(psDeviceNode, "Device Version: %s",
+                            psDeviceNode->psDevConfig->pszVersion);
+       }
+
+       /* pdump info about the core */
+       PDUMPCOMMENT(psDeviceNode,
+                    "RGX Version Information (KM): %d.%d.%d.%d",
+                    psDevInfo->sDevFeatureCfg.ui32B,
+                    psDevInfo->sDevFeatureCfg.ui32V,
+                    psDevInfo->sDevFeatureCfg.ui32N,
+                    psDevInfo->sDevFeatureCfg.ui32C);
+
+       RGXInitMultiCoreInfo(psDeviceNode);
+
+#if defined(PDUMP)
+       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
+                                             &psDeviceNode->sDummyPage,
+                                             PVR_DUMMY_PAGE_INIT_VALUE,
+                                             DUMMY_PAGE,
+                                             IMG_TRUE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate dummy page.", __func__));
+               goto cleanup;
+       }
+       eError = DevmemIntAllocDefBackingPage(psDeviceNode,
+                                             &psDeviceNode->sDevZeroPage,
+                                             PVR_ZERO_PAGE_INIT_VALUE,
+                                             DEV_ZERO_PAGE,
+                                             IMG_TRUE);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate Zero page.", __func__));
+               goto cleanup;
+       }
+#endif
+
+       sLayerParams.psDevInfo = psDevInfo;
+
+#if defined(SUPPORT_TRUSTED_DEVICE)
+       eError = RGXValidateTDHeaps(psDeviceNode);
+       PVR_LOG_RETURN_IF_ERROR(eError, "RGXValidateTDHeaps");
+#endif
+
+#if defined(SUPPORT_AUTOVZ)
+       if (PVRSRV_VZ_MODE_IS(HOST))
+       {
+               /* The RGX_CR_MTS_DM0_INTERRUPT_ENABLE register is always set by the firmware during initialisation
+                * and it provides a good method of determining if the firmware has been booted previously */
+               psDeviceNode->bAutoVzFwIsUp = (OSReadHWReg32(psDevInfo->pvRegsBaseKM, RGX_CR_MTS_DM0_INTERRUPT_ENABLE) != 0);
+
+               PVR_LOG(("AutoVz startup check: firmware is %s;",
+                               (psDeviceNode->bAutoVzFwIsUp) ? "already running" : "powered down"));
+       }
+       else if (PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               /* Guest assumes the firmware is always available */
+               psDeviceNode->bAutoVzFwIsUp = IMG_TRUE;
+       }
+       else
+#endif
+       {
+               /* Firmware does not follow the AutoVz life-cycle */
+               psDeviceNode->bAutoVzFwIsUp = IMG_FALSE;
+       }
+
+       if (PVRSRV_VZ_MODE_IS(GUEST) || (psDeviceNode->bAutoVzFwIsUp))
+       {
+               /* set the device power state here as the regular power
+                * callbacks will not be executed on this driver */
+               psDevInfo->bRGXPowered = IMG_TRUE;
+       }
+
+       /* Set which HW Safety Events will be handled by the driver */
+       psDevInfo->ui32HostSafetyEventMask |= RGX_IS_FEATURE_SUPPORTED(psDevInfo, WATCHDOG_TIMER) ?
+                                                                                 RGX_CR_EVENT_STATUS_WDT_TIMEOUT_EN : 0;
+       psDevInfo->ui32HostSafetyEventMask |= (RGX_DEVICE_HAS_FEATURE_VALUE(&sLayerParams, ECC_RAMS)
+                                                                                  && (RGX_DEVICE_GET_FEATURE_VALUE(&sLayerParams, ECC_RAMS) > 0)) ?
+                                                                                 RGX_CR_EVENT_STATUS_FAULT_FW_EN : 0;
+
+#if defined(PDUMP)
+       PDUMPCOMMENTWITHFLAGS(psDeviceNode, PDUMP_FLAGS_CONTINUOUS,
+                             "Register defs revision: %d", RGX_CR_DEFS_KM_REVISION);
+#endif
+
+       ui32NumHWPerfBlocks = RGXHWPerfMaxDefinedBlks((void *)psDevInfo);
+
+       ui32HWPerfBlkSize = sizeof(RGXFWIF_HWPERF_CTL) +
+               (ui32NumHWPerfBlocks - 1) * sizeof(RGXFWIF_HWPERF_CTL_BLK);
+
+       /* Services initialisation parameters */
+       _ParseHTBAppHints(psDeviceNode);
+       GetApphints(psDevInfo, &sApphints);
+       InitDeviceFlags(&sApphints, &ui32DeviceFlags);
+
+#if defined(SUPPORT_GPUVIRT_VALIDATION)
+#if defined(EMULATOR)
+       if ((sApphints.bEnableTrustedDeviceAceConfig) &&
+               (RGX_IS_FEATURE_SUPPORTED(psDevInfo, AXI_ACE)))
+       {
+               SetTrustedDeviceAceEnabled();
+       }
+#endif
+#endif
+
+       eError = RGXInitCreateFWKernelMemoryContext(psDeviceNode);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create FW kernel memory context (%u)",
+                        __func__, eError));
+               goto cleanup;
+       }
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = InitFirmware(psDeviceNode, &sApphints);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: InitFirmware failed (%d)",
+                               __func__,
+                               eError));
+                       goto cleanup;
+               }
+       }
+
+       /*
+        * Setup Firmware initialisation data
+        */
+
+       GetFWConfigFlags(psDeviceNode, &sApphints, &ui32FWConfigFlags, &ui32FWConfigFlagsExt, &ui32FwOsCfgFlags);
+
+#if defined(SUPPORT_VALIDATION)
+       ui32AvailablePowUnitsMask = sApphints.ui32AvailablePowUnitsMask;
+       ui32AvailableRACMask = sApphints.ui32AvailableRACMask;
+#else
+       ui32AvailablePowUnitsMask = AVAIL_POW_UNITS_MASK_DEFAULT;
+       ui32AvailableRACMask = AVAIL_RAC_MASK_DEFAULT;
+#endif
+
+       eError = RGXInitFirmware(psDeviceNode,
+                                sApphints.bEnableSignatureChecks,
+                                sApphints.ui32SignatureChecksBufSize,
+                                sApphints.ui32HWPerfFWBufSize,
+                                (IMG_UINT64)sApphints.ui32HWPerfFilter0 |
+                                ((IMG_UINT64)sApphints.ui32HWPerfFilter1 << 32),
+                                ui32FWConfigFlags,
+                                sApphints.ui32LogType,
+                                GetFilterFlags(&sApphints),
+                                sApphints.ui32JonesDisableMask,
+                                sApphints.ui32HWRDebugDumpLimit,
+#if defined(SUPPORT_VALIDATION)
+                                sApphints.ui32RenderKillingCtl,
+                                sApphints.ui32CDMTDMKillingCtl,
+                                &sApphints.aui32TPUTrilinearFracMask[0],
+                                &sApphints.aui32USRMNumRegions[0],
+                                (IMG_PUINT64)&sApphints.aui64UVBRMNumRegions[0],
+#else
+                                0, 0,
+                                NULL, NULL, NULL,
+#endif
+                                ui32HWPerfBlkSize,
+                                sApphints.eRGXRDPowerIslandConf,
+                                sApphints.eFirmwarePerf,
+                                sApphints.ui32KCCBSizeLog2,
+                                ui32FWConfigFlagsExt,
+                                ui32AvailablePowUnitsMask,
+                                                        ui32AvailableRACMask,
+                                ui32FwOsCfgFlags);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRVRGXInitFirmware failed (%d)",
+                       __func__,
+                       eError));
+               goto cleanup;
+       }
+
+       if (!PVRSRV_VZ_MODE_IS(GUEST))
+       {
+               eError = InitialiseAllCounters(psDeviceNode);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: InitialiseAllCounters failed (%d)",
+                               __func__,
+                               eError));
+                       goto cleanup;
+               }
+       }
+
+       /*
+        * Perform second stage of RGX initialisation
+        */
+       eError = RGXInitDevPart2(psDeviceNode,
+                                ui32DeviceFlags,
+                                sApphints.ui32HWPerfHostFilter,
+                                sApphints.eRGXActivePMConf,
+                                ui32AvailablePowUnitsMask,
+                                                        ui32AvailableRACMask);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: PVRSRVRGXInitDevPart2KM failed (%d)",
+                       __func__,
+                       eError));
+               goto cleanup;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       PVRSRVAppHintDumpState(psDeviceNode);
+#endif
+
+       eError = PVRSRV_OK;
+
+cleanup:
+       return eError;
+}
+
+/******************************************************************************
+ End of file (rgxsrvinit.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxstartstop.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxstartstop.c
new file mode 100644 (file)
index 0000000..30b4a89
--- /dev/null
@@ -0,0 +1,871 @@
+/*************************************************************************/ /*!
+@File
+@Title          Device specific start/stop routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific start/stop routines
+@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.
+*/ /**************************************************************************/
+
+/* The routines implemented here are built on top of an abstraction layer to
+ * hide DDK/OS-specific details in case they are used outside of the DDK
+ * (e.g. when trusted device is enabled).
+ * Any new dependency should be added to rgxlayer.h.
+ * Any new code should be built on top of the existing abstraction layer,
+ * which should be extended when necessary. */
+#include "rgxstartstop.h"
+#include "rgxfwutils.h"
+
+/*
+ * Specific fields for RGX_CR_IDLE must not be polled in pdumps
+ * (technical reasons)
+ */
+#define CR_IDLE_UNSELECTED_MASK ((~RGX_CR_SLC_IDLE_ACE_CONVERTERS_CLRMSK) | \
+                                                                (~RGX_CR_SLC_IDLE_OWDB_CLRMSK) |               \
+                                                                (RGX_CR_SLC_IDLE_FBCDC_ARB_EN))
+
+static PVRSRV_ERROR RGXWriteMetaCoreRegThoughSP(const void *hPrivate,
+                                                IMG_UINT32 ui32CoreReg,
+                                                IMG_UINT32 ui32Value)
+{
+       IMG_UINT32 i = 0;
+
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXDT_OFFSET, ui32Value);
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, ui32CoreReg & ~META_CR_TXUXXRXRQ_RDnWR_BIT);
+
+       do
+       {
+               RGXReadMetaRegThroughSP(hPrivate, META_CR_TXUXXRXRQ_OFFSET, &ui32Value);
+       } while (((ui32Value & META_CR_TXUXXRXRQ_DREADY_BIT) != META_CR_TXUXXRXRQ_DREADY_BIT) && (i++ < 1000));
+
+       if (i == 1000)
+       {
+               RGXCommentLog(hPrivate, "RGXWriteMetaCoreRegThoughSP: Timeout");
+               return PVRSRV_ERROR_TIMEOUT;
+       }
+
+       return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR RGXStartFirmware(const void *hPrivate)
+{
+       PVRSRV_ERROR eError;
+
+       /* Give privilege to debug and slave port */
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_SYSC_JTAG_THREAD, META_CR_SYSC_JTAG_THREAD_PRIV_EN);
+
+       /* Point Meta to the bootloader address, global (uncached) range */
+       eError = RGXWriteMetaCoreRegThoughSP(hPrivate,
+                                            PC_ACCESS(0),
+                                            RGXFW_BOOTLDR_META_ADDR | META_MEM_GLOBAL_RANGE_BIT);
+
+       if (eError != PVRSRV_OK)
+       {
+               RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Slave boot Start failed!");
+               return eError;
+       }
+
+       /* Enable minim encoding */
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXPRIVEXT, META_CR_TXPRIVEXT_MINIM_EN);
+
+       /* Enable Meta thread */
+       RGXWriteMetaRegThroughSP(hPrivate, META_CR_T0ENABLE_OFFSET, META_CR_TXENABLE_ENABLE_BIT);
+
+       return PVRSRV_OK;
+}
+
+/*!
+*******************************************************************************
+
+ @Function      RGXInitMetaProcWrapper
+
+ @Description   Configures the hardware wrapper of the META processor
+
+ @Input         hPrivate  : Implementation specific data
+
+ @Return        void
+
+******************************************************************************/
+static void RGXInitMetaProcWrapper(const void *hPrivate)
+{
+       IMG_UINT64 ui64GartenConfig;
+
+       /* Garten IDLE bit controlled by META */
+       ui64GartenConfig = RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META;
+
+       RGXCommentLog(hPrivate, "RGXStart: Configure META wrapper");
+       RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, ui64GartenConfig);
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      RGXInitRiscvProcWrapper
+
+ @Description   Configures the hardware wrapper of the RISCV processor
+
+ @Input         hPrivate  : Implementation specific data
+
+ @Return        void
+
+******************************************************************************/
+static void RGXInitRiscvProcWrapper(const void *hPrivate)
+{
+       IMG_DEV_VIRTADDR sTmp;
+
+       RGXCommentLog(hPrivate, "RGXStart: Configure RISCV wrapper");
+
+       RGXCommentLog(hPrivate, "RGXStart: Write boot code remap");
+       RGXAcquireBootCodeAddr(hPrivate, &sTmp);
+       RGXWriteReg64(hPrivate,
+                     RGXRISCVFW_BOOTLDR_CODE_REMAP,
+                     sTmp.uiAddr |
+                     (IMG_UINT64) (RGX_FIRMWARE_RAW_HEAP_SIZE >> FWCORE_ADDR_REMAP_CONFIG0_SIZE_ALIGNSHIFT)
+                       << RGX_CR_FWCORE_ADDR_REMAP_CONFIG0_SIZE_SHIFT |
+                     (IMG_UINT64) MMU_CONTEXT_MAPPING_FWPRIV << FWCORE_ADDR_REMAP_CONFIG0_MMU_CONTEXT_SHIFT |
+                     RGX_CR_FWCORE_ADDR_REMAP_CONFIG0_FETCH_EN_EN);
+
+       RGXCommentLog(hPrivate, "RGXStart: Write boot data remap");
+       RGXAcquireBootDataAddr(hPrivate, &sTmp);
+       RGXWriteReg64(hPrivate,
+                     RGXRISCVFW_BOOTLDR_DATA_REMAP,
+                     sTmp.uiAddr |
+                     (IMG_UINT64) (RGX_FIRMWARE_RAW_HEAP_SIZE >> FWCORE_ADDR_REMAP_CONFIG0_SIZE_ALIGNSHIFT)
+                       << RGX_CR_FWCORE_ADDR_REMAP_CONFIG0_SIZE_SHIFT |
+                     (IMG_UINT64) MMU_CONTEXT_MAPPING_FWPRIV << FWCORE_ADDR_REMAP_CONFIG0_MMU_CONTEXT_SHIFT |
+                     RGX_CR_FWCORE_ADDR_REMAP_CONFIG0_LOAD_STORE_EN_EN);
+
+       /* Garten IDLE bit controlled by RISCV */
+       RGXCommentLog(hPrivate, "RGXStart: Set GARTEN_IDLE type to RISCV");
+       RGXWriteReg64(hPrivate, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG, RGX_CR_MTS_GARTEN_WRAPPER_CONFIG_IDLE_CTRL_META);
+}
+
+
+/*!
+*******************************************************************************
+
+ @Function      RGXInitBIF
+
+ @Description   Initialise RGX BIF
+
+ @Input         hPrivate : Implementation specific data
+
+ @Return        void
+
+******************************************************************************/
+static void RGXInitBIF(const void *hPrivate)
+{
+       IMG_DEV_PHYADDR sPCAddr;
+       IMG_UINT32 uiPCAddr;
+
+       /*
+        * Acquire the address of the Kernel Page Catalogue.
+        */
+       RGXAcquireKernelMMUPC(hPrivate, &sPCAddr);
+       uiPCAddr = (((sPCAddr.uiAddr >> RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT)
+                    << RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT)
+                   & ~RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_CLRMSK);
+
+       /*
+        * Write the kernel catalogue base.
+        */
+       RGXCommentLog(hPrivate, "RGX firmware MMU Page Catalogue");
+
+
+       /* Set the mapping context */
+       RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, MMU_CONTEXT_MAPPING_FWPRIV);
+       (void)RGXReadReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT); /* Fence write */
+
+       /* Write the cat-base address */
+       RGXWriteKernelMMUPC32(hPrivate,
+                             RGX_CR_MMU_CBASE_MAPPING,
+                             RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
+                             RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
+                             uiPCAddr);
+
+#if (MMU_CONTEXT_MAPPING_FWIF != MMU_CONTEXT_MAPPING_FWPRIV)
+       /* Set-up different MMU ID mapping to the same PC used above */
+       RGXWriteReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT, MMU_CONTEXT_MAPPING_FWIF);
+       (void)RGXReadReg32(hPrivate, RGX_CR_MMU_CBASE_MAPPING_CONTEXT); /* Fence write */
+
+       RGXWriteKernelMMUPC32(hPrivate,
+                             RGX_CR_MMU_CBASE_MAPPING,
+                             RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_ALIGNSHIFT,
+                             RGX_CR_MMU_CBASE_MAPPING_BASE_ADDR_SHIFT,
+                             uiPCAddr);
+#endif
+}
+
+
+/**************************************************************************/ /*!
+@Function       RGXInitMMURangeRegisters
+@Description    Initialises MMU range registers for Non4K pages.
+@Input          hPrivate           Implementation specific data
+@Return         void
+ */ /**************************************************************************/
+static void RGXInitMMURangeRegisters(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psParams->psDevInfo;
+       IMG_UINT32 ui32RegAddr = RGX_CR_MMU_PAGE_SIZE_RANGE_ONE;
+       IMG_UINT32 i;
+
+       for (i = 0; i < ARRAY_SIZE(psDevInfo->aui64MMUPageSizeRangeValue); ++i, ui32RegAddr += sizeof(IMG_UINT64))
+       {
+               RGXWriteReg64(hPrivate, ui32RegAddr, psDevInfo->aui64MMUPageSizeRangeValue[i]);
+       }
+}
+
+
+/**************************************************************************/ /*!
+@Function       RGXInitAXIACE
+@Description    Initialises AXI ACE registers
+@Input          hPrivate           Implementation specific data
+@Return         void
+ */ /**************************************************************************/
+static void RGXInitAXIACE(const void *hPrivate)
+{
+       IMG_UINT64 ui64RegVal;
+
+       /**
+        * The below configuration is only applicable for RGX core's supporting
+        * ACE/ACE-lite protocol and connected to ACE coherent interconnect.
+        */
+
+       /**
+        * Configure AxDomain and AxCache for MMU transactions.
+        * AxDomain set to non sharable (0x0).
+        */
+       ui64RegVal = RGX_CR_ACE_CTRL_MMU_AWCACHE_WRITE_BACK_WRITE_ALLOCATE |
+                                RGX_CR_ACE_CTRL_MMU_ARCACHE_WRITE_BACK_READ_ALLOCATE;
+
+       /**
+        * Configure AxCache for PM/MMU transactions.
+        * Set to same value (i.e WBRWALLOC caching, rgxmmunit.c:RGXDerivePTEProt8)
+        * as non-coherent PTEs
+        */
+       ui64RegVal |= (IMG_UINT64_C(0xF)) << RGX_CR_ACE_CTRL_PM_MMU_AXCACHE_SHIFT;
+
+       /**
+        * Configure AxDomain for non MMU transactions.
+        */
+       ui64RegVal |= (IMG_UINT64)(RGX_CR_ACE_CTRL_COH_DOMAIN_OUTER_SHAREABLE |
+                                                          RGX_CR_ACE_CTRL_NON_COH_DOMAIN_NON_SHAREABLE);
+
+       RGXCommentLog(hPrivate, "Init AXI-ACE interface");
+       RGXWriteReg64(hPrivate, RGX_CR_ACE_CTRL, ui64RegVal);
+}
+
+static void RGXMercerSoftResetSet(const void *hPrivate, IMG_UINT64 ui32MercerFlags)
+{
+       RGXWriteReg64(hPrivate, RGX_CR_MERCER_SOFT_RESET, ui32MercerFlags & RGX_CR_MERCER_SOFT_RESET_MASKFULL);
+
+       /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+       (void) RGXReadReg64(hPrivate, RGX_CR_MERCER_SOFT_RESET);
+}
+
+static void RGXSPUSoftResetAssert(const void *hPrivate)
+{
+       /* Assert Mercer0 */
+       RGXMercerSoftResetSet(hPrivate, RGX_CR_MERCER0_SOFT_RESET_SPU_EN);
+       /* Assert Mercer1 */
+       RGXMercerSoftResetSet(hPrivate, RGX_CR_MERCER0_SOFT_RESET_SPU_EN | RGX_CR_MERCER1_SOFT_RESET_SPU_EN);
+       /* Assert Mercer2 */
+       RGXMercerSoftResetSet(hPrivate, RGX_CR_MERCER0_SOFT_RESET_SPU_EN | RGX_CR_MERCER1_SOFT_RESET_SPU_EN | RGX_CR_MERCER2_SOFT_RESET_SPU_EN);
+
+       RGXWriteReg32(hPrivate, RGX_CR_SWIFT_SOFT_RESET, RGX_CR_SWIFT_SOFT_RESET_MASKFULL);
+       /* Fence the previous write */
+       (void) RGXReadReg32(hPrivate, RGX_CR_SWIFT_SOFT_RESET);
+
+       RGXWriteReg32(hPrivate, RGX_CR_TEXAS_SOFT_RESET, RGX_CR_TEXAS_SOFT_RESET_MASKFULL);
+       /* Fence the previous write */
+       (void) RGXReadReg32(hPrivate, RGX_CR_TEXAS_SOFT_RESET);
+}
+
+static void RGXSPUSoftResetDeAssert(const void *hPrivate)
+{
+       RGXWriteReg32(hPrivate, RGX_CR_TEXAS_SOFT_RESET, 0);
+       /* Fence the previous write */
+       (void) RGXReadReg32(hPrivate, RGX_CR_TEXAS_SOFT_RESET);
+
+
+       RGXWriteReg32(hPrivate, RGX_CR_SWIFT_SOFT_RESET, 0);
+       /* Fence the previous write */
+       (void) RGXReadReg32(hPrivate, RGX_CR_SWIFT_SOFT_RESET);
+
+       /* Deassert Mercer2 */
+       RGXMercerSoftResetSet(hPrivate, RGX_CR_MERCER0_SOFT_RESET_SPU_EN | RGX_CR_MERCER1_SOFT_RESET_SPU_EN);
+       /* Deassert Mercer1 */
+       RGXMercerSoftResetSet(hPrivate, RGX_CR_MERCER0_SOFT_RESET_SPU_EN);
+       /* Deassert Mercer0 */
+       RGXMercerSoftResetSet(hPrivate, 0);
+}
+
+static void RGXResetSequence(const void *hPrivate, const IMG_CHAR *pcRGXFW_PROCESSOR)
+{
+       /* Set RGX in soft-reset */
+       RGXCommentLog(hPrivate, "RGXStart: soft reset assert step 1");
+       RGXSPUSoftResetAssert(hPrivate);
+
+       RGXCommentLog(hPrivate, "RGXStart: soft reset assert step 2");
+       RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_SOFT_RESET_JONES_ALL);
+
+       /* Read soft-reset to fence previous write in order to clear the SOCIF pipeline */
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+
+       RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_SOFT_RESET_JONES_ALL | RGX_SOFT_RESET_EXTRA);
+
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+
+       /* Take everything out of reset but the FW processor */
+       RGXCommentLog(hPrivate, "RGXStart: soft reset de-assert step 1 excluding %s", pcRGXFW_PROCESSOR);
+       RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_SOFT_RESET_EXTRA | RGX_CR_SOFT_RESET_GARTEN_EN);
+
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+
+       RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+
+       RGXCommentLog(hPrivate, "RGXStart: soft reset de-assert step 2 excluding %s", pcRGXFW_PROCESSOR);
+       RGXSPUSoftResetDeAssert(hPrivate);
+
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+}
+
+static void DeassertMetaReset(const void *hPrivate)
+{
+       /* Need to wait for at least 16 cycles before taking the FW processor out of reset ... */
+       RGXWaitCycles(hPrivate, 32, 3);
+
+       RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, 0x0);
+       (void) RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+
+       /* ... and afterwards */
+       RGXWaitCycles(hPrivate, 32, 3);
+}
+
+static PVRSRV_ERROR InitJonesECCRAM(const void *hPrivate)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32Value;
+       IMG_BOOL bMetaFW = RGX_DEVICE_HAS_FEATURE_VALUE(hPrivate, META);
+       IMG_UINT32 ui32Mask;
+
+       if (RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, ECC_RAMS) == 0)
+       {
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       if (bMetaFW)
+       {
+               /* META must be taken out of reset (without booting) during Coremem initialization. */
+               RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, 0);
+               DeassertMetaReset(hPrivate);
+       }
+
+       /* Clocks must be set to "on" during RAMs initialization. */
+       RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL0, RGX_CR_CLK_CTRL0_ALL_ON);
+       RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL1, RGX_CR_CLK_CTRL1_ALL_ON);
+
+       if (bMetaFW)
+       {
+               RGXWriteMetaRegThroughSP(hPrivate, META_CR_SYSC_JTAG_THREAD, META_CR_SYSC_JTAG_THREAD_PRIV_EN);
+               RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXCLKCTRL, META_CR_TXCLKCTRL_ALL_ON);
+               RGXReadMetaRegThroughSP(hPrivate, META_CR_TXCLKCTRL, &ui32Value);
+       }
+
+       ui32Mask = bMetaFW ?
+               RGX_CR_JONES_RAM_INIT_KICK_MASKFULL
+               : RGX_CR_JONES_RAM_INIT_KICK_MASKFULL & ~RGX_CR_JONES_RAM_INIT_KICK_GARTEN_EN;
+       RGXWriteReg64(hPrivate, RGX_CR_JONES_RAM_INIT_KICK, ui32Mask);
+       eError = RGXPollReg64(hPrivate, RGX_CR_JONES_RAM_STATUS, ui32Mask, ui32Mask);
+
+       if (bMetaFW)
+       {
+               RGXWriteMetaRegThroughSP(hPrivate, META_CR_TXCLKCTRL, META_CR_TXCLKCTRL_ALL_AUTO);
+               RGXReadMetaRegThroughSP(hPrivate, META_CR_TXCLKCTRL, &ui32Value);
+       }
+
+       RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL0, RGX_CR_CLK_CTRL0_ALL_AUTO);
+       RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL1, RGX_CR_CLK_CTRL1_ALL_AUTO);
+
+       if (bMetaFW)
+       {
+               RGXWriteReg64(hPrivate, RGX_CR_SOFT_RESET, RGX_CR_SOFT_RESET_GARTEN_EN);
+               RGXReadReg64(hPrivate, RGX_CR_SOFT_RESET);
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXStart(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psParams->psDevInfo;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_BOOL bDoFWSlaveBoot = IMG_FALSE;
+       IMG_CHAR *pcRGXFW_PROCESSOR;
+       IMG_BOOL bMetaFW = IMG_FALSE;
+
+       if (RGX_DEVICE_HAS_FEATURE(hPrivate, RISCV_FW_PROCESSOR))
+       {
+               pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_RISCV;
+               bMetaFW = IMG_FALSE;
+               bDoFWSlaveBoot = IMG_FALSE;
+       }
+       else
+       {
+               pcRGXFW_PROCESSOR = RGXFW_PROCESSOR_META;
+               bMetaFW = IMG_TRUE;
+               bDoFWSlaveBoot = RGXDoFWSlaveBoot(hPrivate);
+       }
+
+       /* Disable the default sys_bus_secure protection to perform minimal setup */
+       RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, 0);
+       (void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE);
+
+       /* Only bypass HMMU if the module is present */
+       if (RGXDeviceHasFeature(hPrivate, RGX_FEATURE_HYPERVISOR_MMU_BIT_MASK))
+       {
+               if (PVRSRV_VZ_MODE_IS(NATIVE))
+               {
+                       /* Always set HMMU in bypass mode */
+                       RGXWriteReg32(hPrivate, RGX_CR_HMMU_BYPASS, RGX_CR_HMMU_BYPASS_MASKFULL);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_HMMU_BYPASS);
+               }
+#if defined(PVRSRV_VZ_BYPASS_HMMU)
+               if (PVRSRV_VZ_MODE_IS(HOST))
+               {
+                       /* Also set HMMU in bypass mode */
+                       RGXWriteReg32(hPrivate, RGX_CR_HMMU_BYPASS, RGX_CR_HMMU_BYPASS_MASKFULL);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_HMMU_BYPASS);
+               }
+#endif
+       }
+
+#if defined(SUPPORT_VALIDATION)
+#if !defined(RGX_CR_FIRMWARE_PROCESSOR_LS)
+#define RGX_CR_FIRMWARE_PROCESSOR_LS                      (0x01A0U)
+#define RGX_CR_FIRMWARE_PROCESSOR_LS_ENABLE_EN            (0x00000001U)
+#endif
+       {
+               if (psDevInfo->ui32ValidationFlags & RGX_VAL_LS_EN)
+               {
+                       /* Set the dual LS mode */
+                       RGXWriteReg32(hPrivate, RGX_CR_FIRMWARE_PROCESSOR_LS, RGX_CR_FIRMWARE_PROCESSOR_LS_ENABLE_EN);
+                       (void) RGXReadReg32(hPrivate, RGX_CR_FIRMWARE_PROCESSOR_LS);
+               }
+       }
+#endif
+
+       /*!
+        * Start series8 FW init sequence
+        */
+       RGXResetSequence(hPrivate, pcRGXFW_PROCESSOR);
+
+       if (RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, ECC_RAMS) > 0)
+       {
+               RGXCommentLog(hPrivate, "RGXStart: Init Jones ECC RAM");
+               eError = InitJonesECCRAM(hPrivate);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+       }
+
+       if (RGX_DEVICE_HAS_BRN(hPrivate, BRN_66927))
+       {
+               IMG_UINT64 ui64ClockCtrl;
+
+               ui64ClockCtrl = RGXReadReg64(hPrivate, RGX_CR_CLK_CTRL0);
+               CLK_CTRL_FORCE_ON(ui64ClockCtrl, CLK_CTRL0_MCU_L0);
+               CLK_CTRL_FORCE_ON(ui64ClockCtrl, CLK_CTRL0_PM);
+               CLK_CTRL_FORCE_ON(ui64ClockCtrl, CLK_CTRL0_FBDC);
+               RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL0, ui64ClockCtrl);
+
+               ui64ClockCtrl = RGXReadReg64(hPrivate, RGX_CR_CLK_CTRL1);
+               CLK_CTRL_FORCE_ON(ui64ClockCtrl, CLK_CTRL1_PIXEL);
+               CLK_CTRL_FORCE_ON(ui64ClockCtrl, CLK_CTRL1_GEO_VERTEX);
+               RGXWriteReg64(hPrivate, RGX_CR_CLK_CTRL1, ui64ClockCtrl);
+       }
+
+       if (bMetaFW)
+       {
+               if (bDoFWSlaveBoot)
+               {
+                       /* Configure META to Slave boot */
+                       RGXCommentLog(hPrivate, "RGXStart: META Slave boot");
+                       RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, 0);
+               }
+               else
+               {
+                       /* Configure META to Master boot */
+                       RGXCommentLog(hPrivate, "RGXStart: META Master boot");
+                       RGXWriteReg32(hPrivate, RGX_CR_META_BOOT, RGX_CR_META_BOOT_MODE_EN);
+               }
+       }
+
+       /*
+        * Initialise Firmware wrapper
+        */
+       if (bMetaFW)
+       {
+               RGXInitMetaProcWrapper(hPrivate);
+       }
+       else
+       {
+               RGXInitRiscvProcWrapper(hPrivate);
+       }
+
+       if (RGX_GET_FEATURE_VALUE(psDevInfo, MMU_VERSION) >= 4)
+       {
+               // initialise the MMU range based config registers for Non4K pages.
+               RGXInitMMURangeRegisters(hPrivate);
+       }
+
+       RGXInitAXIACE(hPrivate);
+       /*
+        * Initialise BIF.
+        */
+       RGXInitBIF(hPrivate);
+
+       RGXCommentLog(hPrivate, "RGXStart: Take %s out of reset", pcRGXFW_PROCESSOR);
+       DeassertMetaReset(hPrivate);
+
+       if (bMetaFW)
+       {
+               if (bDoFWSlaveBoot)
+               {
+                       eError = RGXFabricCoherencyTest(hPrivate);
+                       if (eError != PVRSRV_OK) return eError;
+
+                       RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Slave boot Start");
+                       eError = RGXStartFirmware(hPrivate);
+                       if (eError != PVRSRV_OK) return eError;
+               }
+               else
+               {
+                       RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Master boot Start");
+               }
+       }
+       else
+       {
+               /* Bring Debug Module out of reset */
+               RGXWriteReg32(hPrivate, RGX_CR_FWCORE_DMI_DMCONTROL, RGX_CR_FWCORE_DMI_DMCONTROL_DMACTIVE_EN);
+
+               /* Boot the FW */
+               RGXCommentLog(hPrivate, "RGXStart: RGX Firmware Master boot Start");
+               RGXWriteReg32(hPrivate, RGX_CR_FWCORE_BOOT, 1);
+               RGXWaitCycles(hPrivate, 32, 3);
+       }
+
+#if defined(SUPPORT_TRUSTED_DEVICE) && !defined(SUPPORT_SECURITY_VALIDATION)
+       RGXCommentLog(hPrivate, "RGXStart: Enable sys_bus_secure");
+       RGXWriteReg32(hPrivate, RGX_CR_SYS_BUS_SECURE, RGX_CR_SYS_BUS_SECURE_ENABLE_EN);
+       (void) RGXReadReg32(hPrivate, RGX_CR_SYS_BUS_SECURE); /* Fence write */
+#endif
+
+       /*!
+        * End series8 FW init sequence
+        */
+
+       return eError;
+}
+
+PVRSRV_ERROR RGXStop(const void *hPrivate)
+{
+       RGX_LAYER_PARAMS *psParams = (RGX_LAYER_PARAMS*)hPrivate;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psParams->psDevInfo;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_BOOL bMetaFW = RGX_DEVICE_HAS_FEATURE_VALUE(hPrivate, META);
+       IMG_UINT32 ui32JonesIdleMask = RGX_CR_JONES_IDLE_MASKFULL^RGX_CR_JONES_IDLE_AXI2IMG_EN;
+
+       RGXDeviceAckIrq(hPrivate);
+
+#if defined(SUPPORT_VALIDATION) && !defined(TC_MEMORY_CONFIG)
+#if !defined(RGX_CR_POWER_EVENT)
+#define RGX_CR_POWER_EVENT                                (0x0038U)
+#define RGX_CR_POWER_EVENT_GPU_MASK_CLRMSK                (IMG_UINT64_C(0x00FFFFFFFFFFFFFF))
+#define RGX_CR_POWER_EVENT_GPU_ID_CLRMSK                  (IMG_UINT64_C(0xFFFFFFFFFFFFFF1F))
+#define RGX_CR_POWER_EVENT_DOMAIN_SPU0_SHIFT              (9U)
+#define RGX_CR_POWER_EVENT_DOMAIN_CLUSTER0_SHIFT          (8U)
+#define RGX_CR_POWER_EVENT_DOMAIN_CLUSTER_CLUSTER0_SHIFT  (32U)
+#define RGX_CR_POWER_EVENT_TYPE_SHIFT                     (0U)
+#define RGX_CR_POWER_EVENT_TYPE_POWER_DOWN                (0x00000000U)
+#define RGX_CR_POWER_EVENT_REQ_EN                         (0x00000002U)
+#endif
+
+       /* Power off any enabled SPUs */
+       if (BITMASK_HAS(psDevInfo->ui32DeviceFlags, RGXKM_DEVICE_STATE_ENABLE_SPU_UNITS_POWER_MASK_CHANGE_EN))
+       {
+               if (RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, POWER_ISLAND_VERSION) == 3)
+               {
+                       IMG_UINT64 ui64PowUnitOffMask;
+                       IMG_UINT64 ui64RegVal;
+
+                       ui64PowUnitOffMask = (1 << RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, NUM_CLUSTERS)) -1;
+                       ui64RegVal = (~RGX_CR_POWER_EVENT_GPU_MASK_CLRMSK) | // GPU_MASK specifies all cores
+                                    (~RGX_CR_POWER_EVENT_GPU_ID_CLRMSK) | // GPU_ID all set means use the GPU_MASK
+                                    (ui64PowUnitOffMask << RGX_CR_POWER_EVENT_DOMAIN_CLUSTER_CLUSTER0_SHIFT) |
+                                    RGX_CR_POWER_EVENT_TYPE_POWER_DOWN;
+
+                       RGXWriteReg64(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui64RegVal);
+
+                       RGXWriteReg64(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui64RegVal | RGX_CR_POWER_EVENT_REQ_EN);
+               }
+               else if (RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, POWER_ISLAND_VERSION) == 2)
+               {
+                       IMG_UINT64 ui64PowUnitOffMask;
+                       IMG_UINT64 ui64RegVal;
+
+                       ui64PowUnitOffMask = (1 << RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, NUM_CLUSTERS)) -1;
+                       ui64RegVal = (~RGX_CR_POWER_EVENT_GPU_MASK_CLRMSK) | // GPU_MASK specifies all cores
+                                    (~RGX_CR_POWER_EVENT_GPU_ID_CLRMSK) | // GPU_ID all set means use the GPU_MASK
+                                    (ui64PowUnitOffMask << RGX_CR_POWER_EVENT_DOMAIN_CLUSTER0_SHIFT) |
+                                    RGX_CR_POWER_EVENT_TYPE_POWER_DOWN;
+
+                       RGXWriteReg64(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui64RegVal);
+
+                       RGXWriteReg64(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui64RegVal | RGX_CR_POWER_EVENT_REQ_EN);
+               }
+               else
+               {
+                       IMG_UINT32 ui32PowUnitOffMask;
+                       IMG_UINT32 ui32RegVal;
+
+                       ui32PowUnitOffMask = (1 << RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, NUM_SPU)) -1;
+                       ui32RegVal = (ui32PowUnitOffMask << RGX_CR_POWER_EVENT_DOMAIN_SPU0_SHIFT) |
+                                    RGX_CR_POWER_EVENT_TYPE_POWER_DOWN;
+
+                       RGXWriteReg32(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui32RegVal);
+
+                       RGXWriteReg32(hPrivate,
+                                     RGX_CR_POWER_EVENT,
+                                     ui32RegVal | RGX_CR_POWER_EVENT_REQ_EN);
+               }
+
+               /* Poll on complete */
+               eError = RGXPollReg32(hPrivate,
+                                     RGX_CR_EVENT_STATUS,
+                                     RGX_CR_EVENT_STATUS_POWER_COMPLETE_EN,
+                                     RGX_CR_EVENT_STATUS_POWER_COMPLETE_EN);
+               if (eError != PVRSRV_OK) return eError;
+
+               /* Update the SPU_ENABLE mask */
+               if (RGX_DEVICE_GET_FEATURE_VALUE(hPrivate, POWER_ISLAND_VERSION) == 1)
+               {
+                       RGXWriteReg32(hPrivate, RGX_CR_SPU_ENABLE, 0);
+               }
+               RGXWriteReg32(hPrivate, 0xF020, 0);
+       }
+#endif
+
+       /* Wait for Sidekick/Jones to signal IDLE except for the Garten Wrapper */
+       if (!RGX_IS_FEATURE_VALUE_SUPPORTED(psDevInfo, RAY_TRACING_ARCH) ||
+           RGX_GET_FEATURE_VALUE(psDevInfo, RAY_TRACING_ARCH) < 2)
+       {
+               ui32JonesIdleMask ^= (RGX_CR_JONES_IDLE_ASC_EN|RGX_CR_JONES_IDLE_RCE_EN);
+       }
+
+       eError = RGXPollReg32(hPrivate,
+                             RGX_CR_JONES_IDLE,
+                             ui32JonesIdleMask^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN),
+                             ui32JonesIdleMask^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN));
+
+       if (eError != PVRSRV_OK) return eError;
+
+
+       /* Wait for SLC to signal IDLE */
+       eError = RGXPollReg32(hPrivate,
+                             RGX_CR_SLC_IDLE,
+                             RGX_CR_SLC_IDLE_MASKFULL^(CR_IDLE_UNSELECTED_MASK),
+                             RGX_CR_SLC_IDLE_MASKFULL^(CR_IDLE_UNSELECTED_MASK));
+       if (eError != PVRSRV_OK) return eError;
+
+
+       /* Unset MTS DM association with threads */
+       RGXWriteReg32(hPrivate,
+                     RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC,
+                     RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK
+                     & RGX_CR_MTS_INTCTX_THREAD0_DM_ASSOC_MASKFULL);
+       RGXWriteReg32(hPrivate,
+                     RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC,
+                     RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_DM_ASSOC_CLRMSK
+                     & RGX_CR_MTS_BGCTX_THREAD0_DM_ASSOC_MASKFULL);
+       RGXWriteReg32(hPrivate,
+                     RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC,
+                     RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
+                     & RGX_CR_MTS_INTCTX_THREAD1_DM_ASSOC_MASKFULL);
+       RGXWriteReg32(hPrivate,
+                     RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC,
+                     RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_DM_ASSOC_CLRMSK
+                     & RGX_CR_MTS_BGCTX_THREAD1_DM_ASSOC_MASKFULL);
+
+
+#if defined(PDUMP)
+       if (bMetaFW)
+       {
+               /* Disabling threads is only required for pdumps to stop the fw gracefully */
+
+               /* Disable thread 0 */
+               eError = RGXWriteMetaRegThroughSP(hPrivate,
+                                                 META_CR_T0ENABLE_OFFSET,
+                                                 ~META_CR_TXENABLE_ENABLE_BIT);
+               if (eError != PVRSRV_OK) return eError;
+
+               /* Disable thread 1 */
+               eError = RGXWriteMetaRegThroughSP(hPrivate,
+                                                 META_CR_T1ENABLE_OFFSET,
+                                                 ~META_CR_TXENABLE_ENABLE_BIT);
+               if (eError != PVRSRV_OK) return eError;
+
+               /* Wait for the Slave Port to finish all the transactions */
+               if (RGX_IS_FEATURE_SUPPORTED(psDevInfo, META_REGISTER_UNPACKED_ACCESSES))
+               {
+                       /* Clear down any irq raised by META (done after disabling the FW
+                        * threads to avoid a race condition).
+                        * This is only really needed for PDumps but we do it anyway driver-live.
+                        */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS__META_REGISTER_UNPACKED_ACCESSES, 0x0);
+                       (void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS__META_REGISTER_UNPACKED_ACCESSES); /* Fence write */
+
+                       eError = RGXPollReg32(hPrivate,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                                 | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN,
+                                                                 RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__READY_EN
+                                                                 | RGX_CR_META_SP_MSLVCTRL1__META_REGISTER_UNPACKED_ACCESSES__GBLPORT_IDLE_EN);
+               }
+               else
+               {
+                       /* Clear down any irq raised by META (done after disabling the FW
+                        * threads to avoid a race condition).
+                        * This is only really needed for PDumps but we do it anyway driver-live.
+                        */
+                       RGXWriteReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS, 0x0);
+                       (void)RGXReadReg32(hPrivate, RGX_CR_META_SP_MSLVIRQSTATUS); /* Fence write */
+
+                       eError = RGXPollReg32(hPrivate,
+                                                                 RGX_CR_META_SP_MSLVCTRL1,
+                                                                 RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN,
+                                                                 RGX_CR_META_SP_MSLVCTRL1_READY_EN | RGX_CR_META_SP_MSLVCTRL1_GBLPORT_IDLE_EN);
+               }
+               if (eError != PVRSRV_OK) return eError;
+       }
+#endif
+
+
+       eError = RGXPollReg64(hPrivate,
+                             RGX_CR_SLC_STATUS1,
+                             0,
+                             (~RGX_CR_SLC_STATUS1_BUS0_OUTSTANDING_READS_CLRMSK |
+                              ~RGX_CR_SLC_STATUS1_BUS1_OUTSTANDING_READS_CLRMSK |
+                              ~RGX_CR_SLC_STATUS1_BUS0_OUTSTANDING_WRITES_CLRMSK |
+                              ~RGX_CR_SLC_STATUS1_BUS1_OUTSTANDING_WRITES_CLRMSK));
+       if (eError != PVRSRV_OK) return eError;
+
+       eError = RGXPollReg64(hPrivate,
+                             RGX_CR_SLC_STATUS2,
+                             0,
+                             (~RGX_CR_SLC_STATUS2_BUS2_OUTSTANDING_READS_CLRMSK |
+                              ~RGX_CR_SLC_STATUS2_BUS3_OUTSTANDING_READS_CLRMSK |
+                              ~RGX_CR_SLC_STATUS2_BUS2_OUTSTANDING_WRITES_CLRMSK |
+                              ~RGX_CR_SLC_STATUS2_BUS3_OUTSTANDING_WRITES_CLRMSK));
+       if (eError != PVRSRV_OK) return eError;
+
+
+       /* Wait for SLC to signal IDLE */
+       eError = RGXPollReg32(hPrivate,
+                             RGX_CR_SLC_IDLE,
+                             RGX_CR_SLC_IDLE_MASKFULL^(CR_IDLE_UNSELECTED_MASK),
+                             RGX_CR_SLC_IDLE_MASKFULL^(CR_IDLE_UNSELECTED_MASK));
+       if (eError != PVRSRV_OK) return eError;
+
+
+       /* Wait for Jones to signal IDLE except for the Garten Wrapper */
+       eError = RGXPollReg32(hPrivate,
+                             RGX_CR_JONES_IDLE,
+                             ui32JonesIdleMask^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN),
+                             ui32JonesIdleMask^(RGX_CR_JONES_IDLE_GARTEN_EN|RGX_CR_JONES_IDLE_SOCIF_EN));
+
+       if (eError != PVRSRV_OK) return eError;
+
+
+       if (bMetaFW)
+       {
+               IMG_UINT32 ui32RegValue;
+
+               eError = RGXReadMetaRegThroughSP(hPrivate,
+                                                META_CR_TxVECINT_BHALT,
+                                                &ui32RegValue);
+               if (eError != PVRSRV_OK) return eError;
+
+               if ((ui32RegValue & 0xFFFFFFFFU) == 0x0)
+               {
+                       /* Wait for Sidekick/Jones to signal IDLE including
+                        * the Garten Wrapper if there is no debugger attached
+                        * (TxVECINT_BHALT = 0x0) */
+                       eError = RGXPollReg32(hPrivate,
+                                             RGX_CR_JONES_IDLE,
+                                             ui32JonesIdleMask^RGX_CR_JONES_IDLE_SOCIF_EN,
+                                             ui32JonesIdleMask^RGX_CR_JONES_IDLE_SOCIF_EN);
+                       if (eError != PVRSRV_OK) return eError;
+               }
+       }
+       else
+       {
+               eError = RGXPollReg32(hPrivate,
+                                     RGX_CR_JONES_IDLE,
+                                     ui32JonesIdleMask^RGX_CR_JONES_IDLE_SOCIF_EN,
+                                     ui32JonesIdleMask^RGX_CR_JONES_IDLE_SOCIF_EN);
+               if (eError != PVRSRV_OK) return eError;
+       }
+
+       return eError;
+}
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.c
new file mode 100644 (file)
index 0000000..290bc7f
--- /dev/null
@@ -0,0 +1,5446 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX TA/3D routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    RGX TA/3D routines
+@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.
+*/ /**************************************************************************/
+/* for the offsetof macro */
+#if defined(__linux__)
+#include <linux/stddef.h>
+#else
+#include <stddef.h>
+#endif
+
+#include "pdump_km.h"
+#include "pvr_debug.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxta3d.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "pvrsrv.h"
+#include "rgx_memallocflags.h"
+#include "rgxccb.h"
+#include "rgxhwperf.h"
+#include "ospvr_gputrace.h"
+#include "rgxsyncutils.h"
+#include "htbuffer.h"
+
+#include "rgxdefs_km.h"
+#include "rgx_fwif_km.h"
+#include "physmem.h"
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+#include "process_stats.h"
+
+#include "rgxpmdefs.h"
+
+#include "rgxtimerquery.h"
+
+#if defined(SUPPORT_BUFFER_SYNC)
+#include "pvr_buffer_sync.h"
+#endif
+
+#include "sync_checkpoint.h"
+#include "sync_checkpoint_internal.h"
+
+#if defined(SUPPORT_PDVFS)
+#include "rgxpdvfs.h"
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+
+#define HASH_CLEAN_LIMIT 6
+#endif
+
+/* Enable this to dump the compiled list of UFOs prior to kick call */
+#define ENABLE_TA3D_UFO_DUMP   0
+
+//#define TA3D_CHECKPOINT_DEBUG
+
+#if defined(TA3D_CHECKPOINT_DEBUG)
+#define CHKPT_DBG(X) PVR_DPF(X)
+static INLINE
+void _DebugSyncValues(const IMG_CHAR *pszFunction,
+                                         const IMG_UINT32 *pui32UpdateValues,
+                                         const IMG_UINT32 ui32Count)
+{
+       IMG_UINT32 i;
+       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32UpdateValues;
+
+       for (i = 0; i < ui32Count; i++)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", pszFunction, i, (void*)pui32Tmp, *pui32Tmp));
+               pui32Tmp++;
+       }
+}
+
+static INLINE
+void _DebugSyncCheckpoints(const IMG_CHAR *pszFunction,
+                                                  const IMG_CHAR *pszDMName,
+                                                  const PSYNC_CHECKPOINT *apsSyncCheckpoints,
+                                                  const IMG_UINT32 ui32Count)
+{
+       IMG_UINT32 i;
+
+       for (i = 0; i < ui32Count; i++)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: apsFence%sSyncCheckpoints[%d]=<%p>", pszFunction, pszDMName, i, *(apsSyncCheckpoints + i)));
+       }
+}
+
+#else
+#define CHKPT_DBG(X)
+#endif
+
+/* define the number of commands required to be set up by the CCB helper */
+/* 1 command for the TA */
+#define CCB_CMD_HELPER_NUM_TA_COMMANDS 1
+/* Up to 3 commands for the 3D (partial render fence, partial render, and render) */
+#define CCB_CMD_HELPER_NUM_3D_COMMANDS 3
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#define WORKEST_CYCLES_PREDICTION_GET(x) ((x).ui32CyclesPrediction)
+#else
+#define WORKEST_CYCLES_PREDICTION_GET(x) (NO_CYCEST)
+#endif
+
+typedef struct {
+       DEVMEM_MEMDESC                          *psContextStateMemDesc;
+       RGX_SERVER_COMMON_CONTEXT       *psServerCommonContext;
+       IMG_UINT32                                      ui32Priority;
+} RGX_SERVER_RC_TA_DATA;
+
+typedef struct {
+       DEVMEM_MEMDESC                          *psContextStateMemDesc;
+       RGX_SERVER_COMMON_CONTEXT       *psServerCommonContext;
+       IMG_UINT32                                      ui32Priority;
+} RGX_SERVER_RC_3D_DATA;
+
+struct _RGX_SERVER_RENDER_CONTEXT_ {
+       /* this lock protects usage of the render context.
+        * it ensures only one kick is being prepared and/or submitted on
+        * this render context at any time
+        */
+       POS_LOCK                                hLock;
+       RGX_CCB_CMD_HELPER_DATA asTACmdHelperData[CCB_CMD_HELPER_NUM_TA_COMMANDS];
+       RGX_CCB_CMD_HELPER_DATA as3DCmdHelperData[CCB_CMD_HELPER_NUM_3D_COMMANDS];
+       PVRSRV_DEVICE_NODE                      *psDeviceNode;
+       DEVMEM_MEMDESC                          *psFWRenderContextMemDesc;
+       DEVMEM_MEMDESC                          *psFWFrameworkMemDesc;
+       RGX_SERVER_RC_TA_DATA           sTAData;
+       RGX_SERVER_RC_3D_DATA           s3DData;
+       IMG_UINT32                                      ui32CleanupStatus;
+#define RC_CLEANUP_TA_COMPLETE         (1 << 0)
+#define RC_CLEANUP_3D_COMPLETE         (1 << 1)
+       DLLIST_NODE                                     sListNode;
+       SYNC_ADDR_LIST                          sSyncAddrListTAFence;
+       SYNC_ADDR_LIST                          sSyncAddrListTAUpdate;
+       SYNC_ADDR_LIST                          sSyncAddrList3DFence;
+       SYNC_ADDR_LIST                          sSyncAddrList3DUpdate;
+       ATOMIC_T                                        hIntJobRef;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WORKEST_HOST_DATA                       sWorkEstData;
+#endif
+#if defined(SUPPORT_BUFFER_SYNC)
+       struct pvr_buffer_sync_context *psBufferSyncContext;
+#endif
+};
+
+
+/*
+       Static functions used by render context code
+*/
+
+static
+PVRSRV_ERROR _DestroyTAContext(RGX_SERVER_RC_TA_DATA *psTAData,
+                                                          PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       /* Check if the FW has finished with this resource ... */
+       eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+                                                                                         psTAData->psServerCommonContext,
+                                                                                         RGXFWIF_DM_GEOM,
+                                                                                         PDUMP_FLAGS_CONTINUOUS);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               return eError;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       /* ... it has so we can free its resources */
+       FWCommonContextFree(psTAData->psServerCommonContext);
+       DevmemFwUnmapAndFree(psDeviceNode->pvDevice, psTAData->psContextStateMemDesc);
+       psTAData->psServerCommonContext = NULL;
+       return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR _Destroy3DContext(RGX_SERVER_RC_3D_DATA *ps3DData,
+                                                          PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       /* Check if the FW has finished with this resource ... */
+       eError = RGXFWRequestCommonContextCleanUp(psDeviceNode,
+                                                                                         ps3DData->psServerCommonContext,
+                                                                                         RGXFWIF_DM_3D,
+                                                                                         PDUMP_FLAGS_CONTINUOUS);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               return eError;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       /* ... it has so we can free its resources */
+       FWCommonContextFree(ps3DData->psServerCommonContext);
+       DevmemFwUnmapAndFree(psDeviceNode->pvDevice, ps3DData->psContextStateMemDesc);
+       ps3DData->psServerCommonContext = NULL;
+       return PVRSRV_OK;
+}
+
+static void _RGXDumpPMRPageList(DLLIST_NODE *psNode)
+{
+       RGX_PMR_NODE *psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
+       PVRSRV_ERROR                    eError;
+
+       eError = PMRDumpPageList(psPMRNode->psPMR,
+                                                       RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "Error (%s) printing pmr %p",
+                               PVRSRVGetErrorString(eError),
+                               psPMRNode->psPMR));
+       }
+}
+
+IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList)
+{
+       DLLIST_NODE *psNode, *psNext;
+
+       PVR_LOG(("Freelist FWAddr 0x%08x, ID = %d, CheckSum 0x%016" IMG_UINT64_FMTSPECx,
+                               psFreeList->sFreeListFWDevVAddr.ui32Addr,
+                               psFreeList->ui32FreelistID,
+                               psFreeList->ui64FreelistChecksum));
+
+       /* Dump Init FreeList page list */
+       PVR_LOG(("  Initial Memory block"));
+       dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
+       {
+               _RGXDumpPMRPageList(psNode);
+       }
+
+       /* Dump Grow FreeList page list */
+       PVR_LOG(("  Grow Memory blocks"));
+       dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
+       {
+               _RGXDumpPMRPageList(psNode);
+       }
+
+       return IMG_TRUE;
+}
+
+static void _CheckFreelist(RGX_FREELIST *psFreeList,
+                                                  IMG_UINT32 ui32NumOfPagesToCheck,
+                                                  IMG_UINT64 ui64ExpectedCheckSum,
+                                                  IMG_UINT64 *pui64CalculatedCheckSum)
+{
+#if defined(NO_HARDWARE)
+       /* No checksum needed as we have all information in the pdumps */
+       PVR_UNREFERENCED_PARAMETER(psFreeList);
+       PVR_UNREFERENCED_PARAMETER(ui32NumOfPagesToCheck);
+       PVR_UNREFERENCED_PARAMETER(ui64ExpectedCheckSum);
+       *pui64CalculatedCheckSum = 0;
+#else
+       PVRSRV_ERROR eError;
+       size_t uiNumBytes;
+       IMG_UINT8* pui8Buffer;
+       IMG_UINT32* pui32Buffer;
+       IMG_UINT32 ui32CheckSumAdd = 0;
+       IMG_UINT32 ui32CheckSumXor = 0;
+       IMG_UINT32 ui32Entry;
+       IMG_UINT32 ui32Entry2;
+       IMG_BOOL bFreelistBad = IMG_FALSE;
+
+       *pui64CalculatedCheckSum = 0;
+
+       PVR_ASSERT(ui32NumOfPagesToCheck <= (psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages));
+
+       /* Allocate Buffer of the size of the freelist */
+       pui8Buffer = OSAllocMem(ui32NumOfPagesToCheck * sizeof(IMG_UINT32));
+       if (pui8Buffer == NULL)
+       {
+               PVR_LOG(("%s: Failed to allocate buffer to check freelist %p!",
+                               __func__, psFreeList));
+               PVR_ASSERT(0);
+               return;
+       }
+
+       /* Copy freelist content into Buffer */
+       eError = PMR_ReadBytes(psFreeList->psFreeListPMR,
+                                       psFreeList->uiFreeListPMROffset +
+                                       (((psFreeList->ui32MaxFLPages -
+                                          psFreeList->ui32CurrentFLPages - psFreeList->ui32ReadyFLPages) * sizeof(IMG_UINT32)) &
+                                        ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1)),
+                                        pui8Buffer,
+                                        ui32NumOfPagesToCheck * sizeof(IMG_UINT32),
+                                       &uiNumBytes);
+       if (eError != PVRSRV_OK)
+       {
+               OSFreeMem(pui8Buffer);
+               PVR_LOG(("%s: Failed to get freelist data for freelist %p!",
+                               __func__, psFreeList));
+               PVR_ASSERT(0);
+               return;
+       }
+
+       PVR_ASSERT(uiNumBytes == ui32NumOfPagesToCheck * sizeof(IMG_UINT32));
+
+       /* Generate checksum (skipping the first page if not allocated) */
+       pui32Buffer = (IMG_UINT32 *)pui8Buffer;
+       ui32Entry = ((psFreeList->ui32GrowFLPages == 0  &&  psFreeList->ui32CurrentFLPages > 1) ? 1 : 0);
+       for (/*ui32Entry*/ ; ui32Entry < ui32NumOfPagesToCheck; ui32Entry++)
+       {
+               ui32CheckSumAdd += pui32Buffer[ui32Entry];
+               ui32CheckSumXor ^= pui32Buffer[ui32Entry];
+
+               /* Check for double entries */
+               for (ui32Entry2 = ui32Entry+1; ui32Entry2 < ui32NumOfPagesToCheck; ui32Entry2++)
+               {
+                       if (pui32Buffer[ui32Entry] == pui32Buffer[ui32Entry2])
+                       {
+                               PVR_LOG(("%s: Freelist consistency failure: FW addr: 0x%08X, Double entry found 0x%08x on idx: %d and %d of %d",
+                                               __func__,
+                                               psFreeList->sFreeListFWDevVAddr.ui32Addr,
+                                               pui32Buffer[ui32Entry2],
+                                               ui32Entry,
+                                               ui32Entry2,
+                                               psFreeList->ui32CurrentFLPages));
+                               bFreelistBad = IMG_TRUE;
+                               break;
+                       }
+               }
+       }
+
+       OSFreeMem(pui8Buffer);
+
+       /* Check the calculated checksum against the expected checksum... */
+       *pui64CalculatedCheckSum = ((IMG_UINT64)ui32CheckSumXor << 32) | ui32CheckSumAdd;
+
+       if (ui64ExpectedCheckSum != 0  &&  ui64ExpectedCheckSum != *pui64CalculatedCheckSum)
+       {
+               PVR_LOG(("%s: Checksum mismatch for freelist %p! Expected 0x%016llx calculated 0x%016llx",
+                       __func__, psFreeList, ui64ExpectedCheckSum, *pui64CalculatedCheckSum));
+               bFreelistBad = IMG_TRUE;
+       }
+
+       if (bFreelistBad)
+       {
+               PVR_LOG(("%s: Sleeping for ever!", __func__));
+               PVR_ASSERT(!bFreelistBad);
+       }
+#endif
+}
+
+
+/*
+ *  Function to work out the number of freelist pages to reserve for growing
+ *  within the FW without having to wait for the host to progress a grow
+ *  request.
+ *
+ *  The number of pages must be a multiple of 4 to align the PM addresses
+ *  for the initial freelist allocation and also be less than the grow size.
+ *
+ *  If the threshold or grow size means less than 4 pages, then the feature
+ *  is not used.
+ */
+static IMG_UINT32 _CalculateFreelistReadyPages(RGX_FREELIST *psFreeList,
+                                               IMG_UINT32  ui32FLPages)
+{
+       IMG_UINT32  ui32ReadyFLPages = ((ui32FLPages * psFreeList->ui32GrowThreshold) / 100) &
+                                      ~((RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE/sizeof(IMG_UINT32))-1);
+
+       if (ui32ReadyFLPages > psFreeList->ui32GrowFLPages)
+       {
+               ui32ReadyFLPages = psFreeList->ui32GrowFLPages;
+       }
+
+       return ui32ReadyFLPages;
+}
+
+
+PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
+                             IMG_UINT32 ui32NumPages,
+                             PDLLIST_NODE pListHeader)
+{
+       RGX_PMR_NODE    *psPMRNode;
+       IMG_DEVMEM_SIZE_T uiSize;
+       IMG_UINT32  ui32MappingTable = 0;
+       IMG_DEVMEM_OFFSET_T uiOffset;
+       IMG_DEVMEM_SIZE_T uiLength;
+       IMG_DEVMEM_SIZE_T uistartPage;
+       PVRSRV_ERROR eError;
+       static const IMG_CHAR szAllocName[] = "Free List";
+
+       /* Are we allowed to grow ? */
+       if (psFreeList->ui32MaxFLPages - (psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages) < ui32NumPages)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                               "Freelist [0x%p]: grow by %u pages denied. "
+                               "Max PB size reached (current pages %u+%u/%u)",
+                               psFreeList,
+                               ui32NumPages,
+                               psFreeList->ui32CurrentFLPages,
+                               psFreeList->ui32ReadyFLPages,
+                               psFreeList->ui32MaxFLPages));
+               return PVRSRV_ERROR_PBSIZE_ALREADY_MAX;
+       }
+
+       /* Allocate kernel memory block structure */
+       psPMRNode = OSAllocMem(sizeof(*psPMRNode));
+       if (psPMRNode == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: failed to allocate host data structure",
+                               __func__));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorAllocHost;
+       }
+
+       /*
+        * Lock protects simultaneous manipulation of:
+        * - the memory block list
+        * - the freelist's ui32CurrentFLPages
+        */
+       OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+
+
+       /*
+        *  The PM never takes the last page in a freelist, so if this block
+        *  of pages is the first one and there is no ability to grow, then
+        *  we can skip allocating one 4K page for the lowest entry.
+        */
+       if (OSGetPageSize() > RGX_BIF_PM_PHYSICAL_PAGE_SIZE)
+       {
+               /*
+                * Allocation size will be rounded up to the OS page size,
+                * any attempt to change it a bit now will be invalidated later.
+                */
+               psPMRNode->bFirstPageMissing = IMG_FALSE;
+       }
+       else
+       {
+               psPMRNode->bFirstPageMissing = (psFreeList->ui32GrowFLPages == 0  &&  ui32NumPages > 1);
+       }
+
+       psPMRNode->ui32NumPages = ui32NumPages;
+       psPMRNode->psFreeList = psFreeList;
+
+       /* Allocate Memory Block */
+       PDUMPCOMMENT(psFreeList->psDevInfo->psDeviceNode, "Allocate PB Block (Pages %08X)", ui32NumPages);
+       uiSize = (IMG_DEVMEM_SIZE_T)ui32NumPages * RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
+       if (psPMRNode->bFirstPageMissing)
+       {
+               uiSize -= RGX_BIF_PM_PHYSICAL_PAGE_SIZE;
+       }
+       eError = PhysmemNewRamBackedPMR(psFreeList->psConnection,
+                       psFreeList->psDevInfo->psDeviceNode,
+                       uiSize,
+                       uiSize,
+                       1,
+                       1,
+                       &ui32MappingTable,
+                       RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+                       PVRSRV_MEMALLOCFLAG_GPU_READABLE,
+                       sizeof(szAllocName),
+                       szAllocName,
+                       psFreeList->ownerPid,
+                       &psPMRNode->psPMR,
+                       PDUMP_NONE,
+                       NULL);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to allocate PB block of size: 0x%016" IMG_UINT64_FMTSPECX,
+                                __func__,
+                                (IMG_UINT64)uiSize));
+               goto ErrorBlockAlloc;
+       }
+
+       /* Zeroing physical pages pointed by the PMR */
+       if (psFreeList->psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
+       {
+               eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to zero PMR %p of freelist %p (%s)",
+                                       __func__,
+                                       psPMRNode->psPMR,
+                                       psFreeList,
+                                       PVRSRVGetErrorString(eError)));
+                       PVR_ASSERT(0);
+               }
+       }
+
+       uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
+       uistartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
+       uiOffset = psFreeList->uiFreeListPMROffset + ((uistartPage * sizeof(IMG_UINT32)) & ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1));
+
+#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
+
+       eError = RIWritePMREntryWithOwnerKM(psPMRNode->psPMR,
+                                           psFreeList->ownerPid);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: call to RIWritePMREntryWithOwnerKM failed (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+       }
+
+        /* Attach RI information */
+       eError = RIWriteMEMDESCEntryKM(psPMRNode->psPMR,
+                                      OSStringNLength(szAllocName, DEVMEM_ANNOTATION_MAX_LEN),
+                                      szAllocName,
+                                      0,
+                                      uiSize,
+                                      IMG_FALSE,
+                                      IMG_FALSE,
+                                      &psPMRNode->hRIHandle);
+       PVR_LOG_IF_ERROR(eError, "RIWriteMEMDESCEntryKM");
+
+#endif /* if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) */
+
+       /* write Freelist with Memory Block physical addresses */
+       eError = PMRWritePMPageList(
+                                               /* Target PMR, offset, and length */
+                                               psFreeList->psFreeListPMR,
+                                               (psPMRNode->bFirstPageMissing ? uiOffset + sizeof(IMG_UINT32) : uiOffset),
+                                               (psPMRNode->bFirstPageMissing ? uiLength - sizeof(IMG_UINT32) : uiLength),
+                                               /* Referenced PMR, and "page" granularity */
+                                               psPMRNode->psPMR,
+                                               RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+                                               &psPMRNode->psPageList);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to write pages of Node %p",
+                                __func__,
+                                psPMRNode));
+               goto ErrorPopulateFreelist;
+       }
+
+#if defined(SUPPORT_SHADOW_FREELISTS)
+       /* Copy freelist memory to shadow freelist */
+       {
+               const IMG_UINT32 ui32FLMaxSize = psFreeList->ui32MaxFLPages * sizeof(IMG_UINT32);
+               const IMG_UINT32 ui32MapSize = ui32FLMaxSize * 2;
+               const IMG_UINT32 ui32CopyOffset = uiOffset - psFreeList->uiFreeListPMROffset;
+               IMG_BYTE *pFLMapAddr;
+               size_t uiNumBytes;
+               PVRSRV_ERROR res;
+               IMG_HANDLE hMapHandle;
+
+               /* Map both the FL and the shadow FL */
+               res = PMRAcquireKernelMappingData(psFreeList->psFreeListPMR, psFreeList->uiFreeListPMROffset, ui32MapSize,
+                                                 (void**) &pFLMapAddr, &uiNumBytes, &hMapHandle);
+               if (res != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to map freelist (ID=%d)",
+                                __func__,
+                                psFreeList->ui32FreelistID));
+                       goto ErrorPopulateFreelist;
+               }
+
+               /* Copy only the newly added memory */
+               OSCachedMemCopy(pFLMapAddr + ui32FLMaxSize + ui32CopyOffset, pFLMapAddr + ui32CopyOffset , uiLength);
+               OSWriteMemoryBarrier(pFLMapAddr);
+
+#if defined(PDUMP)
+               PDUMPCOMMENT(psFreeList->psDevInfo->psDeviceNode, "Initialize shadow freelist");
+
+               /* Translate memcpy to pdump */
+               {
+                       IMG_DEVMEM_OFFSET_T uiCurrOffset;
+
+                       for (uiCurrOffset = uiOffset; (uiCurrOffset - uiOffset) < uiLength; uiCurrOffset += sizeof(IMG_UINT32))
+                       {
+                               PMRPDumpCopyMem32(psFreeList->psFreeListPMR,
+                                                 uiCurrOffset + ui32FLMaxSize,
+                                                 psFreeList->psFreeListPMR,
+                                                 uiCurrOffset,
+                                                 ":SYSMEM:$1",
+                                                 PDUMP_FLAGS_CONTINUOUS);
+                       }
+               }
+#endif
+
+
+               res = PMRReleaseKernelMappingData(psFreeList->psFreeListPMR, hMapHandle);
+
+               if (res != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Failed to release freelist mapping (ID=%d)",
+                                __func__,
+                                psFreeList->ui32FreelistID));
+                       goto ErrorPopulateFreelist;
+               }
+       }
+#endif
+
+       /* We add It must be added to the tail, otherwise the freelist population won't work */
+       dllist_add_to_head(pListHeader, &psPMRNode->sMemoryBlock);
+
+       /* Update number of available pages */
+       psFreeList->ui32CurrentFLPages += ui32NumPages;
+
+       /* Update statistics (needs to happen before the ReadyFL calculation to also count those pages) */
+       if (psFreeList->ui32NumHighPages < psFreeList->ui32CurrentFLPages)
+       {
+               psFreeList->ui32NumHighPages = psFreeList->ui32CurrentFLPages;
+       }
+
+       /* Reserve a number ready pages to allow the FW to process OOM quickly and asynchronously request a grow. */
+       psFreeList->ui32ReadyFLPages    = _CalculateFreelistReadyPages(psFreeList, psFreeList->ui32CurrentFLPages);
+       psFreeList->ui32CurrentFLPages -= psFreeList->ui32ReadyFLPages;
+
+       if (psFreeList->bCheckFreelist)
+       {
+               /*
+                *  We can only calculate the freelist checksum when the list is full
+                *  (e.g. at initial creation time). At other times the checksum cannot
+                *  be calculated and has to be disabled for this freelist.
+                */
+               if ((psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages) == ui32NumPages)
+               {
+                       _CheckFreelist(psFreeList, ui32NumPages, 0, &psFreeList->ui64FreelistChecksum);
+               }
+               else
+               {
+                       psFreeList->ui64FreelistChecksum = 0;
+               }
+       }
+       OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+       PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p]: %s %u pages (pages=%u+%u/%u checksum=0x%016" IMG_UINT64_FMTSPECx "%s)",
+                       psFreeList,
+               ((psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages) == ui32NumPages ? "Create initial" : "Grow by"),
+                       ui32NumPages,
+                       psFreeList->ui32CurrentFLPages,
+                       psFreeList->ui32ReadyFLPages,
+                       psFreeList->ui32MaxFLPages,
+                       psFreeList->ui64FreelistChecksum,
+                       (psPMRNode->bFirstPageMissing ? " - lowest page not allocated" : "")));
+
+       return PVRSRV_OK;
+
+       /* Error handling */
+ErrorPopulateFreelist:
+       PMRUnrefPMR(psPMRNode->psPMR);
+
+ErrorBlockAlloc:
+       OSFreeMem(psPMRNode);
+       OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+ErrorAllocHost:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+
+}
+
+static PVRSRV_ERROR RGXShrinkFreeList(PDLLIST_NODE pListHeader,
+                                                                               RGX_FREELIST *psFreeList)
+{
+       DLLIST_NODE *psNode;
+       RGX_PMR_NODE *psPMRNode;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+       IMG_UINT32 ui32OldValue;
+
+       /*
+        * Lock protects simultaneous manipulation of:
+        * - the memory block list
+        * - the freelist's ui32CurrentFLPages value
+        */
+       PVR_ASSERT(pListHeader);
+       PVR_ASSERT(psFreeList);
+       PVR_ASSERT(psFreeList->psDevInfo);
+       PVR_ASSERT(psFreeList->psDevInfo->hLockFreeList);
+
+       OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+
+       /* Get node from head of list and remove it */
+       psNode = dllist_get_next_node(pListHeader);
+       if (psNode)
+       {
+               dllist_remove_node(psNode);
+
+               psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
+               PVR_ASSERT(psPMRNode);
+               PVR_ASSERT(psPMRNode->psPMR);
+               PVR_ASSERT(psPMRNode->psFreeList);
+
+               /* remove block from freelist list */
+
+               /* Unwrite Freelist with Memory Block physical addresses */
+               eError = PMRUnwritePMPageList(psPMRNode->psPageList);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to unwrite pages of Node %p",
+                                        __func__,
+                                        psPMRNode));
+                       PVR_ASSERT(IMG_FALSE);
+               }
+
+#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
+
+               if (psPMRNode->hRIHandle)
+               {
+                       PVRSRV_ERROR eError;
+
+                       eError = RIDeleteMEMDESCEntryKM(psPMRNode->hRIHandle);
+                       PVR_LOG_IF_ERROR(eError, "RIDeleteMEMDESCEntryKM");
+               }
+
+#endif  /* if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) */
+
+               /* Free PMR (We should be the only one that holds a ref on the PMR) */
+               eError = PMRUnrefPMR(psPMRNode->psPMR);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to free PB block %p (%s)",
+                                        __func__,
+                                        psPMRNode->psPMR,
+                                        PVRSRVGetErrorString(eError)));
+                       PVR_ASSERT(IMG_FALSE);
+               }
+
+               /* update available pages in freelist */
+               ui32OldValue = psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages;
+
+               /*
+                * Deallocated pages should first be deducted from ReadyPages bank, once
+                * there are no more left, start deducting them from CurrentPage bank.
+                */
+               if (psPMRNode->ui32NumPages > psFreeList->ui32ReadyFLPages)
+               {
+                       psFreeList->ui32CurrentFLPages -= psPMRNode->ui32NumPages - psFreeList->ui32ReadyFLPages;
+                       psFreeList->ui32ReadyFLPages = 0;
+               }
+               else
+               {
+                       psFreeList->ui32ReadyFLPages -= psPMRNode->ui32NumPages;
+               }
+
+               /* check underflow */
+               PVR_ASSERT(ui32OldValue > (psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages));
+
+               PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p]: shrink by %u pages (current pages %u/%u)",
+                                                               psFreeList,
+                                                               psPMRNode->ui32NumPages,
+                                                               psFreeList->ui32CurrentFLPages,
+                                                               psFreeList->ui32MaxFLPages));
+
+               OSFreeMem(psPMRNode);
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                               "Freelist [0x%p]: shrink denied. PB already at initial PB size (%u pages)",
+                                                               psFreeList,
+                                                               psFreeList->ui32InitFLPages));
+               eError = PVRSRV_ERROR_PBSIZE_ALREADY_MIN;
+       }
+
+       OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+       return eError;
+}
+
+static RGX_FREELIST *FindFreeList(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32FreelistID)
+{
+       DLLIST_NODE *psNode, *psNext;
+       RGX_FREELIST *psFreeList = NULL;
+
+       OSLockAcquire(psDevInfo->hLockFreeList);
+
+       dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
+       {
+               RGX_FREELIST *psThisFreeList = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+
+               if (psThisFreeList->ui32FreelistID == ui32FreelistID)
+               {
+                       psFreeList = psThisFreeList;
+                       break;
+               }
+       }
+
+       OSLockRelease(psDevInfo->hLockFreeList);
+       return psFreeList;
+}
+
+void RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+                           IMG_UINT32 ui32FreelistID)
+{
+       RGX_FREELIST *psFreeList = NULL;
+       RGXFWIF_KCCB_CMD s3DCCBCmd;
+       IMG_UINT32 ui32GrowValue;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psDevInfo);
+
+       psFreeList = FindFreeList(psDevInfo, ui32FreelistID);
+       if (psFreeList == NULL)
+       {
+               /* Should never happen */
+               PVR_DPF((PVR_DBG_ERROR,
+                        "FreeList Lookup for FreeList ID 0x%08x failed (Populate)",
+                        ui32FreelistID));
+               PVR_ASSERT(IMG_FALSE);
+
+               return;
+       }
+
+       /* Since the FW made the request, it has already consumed the ready pages, update the host struct */
+       psFreeList->ui32CurrentFLPages += psFreeList->ui32ReadyFLPages;
+       psFreeList->ui32ReadyFLPages = 0;
+
+
+       /* Try to grow the freelist */
+       eError = RGXGrowFreeList(psFreeList,
+                                psFreeList->ui32GrowFLPages,
+                                &psFreeList->sMemoryBlockHead);
+
+       if (eError == PVRSRV_OK)
+       {
+               /* Grow successful, return size of grow size */
+               ui32GrowValue = psFreeList->ui32GrowFLPages;
+
+               psFreeList->ui32NumGrowReqByFW++;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+               /* Update Stats */
+               PVRSRVStatsUpdateFreelistStats(0,
+                                              1, /* Add 1 to the appropriate counter (Requests by FW) */
+                                              psFreeList->ui32InitFLPages,
+                                              psFreeList->ui32NumHighPages,
+                                              psFreeList->ownerPid);
+
+#endif
+
+       }
+       else
+       {
+               /* Grow failed */
+               ui32GrowValue = 0;
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Grow for FreeList %p failed (%s)",
+                        psFreeList,
+                        PVRSRVGetErrorString(eError)));
+       }
+
+       /* send feedback */
+       s3DCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELIST_GROW_UPDATE;
+       s3DCCBCmd.uCmdData.sFreeListGSData.sFreeListFWDevVAddr.ui32Addr = psFreeList->sFreeListFWDevVAddr.ui32Addr;
+       s3DCCBCmd.uCmdData.sFreeListGSData.ui32DeltaPages = ui32GrowValue;
+       s3DCCBCmd.uCmdData.sFreeListGSData.ui32NewPages = psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages;
+       s3DCCBCmd.uCmdData.sFreeListGSData.ui32ReadyPages = psFreeList->ui32ReadyFLPages;
+
+
+       PVR_DPF((PVR_DBG_MESSAGE, "Freelist [%p]: Grow pages=%u, new pages=%u, ready pages=%u, counter=%d",
+                psFreeList,
+                ui32GrowValue,
+                s3DCCBCmd.uCmdData.sFreeListGSData.ui32NewPages,
+                s3DCCBCmd.uCmdData.sFreeListGSData.ui32ReadyPages,
+                psFreeList->ui32NumGrowReqByFW));
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                           RGXFWIF_DM_3D,
+                                           &s3DCCBCmd,
+                                           PDUMP_FLAGS_NONE);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+       /* Kernel CCB should never fill up, as the FW is processing them right away  */
+
+       PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+static void _RGXFreeListReconstruction(PDLLIST_NODE psNode)
+{
+
+       PVRSRV_RGXDEV_INFO              *psDevInfo;
+       RGX_FREELIST                    *psFreeList;
+       RGX_PMR_NODE                    *psPMRNode;
+       PVRSRV_ERROR                    eError;
+       IMG_DEVMEM_OFFSET_T             uiOffset;
+       IMG_DEVMEM_SIZE_T               uiLength;
+       IMG_UINT32                              ui32StartPage;
+
+       psPMRNode = IMG_CONTAINER_OF(psNode, RGX_PMR_NODE, sMemoryBlock);
+       psFreeList = psPMRNode->psFreeList;
+       PVR_ASSERT(psFreeList);
+       psDevInfo = psFreeList->psDevInfo;
+       PVR_ASSERT(psDevInfo);
+
+       uiLength = psPMRNode->ui32NumPages * sizeof(IMG_UINT32);
+       ui32StartPage = (psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages - psPMRNode->ui32NumPages);
+       uiOffset = psFreeList->uiFreeListPMROffset + ((ui32StartPage * sizeof(IMG_UINT32)) & ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1));
+
+       PMRUnwritePMPageList(psPMRNode->psPageList);
+       psPMRNode->psPageList = NULL;
+       eError = PMRWritePMPageList(
+                                               /* Target PMR, offset, and length */
+                                               psFreeList->psFreeListPMR,
+                                               (psPMRNode->bFirstPageMissing ? uiOffset + sizeof(IMG_UINT32) : uiOffset),
+                                               (psPMRNode->bFirstPageMissing ? uiLength - sizeof(IMG_UINT32) : uiLength),
+                                               /* Referenced PMR, and "page" granularity */
+                                               psPMRNode->psPMR,
+                                               RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT,
+                                               &psPMRNode->psPageList);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Error (%s) writing FL 0x%08x",
+                               __func__,
+                               PVRSRVGetErrorString(eError),
+                               (IMG_UINT32)psFreeList->ui32FreelistID));
+       }
+
+       /* Zeroing physical pages pointed by the reconstructed freelist */
+       if (psDevInfo->ui32DeviceFlags & RGXKM_DEVICE_STATE_ZERO_FREELIST)
+       {
+               eError = PMRZeroingPMR(psPMRNode->psPMR, RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to zero PMR %p of freelist %p (%s)",
+                                       __func__,
+                                       psPMRNode->psPMR,
+                                       psFreeList,
+                                       PVRSRVGetErrorString(eError)));
+                       PVR_ASSERT(0);
+               }
+       }
+
+       psFreeList->ui32CurrentFLPages += psPMRNode->ui32NumPages;
+}
+
+
+static PVRSRV_ERROR RGXReconstructFreeList(RGX_FREELIST *psFreeList)
+{
+       IMG_UINT32        ui32OriginalFLPages;
+       DLLIST_NODE       *psNode, *psNext;
+       PVRSRV_ERROR      eError;
+#if !defined(PM_INTERACTIVE_MODE)
+       IMG_DEV_VIRTADDR  sFreeListBaseDevVAddr;
+#endif
+
+       //PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: Reconstructing freelist %p (ID=%u)", psFreeList, psFreeList->ui32FreelistID));
+
+       /* Do the FreeList Reconstruction */
+       ui32OriginalFLPages            = psFreeList->ui32CurrentFLPages;
+       psFreeList->ui32CurrentFLPages = 0;
+
+       /* Reconstructing Init FreeList pages */
+       dllist_foreach_node(&psFreeList->sMemoryBlockInitHead, psNode, psNext)
+       {
+               _RGXFreeListReconstruction(psNode);
+       }
+
+       /* Reconstructing Grow FreeList pages */
+       dllist_foreach_node(&psFreeList->sMemoryBlockHead, psNode, psNext)
+       {
+               _RGXFreeListReconstruction(psNode);
+       }
+
+       /* Ready pages are allocated but kept hidden until OOM occurs. */
+       psFreeList->ui32CurrentFLPages -= psFreeList->ui32ReadyFLPages;
+       if (psFreeList->ui32CurrentFLPages != ui32OriginalFLPages)
+       {
+               PVR_ASSERT(psFreeList->ui32CurrentFLPages == ui32OriginalFLPages);
+               return PVRSRV_ERROR_FREELIST_RECONSTRUCTION_FAILED;
+       }
+
+       {
+               RGXFWIF_FREELIST  *psFWFreeList;
+
+               /* Update firmware freelist structure */
+               eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+
+#if defined(PM_INTERACTIVE_MODE)
+               psFWFreeList->ui32CurrentStackTop       = psFWFreeList->ui32CurrentPages - 1;
+               psFWFreeList->ui32AllocatedPageCount    = 0;
+               psFWFreeList->ui32AllocatedMMUPageCount = 0;
+#else
+               sFreeListBaseDevVAddr                          = psFWFreeList->sFreeListBaseDevVAddr;
+               psFWFreeList->bUpdatePending                   = IMG_FALSE;
+               psFWFreeList->ui32UpdateNewPages               = 0;
+               psFWFreeList->ui32UpdateNewReadyPages          = 0;
+               psFWFreeList->sFreeListLastGrowDevVAddr.uiAddr = 0;
+#endif
+
+               DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+       }
+
+#if !defined(PM_INTERACTIVE_MODE)
+       /* Reset freelist state buffer */
+       {
+               RGX_PM_FREELISTSTATE_BUFFER             sFLState;
+               size_t uiNbBytes;
+               IMG_DEV_VIRTADDR sFLBaseAddr;
+
+               eError = PMR_ReadBytes(psFreeList->psFreeListStatePMR, psFreeList->uiFreeListStatePMROffset, (IMG_UINT8*)&sFLState, sizeof(sFLState), &uiNbBytes);
+
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+
+               PVR_ASSERT(uiNbBytes == sizeof(sFLState));
+
+               sFLBaseAddr.uiAddr = (sFreeListBaseDevVAddr.uiAddr +
+                                     ((psFreeList->ui32MaxFLPages - psFreeList->ui32CurrentFLPages) * sizeof(IMG_UINT32))) &
+                                     ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1);
+               /* Note: Freelist base address is packed shifted down. */
+               RGX_PM_FREELISTSTATE_BUFFER_SET_BASE_ADDR(sFLState, sFLBaseAddr.uiAddr >> RGX_PM_FREELISTSTATE_BASE_ADDR_ALIGNSHIFT);
+               RGX_PM_FREELISTSTATE_BUFFER_SET_STACK_PTR(sFLState, psFreeList->ui32CurrentFLPages - 1);
+               RGX_PM_FREELISTSTATE_BUFFER_SET_PAGE_STATUS(sFLState, 0);
+               RGX_PM_FREELISTSTATE_BUFFER_SET_MMUPAGE_STATUS(sFLState, 0);
+
+               eError = PMR_WriteBytes(psFreeList->psFreeListStatePMR, psFreeList->uiFreeListStatePMROffset, (IMG_UINT8*)&sFLState, sizeof(sFLState), &uiNbBytes);
+
+               if (eError != PVRSRV_OK)
+               {
+                       return eError;
+               }
+
+               PVR_ASSERT(uiNbBytes == sizeof(sFLState));
+       }
+#endif
+
+       /* Check the Freelist checksum if required (as the list is fully populated) */
+       if (psFreeList->bCheckFreelist)
+       {
+               IMG_UINT64  ui64CheckSum;
+
+               _CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
+       }
+
+       return eError;
+}
+
+
+void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                              IMG_UINT32 ui32FreelistsCount,
+                                              const IMG_UINT32 *paui32Freelists)
+{
+       PVRSRV_ERROR      eError = PVRSRV_OK;
+       DLLIST_NODE       *psNode, *psNext;
+       IMG_UINT32        ui32Loop;
+       RGXFWIF_KCCB_CMD  sTACCBCmd;
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       DLLIST_NODE       *psNodeHWRTData, *psNextHWRTData;
+       RGX_KM_HW_RT_DATASET *psKMHWRTDataSet;
+       RGXFWIF_HWRTDATA     *psHWRTData;
+#endif
+       IMG_UINT32        ui32FinalFreelistsCount = 0;
+       IMG_UINT32        aui32FinalFreelists[RGXFWIF_MAX_FREELISTS_TO_RECONSTRUCT * 2]; /* Worst-case is double what we are sent */
+
+       PVR_ASSERT(psDevInfo != NULL);
+       PVR_ASSERT(ui32FreelistsCount <= RGXFWIF_MAX_FREELISTS_TO_RECONSTRUCT);
+       if (ui32FreelistsCount > RGXFWIF_MAX_FREELISTS_TO_RECONSTRUCT)
+       {
+               ui32FreelistsCount = RGXFWIF_MAX_FREELISTS_TO_RECONSTRUCT;
+       }
+
+       //PVR_DPF((PVR_DBG_ERROR, "FreeList RECONSTRUCTION: %u freelist(s) requested for reconstruction", ui32FreelistsCount));
+
+       /*
+        *  Initialise the response command (in case we don't find a freelist ID).
+        *  Also copy the list to the 'final' freelist array.
+        */
+       sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_FREELISTS_RECONSTRUCTION_UPDATE;
+       sTACCBCmd.uCmdData.sFreeListsReconstructionData.ui32FreelistsCount = ui32FreelistsCount;
+
+       for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+       {
+               sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] = paui32Freelists[ui32Loop] |
+                               RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
+               aui32FinalFreelists[ui32Loop] = paui32Freelists[ui32Loop];
+       }
+
+       ui32FinalFreelistsCount = ui32FreelistsCount;
+
+       /*
+        *  The list of freelists we have been given for reconstruction will
+        *  consist of local and global freelists (maybe MMU as well). Any
+        *  local freelists should have their global list specified as well.
+        *  There may be cases where the global freelist is not given (in
+        *  cases of partial setups before a poll failure for example). To
+        *  handle that we must first ensure every local freelist has a global
+        *  freelist specified, otherwise we add that to the 'final' list.
+        *  This final list of freelists is created in a first pass.
+        *
+        *  Even with the global freelists listed, there may be other local
+        *  freelists not listed, which are going to have their global freelist
+        *  reconstructed. Therefore we have to find those freelists as well
+        *  meaning we will have to iterate the entire list of freelists to
+        *  find which must be reconstructed. This is the second pass.
+        */
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
+       {
+               RGX_FREELIST  *psFreeList   = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+               IMG_BOOL      bInList       = IMG_FALSE;
+               IMG_BOOL      bGlobalInList = IMG_FALSE;
+
+               /* Check if this local freelist is in the list and ensure its global is too. */
+               if (psFreeList->ui32FreelistGlobalID != 0)
+               {
+                       for (ui32Loop = 0; ui32Loop < ui32FinalFreelistsCount; ui32Loop++)
+                       {
+                               if (aui32FinalFreelists[ui32Loop] == psFreeList->ui32FreelistID)
+                               {
+                                       bInList = IMG_TRUE;
+                               }
+                               if (aui32FinalFreelists[ui32Loop] == psFreeList->ui32FreelistGlobalID)
+                               {
+                                       bGlobalInList = IMG_TRUE;
+                               }
+                       }
+
+                       if (bInList  &&  !bGlobalInList)
+                       {
+                               aui32FinalFreelists[ui32FinalFreelistsCount] = psFreeList->ui32FreelistGlobalID;
+                               ui32FinalFreelistsCount++;
+                       }
+               }
+       }
+       dllist_foreach_node(&psDevInfo->sFreeListHead, psNode, psNext)
+       {
+               RGX_FREELIST  *psFreeList  = IMG_CONTAINER_OF(psNode, RGX_FREELIST, sNode);
+               IMG_BOOL      bReconstruct = IMG_FALSE;
+
+               /*
+                *  Check if this freelist needs to be reconstructed (was it requested
+                *  or is its global freelist going to be reconstructed)...
+                */
+               for (ui32Loop = 0; ui32Loop < ui32FinalFreelistsCount; ui32Loop++)
+               {
+                       if (aui32FinalFreelists[ui32Loop] == psFreeList->ui32FreelistID  ||
+                           aui32FinalFreelists[ui32Loop] == psFreeList->ui32FreelistGlobalID)
+                       {
+                               bReconstruct = IMG_TRUE;
+                               break;
+                       }
+               }
+
+               if (bReconstruct)
+               {
+                       eError = RGXReconstructFreeList(psFreeList);
+                       if (eError == PVRSRV_OK)
+                       {
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+                               /* Mark all HWRTData's of reconstructing local freelists as HWR (applies to TA/3D's not finished yet) */
+                               dllist_foreach_node(&psFreeList->sNodeHWRTDataHead, psNodeHWRTData, psNextHWRTData)
+                               {
+                                       psKMHWRTDataSet = IMG_CONTAINER_OF(psNodeHWRTData, RGX_KM_HW_RT_DATASET, sNodeHWRTData);
+                                       eError = DevmemAcquireCpuVirtAddr(psKMHWRTDataSet->psHWRTDataFwMemDesc, (void **)&psHWRTData);
+                                       if (eError != PVRSRV_OK)
+                                       {
+                                               PVR_DPF((PVR_DBG_ERROR,
+                                                                       "Devmem AcquireCpuVirtAddr Failed during Reconstructing of FreeList, FwMemDesc(%p),psHWRTData(%p)",
+                                                                       psKMHWRTDataSet->psHWRTDataFwMemDesc,
+                                                                       psHWRTData));
+                                               continue;
+                                       }
+
+                                       psHWRTData->eState = RGXFWIF_RTDATA_STATE_HWR;
+                                       psHWRTData->ui32HWRTDataFlags &= ~HWRTDATA_HAS_LAST_TA;
+
+                                       DevmemReleaseCpuVirtAddr(psKMHWRTDataSet->psHWRTDataFwMemDesc);
+                               }
+#endif
+
+                               /* Update the response for this freelist if it was specifically requested for reconstruction. */
+                               for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+                               {
+                                       if (paui32Freelists[ui32Loop] == psFreeList->ui32FreelistID)
+                                       {
+                                               /* Reconstruction of this requested freelist was successful... */
+                                               sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &= ~RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG;
+                                               break;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "Reconstructing of FreeList %p failed (%s)",
+                                               psFreeList,
+                                               PVRSRVGetErrorString(eError)));
+                       }
+               }
+       }
+       OSLockRelease(psDevInfo->hLockFreeList);
+
+       /* Check that all freelists were found and reconstructed... */
+       for (ui32Loop = 0; ui32Loop < ui32FreelistsCount; ui32Loop++)
+       {
+               PVR_ASSERT((sTACCBCmd.uCmdData.sFreeListsReconstructionData.aui32FreelistIDs[ui32Loop] &
+                           RGXFWIF_FREELISTS_RECONSTRUCTION_FAILED_FLAG) == 0);
+       }
+
+       /* send feedback */
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                           RGXFWIF_DM_GEOM,
+                                           &sTACCBCmd,
+                                           PDUMP_FLAGS_NONE);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       /* Kernel CCB should never fill up, as the FW is processing them right away  */
+       PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+/* Create HWRTDataSet */
+static PVRSRV_ERROR RGXCreateHWRTData_aux(CONNECTION_DATA  *psConnection,
+                                  PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                  IMG_DEV_VIRTADDR          psVHeapTableDevVAddr,
+                                  IMG_DEV_VIRTADDR          sPMDataDevVAddr, /* per-HWRTData */
+                                  IMG_DEV_VIRTADDR          sPMSecureDataDevVAddr, /* per-HWRTData */
+                                  RGX_FREELIST            *apsFreeLists[RGXFW_MAX_FREELISTS],
+                                  IMG_DEV_VIRTADDR          sTailPtrsDevVAddr,
+                                  IMG_UINT16                ui16MaxRTs,
+                                  RGX_HWRTDATA_COMMON_COOKIE   *psHWRTDataCommonCookie,
+                                  RGX_KM_HW_RT_DATASET    **ppsKMHWRTDataSet) /* per-HWRTData */
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32Loop;
+
+       /* KM cookie storing all the FW/HW data */
+       RGX_KM_HW_RT_DATASET *psKMHWRTDataSet;
+
+       /* local pointers for memory descriptors of FW allocations */
+       DEVMEM_MEMDESC *psHWRTDataFwMemDesc = NULL;
+       DEVMEM_MEMDESC *psRTArrayFwMemDesc = NULL;
+       DEVMEM_MEMDESC *psRendersAccArrayFwMemDesc = NULL;
+
+       /* local pointer for CPU-mapped [FW]HWRTData */
+       RGXFWIF_HWRTDATA *psHWRTData = NULL;
+
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+
+       /* Prepare the HW RT DataSet struct */
+       psKMHWRTDataSet = OSAllocZMem(sizeof(*psKMHWRTDataSet));
+       if (psKMHWRTDataSet == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto AllocError;
+       }
+
+       *ppsKMHWRTDataSet = psKMHWRTDataSet;
+       psKMHWRTDataSet->psDeviceNode = psDeviceNode;
+
+       psKMHWRTDataSet->psHWRTDataCommonCookie = psHWRTDataCommonCookie;
+
+       psDevInfo = psDeviceNode->pvDevice;
+
+       /*
+        * This FW RT-Data is only mapped into kernel for initialisation.
+        * Otherwise this allocation is only used by the FW.
+        * Therefore the GPU cache doesn't need coherency and write-combine will
+        * suffice on the CPU side. (WC buffer will be flushed at the first TA-kick)
+        */
+       eError = DevmemFwAllocate(      psDevInfo,
+                                                               sizeof(RGXFWIF_HWRTDATA),
+                                                               RGX_FWCOMCTX_ALLOCFLAGS,
+                                                               "FwHwRTData",
+                                                               &psHWRTDataFwMemDesc    );
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: DevmemAllocate for RGX_FWIF_HWRTDATA failed",
+                               __func__));
+               goto FWRTDataAllocateError;
+       }
+
+       psKMHWRTDataSet->psHWRTDataFwMemDesc = psHWRTDataFwMemDesc;
+       eError = RGXSetFirmwareAddress( &psKMHWRTDataSet->sHWRTDataFwAddr,
+                                                       psHWRTDataFwMemDesc,
+                                                       0,
+                                                       RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:1", FWRTDataFwAddrError);
+
+       eError = DevmemAcquireCpuVirtAddr(psHWRTDataFwMemDesc,
+                                                                         (void **)&psHWRTData);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWRTDataCpuMapError);
+
+#if defined(PM_INTERACTIVE_MODE)
+       psHWRTData->psVHeapTableDevVAddr = psVHeapTableDevVAddr;
+#endif
+
+       psHWRTData->sHWRTDataCommonFwAddr = psHWRTDataCommonCookie->sHWRTDataCommonFwAddr;
+
+       psHWRTData->sPMSecureRenderStateDevVAddr = sPMSecureDataDevVAddr;
+
+#if defined(PM_INTERACTIVE_MODE)
+       psHWRTData->sPMMListDevVAddr = sPMDataDevVAddr;
+#else
+       psHWRTData->sPMRenderStateDevVAddr = sPMDataDevVAddr;
+#endif
+
+       psHWRTData->sTailPtrsDevVAddr     = sTailPtrsDevVAddr;
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+       {
+               psKMHWRTDataSet->apsFreeLists[ui32Loop] = apsFreeLists[ui32Loop];
+               psKMHWRTDataSet->apsFreeLists[ui32Loop]->ui32RefCount++;
+               psHWRTData->apsFreeLists[ui32Loop].ui32Addr = psKMHWRTDataSet->apsFreeLists[ui32Loop]->sFreeListFWDevVAddr.ui32Addr;
+               /* invalid initial snapshot value, the snapshot is always taken during first kick
+                * and hence the value get replaced during the first kick anyway. So it's safe to set it 0.
+               */
+               psHWRTData->aui32FreeListHWRSnapshot[ui32Loop] = 0;
+               psHWRTData->bRenderStateNeedsReset = IMG_FALSE;
+       }
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       dllist_add_to_tail(&apsFreeLists[RGXFW_LOCAL_FREELIST]->sNodeHWRTDataHead, &(psKMHWRTDataSet->sNodeHWRTData));
+#endif
+       OSLockRelease(psDevInfo->hLockFreeList);
+
+       {
+               RGXFWIF_RTA_CTL *psRTACtl = &psHWRTData->sRTACtl;
+
+               psRTACtl->ui32RenderTargetIndex = 0;
+               psRTACtl->ui32ActiveRenderTargets = 0;
+               psRTACtl->sValidRenderTargets.ui32Addr = 0;
+               psRTACtl->sRTANumPartialRenders.ui32Addr = 0;
+               psRTACtl->ui32MaxRTs = (IMG_UINT32) ui16MaxRTs;
+
+               if (ui16MaxRTs > 1)
+               {
+                       /* Allocate memory for the checks */
+                       PDUMPCOMMENT(psDeviceNode, "Allocate memory for shadow render target cache");
+                       eError = DevmemFwAllocate(      psDevInfo,
+                                                                               ui16MaxRTs * sizeof(IMG_UINT32),
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                                               PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                                               PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                                                               PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                                               PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                                               "FwShadowRTCache",
+                                                                               &psRTArrayFwMemDesc);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "%s: Failed to allocate %u bytes for render target array (%s)",
+                                               __func__,
+                                               ui16MaxRTs, PVRSRVGetErrorString(eError)));
+                               goto FWAllocateRTArryError;
+                       }
+
+                       psKMHWRTDataSet->psRTArrayFwMemDesc = psRTArrayFwMemDesc;
+
+                       eError = RGXSetFirmwareAddress( &psRTACtl->sValidRenderTargets,
+                                                                       psRTArrayFwMemDesc,
+                                                                       0,
+                                                                       RFW_FWADDR_FLAG_NONE    );
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:2", FWAllocateRTArryFwAddrError);
+
+                       /* Allocate memory for the checks */
+                       PDUMPCOMMENT(psDeviceNode, "Allocate memory for tracking renders accumulation");
+                       eError = DevmemFwAllocate(psDevInfo,
+                                                 ui16MaxRTs * sizeof(IMG_UINT32),
+                                                         PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                         PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                                         PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                         PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                         PVRSRV_MEMALLOCFLAG_GPU_UNCACHED |
+                                                         PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                         PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                         "FwRendersAccumulation",
+                                                         &psRendersAccArrayFwMemDesc);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "%s: Failed to allocate %u bytes for render target array (%s) (renders accumulation)",
+                                               __func__,
+                                               ui16MaxRTs, PVRSRVGetErrorString(eError)));
+                               goto FWAllocateRTAccArryError;
+                       }
+
+                       psKMHWRTDataSet->psRendersAccArrayFwMemDesc = psRendersAccArrayFwMemDesc;
+
+                       eError = RGXSetFirmwareAddress( &psRTACtl->sRTANumPartialRenders,
+                                                                       psRendersAccArrayFwMemDesc,
+                                                                       0,
+                                                                       RFW_FWADDR_FLAG_NONE    );
+                       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress:3", FWAllocRTAccArryFwAddrError);
+               }
+       }
+
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump HWRTData 0x%08X", psKMHWRTDataSet->sHWRTDataFwAddr.ui32Addr);
+       DevmemPDumpLoadMem(psKMHWRTDataSet->psHWRTDataFwMemDesc, 0, sizeof(*psHWRTData), PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       DevmemReleaseCpuVirtAddr(psKMHWRTDataSet->psHWRTDataFwMemDesc);
+       return PVRSRV_OK;
+
+FWAllocRTAccArryFwAddrError:
+       DevmemFwUnmapAndFree(psDevInfo, psRendersAccArrayFwMemDesc);
+FWAllocateRTAccArryError:
+       RGXUnsetFirmwareAddress(psRTArrayFwMemDesc);
+FWAllocateRTArryFwAddrError:
+       DevmemFwUnmapAndFree(psDevInfo, psRTArrayFwMemDesc);
+FWAllocateRTArryError:
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+       {
+               PVR_ASSERT(psKMHWRTDataSet->apsFreeLists[ui32Loop]->ui32RefCount > 0);
+               psKMHWRTDataSet->apsFreeLists[ui32Loop]->ui32RefCount--;
+       }
+       OSLockRelease(psDevInfo->hLockFreeList);
+       DevmemReleaseCpuVirtAddr(psKMHWRTDataSet->psHWRTDataFwMemDesc);
+FWRTDataCpuMapError:
+       RGXUnsetFirmwareAddress(psKMHWRTDataSet->psHWRTDataFwMemDesc);
+FWRTDataFwAddrError:
+       DevmemFwUnmapAndFree(psDevInfo, psKMHWRTDataSet->psHWRTDataFwMemDesc);
+FWRTDataAllocateError:
+       *ppsKMHWRTDataSet = NULL;
+       OSFreeMem(psKMHWRTDataSet);
+
+AllocError:
+       return eError;
+}
+
+/* Destroy HWRTDataSet */
+static PVRSRV_ERROR RGXDestroyHWRTData_aux(RGX_KM_HW_RT_DATASET *psKMHWRTDataSet)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       IMG_UINT32 ui32Loop;
+
+       PVR_ASSERT(psKMHWRTDataSet);
+
+       psDevInfo = psKMHWRTDataSet->psDeviceNode->pvDevice;
+
+       if (psKMHWRTDataSet->psRTArrayFwMemDesc)
+       {
+               RGXUnsetFirmwareAddress(psKMHWRTDataSet->psRTArrayFwMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psKMHWRTDataSet->psRTArrayFwMemDesc);
+       }
+
+       if (psKMHWRTDataSet->psRendersAccArrayFwMemDesc)
+       {
+               RGXUnsetFirmwareAddress(psKMHWRTDataSet->psRendersAccArrayFwMemDesc);
+               DevmemFwUnmapAndFree(psDevInfo, psKMHWRTDataSet->psRendersAccArrayFwMemDesc);
+       }
+
+       /* Decrease freelist refcount */
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       for (ui32Loop = 0; ui32Loop < RGXFW_MAX_FREELISTS; ui32Loop++)
+       {
+               PVR_ASSERT(psKMHWRTDataSet->apsFreeLists[ui32Loop]->ui32RefCount > 0);
+               psKMHWRTDataSet->apsFreeLists[ui32Loop]->ui32RefCount--;
+       }
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       dllist_remove_node(&psKMHWRTDataSet->sNodeHWRTData);
+#endif
+       OSLockRelease(psDevInfo->hLockFreeList);
+
+       /* Freeing the memory has to happen _after_ removing the HWRTData from the freelist
+        * otherwise we risk traversing the freelist to find a pointer from a freed data structure */
+       RGXUnsetFirmwareAddress(psKMHWRTDataSet->psHWRTDataFwMemDesc);
+       DevmemFwUnmapAndFree(psDevInfo, psKMHWRTDataSet->psHWRTDataFwMemDesc);
+
+       OSFreeMem(psKMHWRTDataSet);
+
+       return PVRSRV_OK;
+}
+
+/* Create set of HWRTData(s) and bind it with a shared FW HWRTDataCommon */
+PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA      *psConnection,
+               PVRSRV_DEVICE_NODE      *psDeviceNode,
+               IMG_DEV_VIRTADDR        psVHeapTableDevVAddr,
+               IMG_DEV_VIRTADDR                asPMDataDevVAddr[RGXMKIF_NUM_RTDATAS],
+               IMG_DEV_VIRTADDR        asPMSecureDataDevVAddr[RGXMKIF_NUM_RTDATAS],
+               RGX_FREELIST               *apsFreeLists[RGXMKIF_NUM_RTDATA_FREELISTS],
+               IMG_UINT32                ui32ScreenPixelMax,
+               IMG_UINT64                ui64PPPMultiSampleCtl,
+               IMG_UINT32                ui32TEStride,
+               IMG_DEV_VIRTADDR          asTailPtrsDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+               IMG_UINT32                ui32TPCSize,
+               IMG_UINT32                ui32TEScreen,
+               IMG_UINT32                ui32TEAA,
+               IMG_UINT32                ui32TEMTILE1,
+               IMG_UINT32                ui32TEMTILE2,
+               IMG_UINT32                ui32RgnStride,
+               IMG_UINT32                ui32ISPMergeLowerX,
+               IMG_UINT32                ui32ISPMergeLowerY,
+               IMG_UINT32                ui32ISPMergeUpperX,
+               IMG_UINT32                ui32ISPMergeUpperY,
+               IMG_UINT32                ui32ISPMergeScaleX,
+               IMG_UINT32                ui32ISPMergeScaleY,
+               IMG_UINT16                ui16MaxRTs,
+               RGX_KM_HW_RT_DATASET     *pasKMHWRTDataSet[RGXMKIF_NUM_RTDATAS])
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32RTDataID;
+       PVRSRV_RGXDEV_INFO              *psDevInfo = psDeviceNode->pvDevice;
+
+       RGX_HWRTDATA_COMMON_COOKIE      *psHWRTDataCommonCookie;
+       RGXFWIF_HWRTDATA_COMMON         *psHWRTDataCommon;
+       DEVMEM_MEMDESC                          *psHWRTDataCommonFwMemDesc;
+       RGXFWIF_DEV_VIRTADDR            sHWRTDataCommonFwAddr;
+
+       /* Prepare KM cleanup object for HWRTDataCommon FW object */
+       psHWRTDataCommonCookie = OSAllocZMem(sizeof(*psHWRTDataCommonCookie));
+       if (psHWRTDataCommonCookie == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto err_HWRTDataCommonCookieAlloc;
+       }
+
+       /*
+        * This FW common context is only mapped into kernel for initialisation.
+        * Otherwise this allocation is only used by the FW.
+        * Therefore the GPU cache doesn't need coherency, and write-combine will
+        * suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+        */
+       eError = DevmemFwAllocate(psDevInfo,
+                       sizeof(RGXFWIF_HWRTDATA_COMMON),
+                       RGX_FWCOMCTX_ALLOCFLAGS,
+                       "FwHWRTDataCommon",
+                       &psHWRTDataCommonFwMemDesc);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: DevmemAllocate for FwHWRTDataCommon failed", __func__));
+               goto err_HWRTDataCommonAlloc;
+       }
+       eError = RGXSetFirmwareAddress(&sHWRTDataCommonFwAddr, psHWRTDataCommonFwMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", err_HWRTDataCommonFwAddr);
+
+       eError = DevmemAcquireCpuVirtAddr(psHWRTDataCommonFwMemDesc, (void **)&psHWRTDataCommon);
+       PVR_LOG_GOTO_IF_ERROR(eError, "DevmemAcquireCpuVirtAddr", err_HWRTDataCommonVA);
+
+       psHWRTDataCommon->ui32ScreenPixelMax    = ui32ScreenPixelMax;
+       psHWRTDataCommon->ui64PPPMultiSampleCtl = ui64PPPMultiSampleCtl;
+       psHWRTDataCommon->ui32TEStride          = ui32TEStride;
+       psHWRTDataCommon->ui32TPCSize           = ui32TPCSize;
+       psHWRTDataCommon->ui32TEScreen          = ui32TEScreen;
+       psHWRTDataCommon->ui32TEAA              = ui32TEAA;
+       psHWRTDataCommon->ui32TEMTILE1          = ui32TEMTILE1;
+       psHWRTDataCommon->ui32TEMTILE2          = ui32TEMTILE2;
+       psHWRTDataCommon->ui32RgnStride         = ui32RgnStride; /* Region stride in Bytes */
+       psHWRTDataCommon->ui32ISPMergeLowerX    = ui32ISPMergeLowerX;
+       psHWRTDataCommon->ui32ISPMergeLowerY    = ui32ISPMergeLowerY;
+       psHWRTDataCommon->ui32ISPMergeUpperX    = ui32ISPMergeUpperX;
+       psHWRTDataCommon->ui32ISPMergeUpperY    = ui32ISPMergeUpperY;
+       psHWRTDataCommon->ui32ISPMergeScaleX    = ui32ISPMergeScaleX;
+       psHWRTDataCommon->ui32ISPMergeScaleY    = ui32ISPMergeScaleY;
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump HWRTDataCommon");
+       DevmemPDumpLoadMem(psHWRTDataCommonFwMemDesc, 0, sizeof(*psHWRTDataCommon), PDUMP_FLAGS_CONTINUOUS);
+#endif
+       DevmemReleaseCpuVirtAddr(psHWRTDataCommonFwMemDesc);
+
+       psHWRTDataCommonCookie->ui32RefCount = 0;
+       psHWRTDataCommonCookie->psHWRTDataCommonFwMemDesc = psHWRTDataCommonFwMemDesc;
+       psHWRTDataCommonCookie->sHWRTDataCommonFwAddr = sHWRTDataCommonFwAddr;
+
+       /* Here we are creating a set of HWRTData(s)
+          the number of elements in the set equals RGXMKIF_NUM_RTDATAS.
+       */
+
+       for (ui32RTDataID = 0; ui32RTDataID < RGXMKIF_NUM_RTDATAS; ui32RTDataID++)
+       {
+               eError = RGXCreateHWRTData_aux(
+                       psConnection,
+                       psDeviceNode,
+                       psVHeapTableDevVAddr,
+                       asPMDataDevVAddr[ui32RTDataID],
+                       asPMSecureDataDevVAddr[ui32RTDataID],
+                       &apsFreeLists[(ui32RTDataID % RGXMKIF_NUM_GEOMDATAS) * RGXFW_MAX_FREELISTS],
+                       asTailPtrsDevVAddr[ui32RTDataID % RGXMKIF_NUM_GEOMDATAS],
+                       ui16MaxRTs,
+                       psHWRTDataCommonCookie,
+                       &pasKMHWRTDataSet[ui32RTDataID]);
+
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to create HWRTData [slot %u] (%s)",
+                                       __func__,
+                                       ui32RTDataID,
+                                       PVRSRVGetErrorString(eError)));
+                       goto err_HWRTDataAlloc;
+               }
+               psHWRTDataCommonCookie->ui32RefCount += 1;
+       }
+
+       return PVRSRV_OK;
+
+err_HWRTDataAlloc:
+       PVR_DPF((PVR_DBG_WARNING, "%s: err_HWRTDataAlloc %u",
+                        __func__, psHWRTDataCommonCookie->ui32RefCount));
+       if (pasKMHWRTDataSet)
+       {
+               for (ui32RTDataID = psHWRTDataCommonCookie->ui32RefCount; ui32RTDataID > 0; ui32RTDataID--)
+               {
+                       if (pasKMHWRTDataSet[ui32RTDataID-1] != NULL)
+                       {
+                               RGXDestroyHWRTData_aux(pasKMHWRTDataSet[ui32RTDataID-1]);
+                               pasKMHWRTDataSet[ui32RTDataID-1] = NULL;
+                       }
+               }
+       }
+err_HWRTDataCommonVA:
+       RGXUnsetFirmwareAddress(psHWRTDataCommonFwMemDesc);
+err_HWRTDataCommonFwAddr:
+       DevmemFwUnmapAndFree(psDevInfo, psHWRTDataCommonFwMemDesc);
+err_HWRTDataCommonAlloc:
+       OSFreeMem(psHWRTDataCommonCookie);
+err_HWRTDataCommonCookieAlloc:
+
+       return eError;
+}
+
+/* Destroy a single instance of HWRTData.
+   Additionally, destroy the HWRTDataCommon{Cookie} objects
+   when it is the last HWRTData within a corresponding set of HWRTDatas.
+*/
+PVRSRV_ERROR RGXDestroyHWRTDataSet(RGX_KM_HW_RT_DATASET *psKMHWRTDataSet)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo;
+       PVRSRV_DEVICE_NODE *psDevNode;
+       PVRSRV_ERROR eError;
+       PRGXFWIF_HWRTDATA psHWRTData;
+       RGX_HWRTDATA_COMMON_COOKIE *psCommonCookie;
+
+       PVR_ASSERT(psKMHWRTDataSet);
+
+       psDevNode = psKMHWRTDataSet->psDeviceNode;
+       psDevInfo = psDevNode->pvDevice;
+
+       eError = RGXSetFirmwareAddress(&psHWRTData,
+                                      psKMHWRTDataSet->psHWRTDataFwMemDesc, 0,
+                                      RFW_FWADDR_NOREF_FLAG);
+       PVR_RETURN_IF_ERROR(eError);
+
+       /* Cleanup HWRTData */
+       eError = RGXFWRequestHWRTDataCleanUp(psDevNode, psHWRTData);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       psCommonCookie = psKMHWRTDataSet->psHWRTDataCommonCookie;
+
+       RGXDestroyHWRTData_aux(psKMHWRTDataSet);
+
+       /* We've got past potential PVRSRV_ERROR_RETRY events, so we are sure
+          that the HWRTDATA instance will be destroyed during this call.
+          Consequently, we decrease the ref count for HWRTDataCommonCookie.
+
+          NOTE: This ref count does not require locks or atomics.
+          -------------------------------------------------------
+            HWRTDatas bound into one pair are always destroyed sequentially,
+            within a single loop on the Client side.
+            The Common/Cookie objects always belong to only one pair of
+            HWRTDatas, and ref count is used to ensure that the Common/Cookie
+            objects will be destroyed after destruction of all HWRTDatas
+            within a single pair.
+       */
+       psCommonCookie->ui32RefCount--;
+
+       /* When ref count for HWRTDataCommonCookie hits ZERO
+        * we have to destroy the HWRTDataCommon [FW object] and the cookie
+        * [KM object] afterwards. */
+       if (psCommonCookie->ui32RefCount == 0)
+       {
+               RGXUnsetFirmwareAddress(psCommonCookie->psHWRTDataCommonFwMemDesc);
+
+               /* We don't need to flush the SLC before freeing.
+                * FW RequestCleanUp has already done that for HWRTData, so we're fine
+                * now. */
+
+               DevmemFwUnmapAndFree(psDevNode->pvDevice,
+                                    psCommonCookie->psHWRTDataCommonFwMemDesc);
+               OSFreeMem(psCommonCookie);
+       }
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR RGXCreateFreeList(CONNECTION_DATA      *psConnection,
+                               PVRSRV_DEVICE_NODE      *psDeviceNode,
+                               IMG_HANDLE                      hMemCtxPrivData,
+                               IMG_UINT32                      ui32MaxFLPages,
+                               IMG_UINT32                      ui32InitFLPages,
+                               IMG_UINT32                      ui32GrowFLPages,
+                               IMG_UINT32           ui32GrowParamThreshold,
+                               RGX_FREELIST                    *psGlobalFreeList,
+                               IMG_BOOL                                bCheckFreelist,
+                               IMG_DEV_VIRTADDR                sFreeListBaseDevVAddr,
+                               IMG_DEV_VIRTADDR                sFreeListStateDevVAddr,
+                               PMR                                     *psFreeListPMR,
+                               IMG_DEVMEM_OFFSET_T     uiFreeListPMROffset,
+                               PMR                                     *psFreeListStatePMR,
+                               IMG_DEVMEM_OFFSET_T     uiFreeListStatePMROffset,
+                               RGX_FREELIST                    **ppsFreeList)
+{
+       PVRSRV_ERROR                            eError;
+       RGXFWIF_FREELIST                        *psFWFreeList;
+       DEVMEM_MEMDESC                          *psFWFreelistMemDesc;
+       RGX_FREELIST                            *psFreeList;
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+
+       if (OSGetPageShift() > RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT)
+       {
+               IMG_UINT32 ui32Size, ui32NewInitFLPages, ui32NewMaxFLPages, ui32NewGrowFLPages;
+
+               /* Round up number of FL pages to the next multiple of the OS page size */
+
+               ui32Size = ui32InitFLPages << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+               ui32Size = PVR_ALIGN(ui32Size, (IMG_DEVMEM_SIZE_T)OSGetPageSize());
+               ui32NewInitFLPages = ui32Size >> RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+
+               ui32Size = ui32GrowFLPages << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+               ui32Size = PVR_ALIGN(ui32Size, (IMG_DEVMEM_SIZE_T)OSGetPageSize());
+               ui32NewGrowFLPages = ui32Size >> RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+
+               ui32Size = ui32MaxFLPages << RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+               ui32Size = PVR_ALIGN(ui32Size, (IMG_DEVMEM_SIZE_T)OSGetPageSize());
+               ui32NewMaxFLPages = ui32Size >> RGX_BIF_PM_PHYSICAL_PAGE_ALIGNSHIFT;
+
+               PVR_DPF((PVR_DBG_WARNING, "%s: Increased number of PB pages: Init %u -> %u, Grow %u -> %u, Max %u -> %u",
+                                __func__, ui32InitFLPages, ui32NewInitFLPages, ui32GrowFLPages, ui32NewGrowFLPages, ui32MaxFLPages, ui32NewMaxFLPages));
+
+               ui32InitFLPages = ui32NewInitFLPages;
+               ui32GrowFLPages = ui32NewGrowFLPages;
+               ui32MaxFLPages = ui32NewMaxFLPages;
+       }
+
+       /* Allocate kernel freelist struct */
+       psFreeList = OSAllocZMem(sizeof(*psFreeList));
+       if (psFreeList == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: failed to allocate host data structure",
+                               __func__));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorAllocHost;
+       }
+
+       /*
+        * This FW FreeList context is only mapped into kernel for initialisation
+        * and reconstruction (at other times it is not mapped and only used by the
+        * FW).
+        * Therefore the GPU cache doesn't need coherency, and write-combine will
+        * suffice on the CPU side (WC buffer will be flushed at the first TA-kick)
+        */
+       eError = DevmemFwAllocate(psDevInfo,
+                                                       sizeof(*psFWFreeList),
+                                                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                                       PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                                       PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                       "FwFreeList",
+                                                       &psFWFreelistMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: DevmemAllocate for RGXFWIF_FREELIST failed",
+                               __func__));
+               goto FWFreeListAlloc;
+       }
+
+       /* Initialise host data structures */
+       psFreeList->psDevInfo = psDevInfo;
+       psFreeList->psConnection = psConnection;
+       psFreeList->psFreeListPMR = psFreeListPMR;
+       psFreeList->uiFreeListPMROffset = uiFreeListPMROffset;
+       psFreeList->psFreeListStatePMR = psFreeListStatePMR;
+       psFreeList->uiFreeListStatePMROffset = uiFreeListStatePMROffset;
+       psFreeList->psFWFreelistMemDesc = psFWFreelistMemDesc;
+       eError = RGXSetFirmwareAddress(&psFreeList->sFreeListFWDevVAddr, psFWFreelistMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", ErrorSetFwAddr);
+
+       /* psFreeList->ui32FreelistID set below with lock... */
+       psFreeList->ui32FreelistGlobalID = (psGlobalFreeList ? psGlobalFreeList->ui32FreelistID : 0);
+       psFreeList->ui32MaxFLPages = ui32MaxFLPages;
+       psFreeList->ui32InitFLPages = ui32InitFLPages;
+       psFreeList->ui32GrowFLPages = ui32GrowFLPages;
+       psFreeList->ui32CurrentFLPages = 0;
+       psFreeList->ui32ReadyFLPages = 0;
+       psFreeList->ui32GrowThreshold = ui32GrowParamThreshold;
+       psFreeList->ui64FreelistChecksum = 0;
+       psFreeList->ui32RefCount = 0;
+       psFreeList->bCheckFreelist = bCheckFreelist;
+       dllist_init(&psFreeList->sMemoryBlockHead);
+       dllist_init(&psFreeList->sMemoryBlockInitHead);
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       dllist_init(&psFreeList->sNodeHWRTDataHead);
+#endif
+       psFreeList->ownerPid = OSGetCurrentClientProcessIDKM();
+
+
+       /* Add to list of freelists */
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       psFreeList->ui32FreelistID = psDevInfo->ui32FreelistCurrID++;
+       dllist_add_to_tail(&psDevInfo->sFreeListHead, &psFreeList->sNode);
+       OSLockRelease(psDevInfo->hLockFreeList);
+
+
+       /* Initialise FW data structure */
+       eError = DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
+       PVR_LOG_GOTO_IF_ERROR(eError, "Devmem AcquireCpuVirtAddr", FWFreeListCpuMap);
+
+       {
+               const IMG_UINT32 ui32ReadyPages = _CalculateFreelistReadyPages(psFreeList, ui32InitFLPages);
+
+               psFWFreeList->ui32MaxPages = ui32MaxFLPages;
+               psFWFreeList->ui32CurrentPages = ui32InitFLPages - ui32ReadyPages;
+               psFWFreeList->ui32GrowPages = ui32GrowFLPages;
+               psFWFreeList->bUpdatePending = IMG_FALSE;
+               psFWFreeList->ui32UpdateNewPages = 0;
+               psFWFreeList->ui32UpdateNewReadyPages = 0;
+               psFWFreeList->sFreeListBaseDevVAddr = sFreeListBaseDevVAddr;
+#if defined(PM_INTERACTIVE_MODE)
+               psFWFreeList->ui32CurrentStackTop = psFWFreeList->ui32CurrentPages - 1;
+               psFWFreeList->ui64CurrentDevVAddr = (sFreeListBaseDevVAddr.uiAddr +
+                                                ((ui32MaxFLPages - psFWFreeList->ui32CurrentPages) * sizeof(IMG_UINT32))) &
+                                                       ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1);
+#endif
+               psFWFreeList->ui32FreeListID = psFreeList->ui32FreelistID;
+               psFWFreeList->bGrowPending = IMG_FALSE;
+               psFWFreeList->ui32ReadyPages = ui32ReadyPages;
+
+#if defined(SUPPORT_SHADOW_FREELISTS)
+               /* Get the FW Memory Context address... */
+               eError = RGXSetFirmwareAddress(&psFWFreeList->psFWMemContext,
+                                              RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData),
+                                              0, RFW_FWADDR_NOREF_FLAG);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: RGXSetFirmwareAddress for RGXFWIF_FWMEMCONTEXT failed",
+                                       __func__));
+                       DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+                       goto FWFreeListCpuMap;
+               }
+#else
+               PVR_UNREFERENCED_PARAMETER(hMemCtxPrivData);
+#endif
+
+               /*
+                * Only the PM state buffer address is needed which contains the PM
+                * state including the freelist base address.
+                *
+                * Access to the physical PMR will be used to update the contents of the
+                * PM state buffer when PB grow occurs following OOM.
+                */
+               psFWFreeList->sFreeListLastGrowDevVAddr.uiAddr = 0;
+               psFWFreeList->sFreeListStateDevVAddr = sFreeListStateDevVAddr;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "Freelist [%p]: Created: Max pages 0x%08x, Init pages 0x%08x, FL base address 0x%016" IMG_UINT64_FMTSPECx ", Current FL base address 0x%016" IMG_UINT64_FMTSPECx ", Current pages %u",
+                       psFreeList,
+                       ui32MaxFLPages,
+                       ui32InitFLPages,
+                       sFreeListBaseDevVAddr.uiAddr,
+                       (sFreeListBaseDevVAddr.uiAddr +
+                ((ui32MaxFLPages - psFWFreeList->ui32CurrentPages) * sizeof(IMG_UINT32))) &
+                       ~((IMG_UINT64)RGX_BIF_PM_FREELIST_BASE_ADDR_ALIGNSIZE-1),
+                       psFWFreeList->ui32CurrentPages - 1));
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump FW FreeList");
+       DevmemPDumpLoadMem(psFreeList->psFWFreelistMemDesc, 0, sizeof(*psFWFreeList), PDUMP_FLAGS_CONTINUOUS);
+
+#if defined(PM_INTERACTIVE_MODE)
+       /*
+        * Separate dump of the Freelist's number of Pages and stack pointer.
+        * This allows to easily modify the PB size in the out2.txt files.
+        */
+       PDUMPCOMMENT(psDeviceNode, "FreeList TotalPages");
+       DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
+                                                       offsetof(RGXFWIF_FREELIST, ui32CurrentPages),
+                                                       psFWFreeList->ui32CurrentPages,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+       PDUMPCOMMENT(psDeviceNode, "FreeList StackPointer");
+       DevmemPDumpLoadMemValue32(psFreeList->psFWFreelistMemDesc,
+                                                       offsetof(RGXFWIF_FREELIST, ui32CurrentStackTop),
+                                                       psFWFreeList->ui32CurrentStackTop,
+                                                       PDUMP_FLAGS_CONTINUOUS);
+#endif
+#endif
+       DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+       /* Add initial PB block */
+       eError = RGXGrowFreeList(psFreeList,
+                                ui32InitFLPages,
+                                &psFreeList->sMemoryBlockInitHead);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: failed to allocate initial memory block for free list 0x%016" IMG_UINT64_FMTSPECx " (%s)",
+                               __func__,
+                               sFreeListBaseDevVAddr.uiAddr,
+                               PVRSRVGetErrorString(eError)));
+               goto FWFreeListCpuMap;
+       }
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+       /* Update Stats */
+       PVRSRVStatsUpdateFreelistStats(1, /* Add 1 to the appropriate counter (Requests by App)*/
+                                      0,
+                                      psFreeList->ui32InitFLPages,
+                                      psFreeList->ui32NumHighPages,
+                                      psFreeList->ownerPid);
+
+#endif
+
+       /* return values */
+       *ppsFreeList = psFreeList;
+
+       return PVRSRV_OK;
+
+       /* Error handling */
+
+FWFreeListCpuMap:
+       /* Remove freelists from list  */
+       OSLockAcquire(psDevInfo->hLockFreeList);
+       dllist_remove_node(&psFreeList->sNode);
+       OSLockRelease(psDevInfo->hLockFreeList);
+       RGXUnsetFirmwareAddress(psFWFreelistMemDesc);
+
+ErrorSetFwAddr:
+       DevmemFwUnmapAndFree(psDevInfo, psFWFreelistMemDesc);
+
+FWFreeListAlloc:
+       OSFreeMem(psFreeList);
+
+ErrorAllocHost:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+
+/*
+       RGXDestroyFreeList
+*/
+PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList)
+{
+       PVRSRV_ERROR eError;
+       IMG_UINT32 ui32RefCount;
+
+       PVR_ASSERT(psFreeList);
+
+       OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+       ui32RefCount = psFreeList->ui32RefCount;
+       OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+       if (ui32RefCount != 0)
+       {
+               /* Freelist still busy */
+               return PVRSRV_ERROR_RETRY;
+       }
+
+       /* Freelist is not in use => start firmware cleanup */
+       eError = RGXFWRequestFreeListCleanUp(psFreeList->psDevInfo,
+                                                                                psFreeList->sFreeListFWDevVAddr);
+       if (eError != PVRSRV_OK)
+       {
+               /* Can happen if the firmware took too long to handle the cleanup request,
+                * or if SLC-flushes didn't went through (due to some GPU lockup) */
+               return eError;
+       }
+
+       /* Remove FreeList from linked list before we destroy it... */
+       OSLockAcquire(psFreeList->psDevInfo->hLockFreeList);
+       dllist_remove_node(&psFreeList->sNode);
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       /* Confirm all HWRTData nodes are freed before releasing freelist */
+       PVR_ASSERT(dllist_is_empty(&psFreeList->sNodeHWRTDataHead));
+#endif
+       OSLockRelease(psFreeList->psDevInfo->hLockFreeList);
+
+#if defined(PM_INTERACTIVE_MODE)
+       if (psFreeList->bCheckFreelist)
+       {
+               RGXFWIF_FREELIST  *psFWFreeList;
+               IMG_UINT64        ui32CurrentStackTop;
+               IMG_UINT64        ui64CheckSum;
+
+               /* Get the current stack pointer for this free list */
+               DevmemAcquireCpuVirtAddr(psFreeList->psFWFreelistMemDesc, (void **)&psFWFreeList);
+               ui32CurrentStackTop = psFWFreeList->ui32CurrentStackTop;
+               DevmemReleaseCpuVirtAddr(psFreeList->psFWFreelistMemDesc);
+
+               if (ui32CurrentStackTop == psFreeList->ui32CurrentFLPages-1)
+               {
+                       /* Do consistency tests (as the list is fully populated) */
+                       _CheckFreelist(psFreeList, psFreeList->ui32CurrentFLPages + psFreeList->ui32ReadyFLPages, psFreeList->ui64FreelistChecksum, &ui64CheckSum);
+               }
+               else
+               {
+                       /* Check for duplicate pages, but don't check the checksum as the list is not fully populated */
+                       _CheckFreelist(psFreeList, ui32CurrentStackTop+1, 0, &ui64CheckSum);
+               }
+       }
+#endif
+
+       /* Destroy FW structures */
+       RGXUnsetFirmwareAddress(psFreeList->psFWFreelistMemDesc);
+       DevmemFwUnmapAndFree(psFreeList->psDevInfo, psFreeList->psFWFreelistMemDesc);
+
+       /* Remove grow shrink blocks */
+       while (!dllist_is_empty(&psFreeList->sMemoryBlockHead))
+       {
+               eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockHead, psFreeList);
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
+
+       /* Remove initial PB block */
+       eError = RGXShrinkFreeList(&psFreeList->sMemoryBlockInitHead, psFreeList);
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+       /* consistency checks */
+       PVR_ASSERT(dllist_is_empty(&psFreeList->sMemoryBlockInitHead));
+       PVR_ASSERT(psFreeList->ui32CurrentFLPages == 0);
+
+       /* free Freelist */
+       OSFreeMem(psFreeList);
+
+       return eError;
+}
+
+
+/*
+       RGXCreateZSBuffer
+*/
+PVRSRV_ERROR RGXCreateZSBufferKM(CONNECTION_DATA * psConnection,
+                                 PVRSRV_DEVICE_NODE    *psDeviceNode,
+                                 DEVMEMINT_RESERVATION *psReservation,
+                                 PMR                                   *psPMR,
+                                 PVRSRV_MEMALLOCFLAGS_T                uiMapFlags,
+                                 RGX_ZSBUFFER_DATA **ppsZSBuffer)
+{
+       PVRSRV_ERROR                            eError;
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+       RGXFWIF_PRBUFFER                        *psFWZSBuffer;
+       RGX_ZSBUFFER_DATA                       *psZSBuffer;
+       DEVMEM_MEMDESC                          *psFWZSBufferMemDesc;
+       IMG_BOOL                                        bOnDemand = PVRSRV_CHECK_ON_DEMAND(uiMapFlags) ? IMG_TRUE : IMG_FALSE;
+
+       /* Allocate host data structure */
+       psZSBuffer = OSAllocZMem(sizeof(*psZSBuffer));
+       if (psZSBuffer == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate cleanup data structure for ZS-Buffer",
+                               __func__));
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto ErrorAllocCleanup;
+       }
+
+       /* Populate Host data */
+       psZSBuffer->psDevInfo = psDevInfo;
+       psZSBuffer->psReservation = psReservation;
+       psZSBuffer->psPMR = psPMR;
+       psZSBuffer->uiMapFlags = uiMapFlags;
+       psZSBuffer->ui32RefCount = 0;
+       psZSBuffer->bOnDemand = bOnDemand;
+       if (bOnDemand)
+       {
+               /* psZSBuffer->ui32ZSBufferID set below with lock... */
+               psZSBuffer->psMapping = NULL;
+
+               OSLockAcquire(psDevInfo->hLockZSBuffer);
+               psZSBuffer->ui32ZSBufferID = psDevInfo->ui32ZSBufferCurrID++;
+               dllist_add_to_tail(&psDevInfo->sZSBufferHead, &psZSBuffer->sNode);
+               OSLockRelease(psDevInfo->hLockZSBuffer);
+       }
+
+       /* Allocate firmware memory for ZS-Buffer. */
+       PDUMPCOMMENT(psDeviceNode, "Allocate firmware ZS-Buffer data structure");
+       eError = DevmemFwAllocate(psDevInfo,
+                                                       sizeof(*psFWZSBuffer),
+                                                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(PMMETA_PROTECT) |
+                                                       PVRSRV_MEMALLOCFLAG_DEVICE_FLAG(FIRMWARE_CACHED) |
+                                                       PVRSRV_MEMALLOCFLAG_ZERO_ON_ALLOC |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_READABLE |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_WRITEABLE |
+                                                       PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_READABLE |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
+                                                       PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC |
+                                                       PVRSRV_MEMALLOCFLAG_KERNEL_CPU_MAPPABLE |
+                                                       PVRSRV_MEMALLOCFLAG_PHYS_HEAP_HINT(FW_MAIN),
+                                                       "FwZSBuffer",
+                                                       &psFWZSBufferMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate firmware ZS-Buffer (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto ErrorAllocFWZSBuffer;
+       }
+       psZSBuffer->psFWZSBufferMemDesc = psFWZSBufferMemDesc;
+
+       /* Temporarily map the firmware render context to the kernel. */
+       eError = DevmemAcquireCpuVirtAddr(psFWZSBufferMemDesc,
+                                         (void **)&psFWZSBuffer);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map firmware ZS-Buffer (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto ErrorAcquireFWZSBuffer;
+       }
+
+       /* Populate FW ZS-Buffer data structure */
+       psFWZSBuffer->bOnDemand = bOnDemand;
+       psFWZSBuffer->eState = (bOnDemand) ? RGXFWIF_PRBUFFER_UNBACKED : RGXFWIF_PRBUFFER_BACKED;
+       psFWZSBuffer->ui32BufferID = psZSBuffer->ui32ZSBufferID;
+
+       /* Get firmware address of ZS-Buffer. */
+       eError = RGXSetFirmwareAddress(&psZSBuffer->sZSBufferFWDevVAddr, psFWZSBufferMemDesc, 0, RFW_FWADDR_FLAG_NONE);
+       PVR_LOG_GOTO_IF_ERROR(eError, "RGXSetFirmwareAddress", ErrorSetFwAddr);
+
+       /* Dump the ZS-Buffer and the memory content */
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump firmware ZS-Buffer");
+       DevmemPDumpLoadMem(psFWZSBufferMemDesc, 0, sizeof(*psFWZSBuffer), PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       /* Release address acquired above. */
+       DevmemReleaseCpuVirtAddr(psFWZSBufferMemDesc);
+
+
+       /* define return value */
+       *ppsZSBuffer = psZSBuffer;
+
+       PVR_DPF((PVR_DBG_MESSAGE, "ZS-Buffer [%p] created (%s)",
+                                                       psZSBuffer,
+                                                       (bOnDemand) ? "On-Demand": "Up-front"));
+
+       psZSBuffer->owner=OSGetCurrentClientProcessIDKM();
+
+       return PVRSRV_OK;
+
+       /* error handling */
+
+ErrorSetFwAddr:
+       DevmemReleaseCpuVirtAddr(psFWZSBufferMemDesc);
+ErrorAcquireFWZSBuffer:
+       DevmemFwUnmapAndFree(psDevInfo, psFWZSBufferMemDesc);
+
+ErrorAllocFWZSBuffer:
+       OSFreeMem(psZSBuffer);
+
+ErrorAllocCleanup:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+
+/*
+       RGXDestroyZSBuffer
+*/
+PVRSRV_ERROR RGXDestroyZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer)
+{
+       POS_LOCK hLockZSBuffer;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psZSBuffer);
+       hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
+
+       /* Request ZS Buffer cleanup */
+       eError = RGXFWRequestZSBufferCleanUp(psZSBuffer->psDevInfo,
+                                                                               psZSBuffer->sZSBufferFWDevVAddr);
+       if (eError == PVRSRV_OK)
+       {
+               /* Free the firmware render context. */
+               RGXUnsetFirmwareAddress(psZSBuffer->psFWZSBufferMemDesc);
+               DevmemFwUnmapAndFree(psZSBuffer->psDevInfo, psZSBuffer->psFWZSBufferMemDesc);
+
+               /* Remove Deferred Allocation from list */
+               if (psZSBuffer->bOnDemand)
+               {
+                       OSLockAcquire(hLockZSBuffer);
+                       PVR_ASSERT(dllist_node_is_in_list(&psZSBuffer->sNode));
+                       dllist_remove_node(&psZSBuffer->sNode);
+                       OSLockRelease(hLockZSBuffer);
+               }
+
+               PVR_ASSERT(psZSBuffer->ui32RefCount == 0);
+
+               PVR_DPF((PVR_DBG_MESSAGE, "ZS-Buffer [%p] destroyed", psZSBuffer));
+
+               /* Free ZS-Buffer host data structure */
+               OSFreeMem(psZSBuffer);
+
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR
+RGXBackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
+{
+       POS_LOCK hLockZSBuffer;
+       PVRSRV_ERROR eError;
+
+       if (!psZSBuffer)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (!psZSBuffer->bOnDemand)
+       {
+               /* Only deferred allocations can be populated */
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "ZS Buffer [%p, ID=0x%08x]: Physical backing requested",
+                                                               psZSBuffer,
+                                                               psZSBuffer->ui32ZSBufferID));
+       hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
+
+       OSLockAcquire(hLockZSBuffer);
+
+       if (psZSBuffer->ui32RefCount == 0)
+       {
+               if (psZSBuffer->bOnDemand)
+               {
+                       IMG_HANDLE hDevmemHeap = (IMG_HANDLE)NULL;
+
+                       PVR_ASSERT(psZSBuffer->psMapping == NULL);
+
+                       /* Get Heap */
+                       eError = DevmemServerGetHeapHandle(psZSBuffer->psReservation, &hDevmemHeap);
+                       PVR_ASSERT(psZSBuffer->psMapping == NULL);
+                       if (unlikely(hDevmemHeap == (IMG_HANDLE)NULL))
+                       {
+                               OSLockRelease(hLockZSBuffer);
+                               return PVRSRV_ERROR_INVALID_HEAP;
+                       }
+
+                       eError = DevmemIntMapPMR(hDevmemHeap,
+                                                                       psZSBuffer->psReservation,
+                                                                       psZSBuffer->psPMR,
+                                                                       psZSBuffer->uiMapFlags,
+                                                                       &psZSBuffer->psMapping);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "Unable populate ZS Buffer [%p, ID=0x%08x] (%s)",
+                                               psZSBuffer,
+                                               psZSBuffer->ui32ZSBufferID,
+                                               PVRSRVGetErrorString(eError)));
+                               OSLockRelease(hLockZSBuffer);
+                               return eError;
+
+                       }
+                       PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing acquired",
+                                                                               psZSBuffer,
+                                                                               psZSBuffer->ui32ZSBufferID));
+               }
+       }
+
+       /* Increase refcount*/
+       psZSBuffer->ui32RefCount++;
+
+       OSLockRelease(hLockZSBuffer);
+
+       return PVRSRV_OK;
+}
+
+
+PVRSRV_ERROR
+RGXPopulateZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer,
+                                       RGX_POPULATION **ppsPopulation)
+{
+       RGX_POPULATION *psPopulation;
+       PVRSRV_ERROR eError;
+
+       psZSBuffer->ui32NumReqByApp++;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+       PVRSRVStatsUpdateZSBufferStats(1, 0, psZSBuffer->owner);
+#endif
+
+       /* Do the backing */
+       eError = RGXBackingZSBuffer(psZSBuffer);
+       if (eError != PVRSRV_OK)
+       {
+               goto OnErrorBacking;
+       }
+
+       /* Create the handle to the backing */
+       psPopulation = OSAllocMem(sizeof(*psPopulation));
+       if (psPopulation == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto OnErrorAlloc;
+       }
+
+       psPopulation->psZSBuffer = psZSBuffer;
+
+       /* return value */
+       *ppsPopulation = psPopulation;
+
+       return PVRSRV_OK;
+
+OnErrorAlloc:
+       RGXUnbackingZSBuffer(psZSBuffer);
+
+OnErrorBacking:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+PVRSRV_ERROR
+RGXUnbackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer)
+{
+       POS_LOCK hLockZSBuffer;
+       PVRSRV_ERROR eError;
+
+       if (!psZSBuffer)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       PVR_ASSERT(psZSBuffer->ui32RefCount);
+
+       PVR_DPF((PVR_DBG_MESSAGE,
+                       "ZS Buffer [%p, ID=0x%08x]: Physical backing removal requested",
+                                                               psZSBuffer,
+                                                               psZSBuffer->ui32ZSBufferID));
+
+       hLockZSBuffer = psZSBuffer->psDevInfo->hLockZSBuffer;
+
+       OSLockAcquire(hLockZSBuffer);
+
+       if (psZSBuffer->bOnDemand)
+       {
+               if (psZSBuffer->ui32RefCount == 1)
+               {
+                       PVR_ASSERT(psZSBuffer->psMapping);
+
+                       eError = DevmemIntUnmapPMR(psZSBuffer->psMapping);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                               "Unable to unpopulate ZS Buffer [%p, ID=0x%08x] (%s)",
+                                               psZSBuffer,
+                                               psZSBuffer->ui32ZSBufferID,
+                                               PVRSRVGetErrorString(eError)));
+                               OSLockRelease(hLockZSBuffer);
+                               return eError;
+                       }
+
+                       PVR_DPF((PVR_DBG_MESSAGE, "ZS Buffer [%p, ID=0x%08x]: Physical backing removed",
+                                                                               psZSBuffer,
+                                                                               psZSBuffer->ui32ZSBufferID));
+               }
+       }
+
+       /* Decrease refcount*/
+       psZSBuffer->ui32RefCount--;
+
+       OSLockRelease(hLockZSBuffer);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+RGXUnpopulateZSBufferKM(RGX_POPULATION *psPopulation)
+{
+       PVRSRV_ERROR eError;
+
+       if (!psPopulation)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       eError = RGXUnbackingZSBuffer(psPopulation->psZSBuffer);
+       if (eError != PVRSRV_OK)
+       {
+               return eError;
+       }
+
+       OSFreeMem(psPopulation);
+
+       return PVRSRV_OK;
+}
+
+static RGX_ZSBUFFER_DATA *FindZSBuffer(PVRSRV_RGXDEV_INFO *psDevInfo, IMG_UINT32 ui32ZSBufferID)
+{
+       DLLIST_NODE *psNode, *psNext;
+       RGX_ZSBUFFER_DATA *psZSBuffer = NULL;
+
+       OSLockAcquire(psDevInfo->hLockZSBuffer);
+
+       dllist_foreach_node(&psDevInfo->sZSBufferHead, psNode, psNext)
+       {
+               RGX_ZSBUFFER_DATA *psThisZSBuffer = IMG_CONTAINER_OF(psNode, RGX_ZSBUFFER_DATA, sNode);
+
+               if (psThisZSBuffer->ui32ZSBufferID == ui32ZSBufferID)
+               {
+                       psZSBuffer = psThisZSBuffer;
+                       break;
+               }
+       }
+
+       OSLockRelease(psDevInfo->hLockZSBuffer);
+       return psZSBuffer;
+}
+
+void RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                         IMG_UINT32 ui32ZSBufferID)
+{
+       IMG_BOOL bBackingDone = IMG_TRUE;
+       RGX_ZSBUFFER_DATA *psZSBuffer;
+       RGXFWIF_KCCB_CMD sTACCBCmd;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psDevInfo);
+
+       /* scan all deferred allocations */
+       psZSBuffer = FindZSBuffer(psDevInfo, ui32ZSBufferID);
+
+       if (psZSBuffer == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (Populate)",
+                        ui32ZSBufferID));
+
+               return;
+       }
+
+       /* Populate ZLS */
+       eError = RGXBackingZSBuffer(psZSBuffer);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "Populating ZS-Buffer failed with error %u (ID = 0x%08x)",
+                        eError, ui32ZSBufferID));
+               bBackingDone = IMG_FALSE;
+       }
+
+       /* send confirmation */
+       sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_BACKING_UPDATE;
+       sTACCBCmd.uCmdData.sZSBufferBackingData.sZSBufferFWDevVAddr.ui32Addr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
+       sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = bBackingDone;
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                                                       RGXFWIF_DM_GEOM,
+                                                                       &sTACCBCmd,
+                                                                       PDUMP_FLAGS_NONE);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       /* Kernel CCB should never fill up, as the FW is processing them right away  */
+       PVR_ASSERT(eError == PVRSRV_OK);
+
+       psZSBuffer->ui32NumReqByFW++;
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+       PVRSRVStatsUpdateZSBufferStats(0, 1, psZSBuffer->owner);
+#endif
+}
+
+void RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                       IMG_UINT32 ui32ZSBufferID)
+{
+       RGX_ZSBUFFER_DATA *psZSBuffer;
+       RGXFWIF_KCCB_CMD sTACCBCmd;
+       PVRSRV_ERROR eError;
+
+       PVR_ASSERT(psDevInfo);
+
+       /* scan all deferred allocations */
+       psZSBuffer = FindZSBuffer(psDevInfo, ui32ZSBufferID);
+
+       if (psZSBuffer == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "ZS Buffer Lookup for ZS Buffer ID 0x%08x failed (UnPopulate)",
+                        ui32ZSBufferID));
+
+               return;
+       }
+
+       /* Unpopulate ZLS */
+       eError = RGXUnbackingZSBuffer(psZSBuffer);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                        "UnPopulating ZS-Buffer failed with error %u (ID = 0x%08x)",
+                        eError, ui32ZSBufferID));
+               PVR_ASSERT(IMG_FALSE);
+       }
+
+       /* send confirmation */
+       sTACCBCmd.eCmdType = RGXFWIF_KCCB_CMD_ZSBUFFER_UNBACKING_UPDATE;
+       sTACCBCmd.uCmdData.sZSBufferBackingData.sZSBufferFWDevVAddr.ui32Addr = psZSBuffer->sZSBufferFWDevVAddr.ui32Addr;
+       sTACCBCmd.uCmdData.sZSBufferBackingData.bDone = IMG_TRUE;
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psDevInfo,
+                                                                       RGXFWIF_DM_GEOM,
+                                                                       &sTACCBCmd,
+                                                                       PDUMP_FLAGS_NONE);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       /* Kernel CCB should never fill up, as the FW is processing them right away */
+       PVR_ASSERT(eError == PVRSRV_OK);
+}
+
+static
+PVRSRV_ERROR _CreateTAContext(CONNECTION_DATA *psConnection,
+                                                         PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                         SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                         DEVMEM_MEMDESC *psAllocatedMemDesc,
+                                                         IMG_UINT32 ui32AllocatedOffset,
+                                                         DEVMEM_MEMDESC *psFWMemContextMemDesc,
+                                                         IMG_UINT32 ui32Priority,
+                                                         IMG_UINT32 ui32MaxDeadlineMS,
+                                                         IMG_UINT64 ui64RobustnessAddress,
+                                                         RGX_COMMON_CONTEXT_INFO *psInfo,
+                                                         RGX_SERVER_RC_TA_DATA *psTAData,
+                                                         IMG_UINT32 ui32CCBAllocSizeLog2,
+                                                         IMG_UINT32 ui32CCBMaxAllocSizeLog2,
+                                                         IMG_UINT32 ui32ContextFlags)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+
+       /*
+               Allocate device memory for the firmware GPU context suspend state.
+               Note: the FW reads/writes the state to memory by accessing the GPU register interface.
+       */
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware TA context suspend state");
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         sizeof(RGXFWIF_TACTX_STATE),
+                                                         RGX_FWCOMCTX_ALLOCFLAGS,
+                                                         "FwTAContextState",
+                                                         &psTAData->psContextStateMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate firmware GPU context suspend state (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto fail_tacontextsuspendalloc;
+       }
+
+       eError = FWCommonContextAllocate(psConnection,
+                                                                        psDeviceNode,
+                                                                        REQ_TYPE_TA,
+                                                                        RGXFWIF_DM_GEOM,
+                                                                        psServerMMUContext,
+                                                                        psAllocatedMemDesc,
+                                                                        ui32AllocatedOffset,
+                                                                        psFWMemContextMemDesc,
+                                                                        psTAData->psContextStateMemDesc,
+                                                                        ui32CCBAllocSizeLog2 ? ui32CCBAllocSizeLog2 : RGX_TA_CCB_SIZE_LOG2,
+                                                                        ui32CCBMaxAllocSizeLog2 ? ui32CCBMaxAllocSizeLog2 : RGX_TA_CCB_MAX_SIZE_LOG2,
+                                                                        ui32ContextFlags,
+                                                                        ui32Priority,
+                                                                        ui32MaxDeadlineMS,
+                                                                        ui64RobustnessAddress,
+                                                                        psInfo,
+                                                                        &psTAData->psServerCommonContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to init TA fw common context (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto fail_tacommoncontext;
+       }
+
+       /*
+        * Dump the FW 3D context suspend state buffer
+        */
+#if defined(PDUMP)
+       PDUMPCOMMENT(psDeviceNode, "Dump the TA context suspend state buffer");
+       DevmemPDumpLoadMem(psTAData->psContextStateMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_TACTX_STATE),
+                                          PDUMP_FLAGS_CONTINUOUS);
+#endif
+
+       psTAData->ui32Priority = ui32Priority;
+       return PVRSRV_OK;
+
+fail_tacommoncontext:
+       DevmemFree(psTAData->psContextStateMemDesc);
+fail_tacontextsuspendalloc:
+       PVR_ASSERT(eError != PVRSRV_OK);
+
+       return eError;
+}
+
+static
+PVRSRV_ERROR _Create3DContext(CONNECTION_DATA *psConnection,
+                                                         PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                         SERVER_MMU_CONTEXT *psServerMMUContext,
+                                                         DEVMEM_MEMDESC *psAllocatedMemDesc,
+                                                         IMG_UINT32 ui32AllocatedOffset,
+                                                         DEVMEM_MEMDESC *psFWMemContextMemDesc,
+                                                         IMG_UINT32 ui32Priority,
+                                                         IMG_UINT32 ui32MaxDeadlineMS,
+                                                         IMG_UINT64 ui64RobustnessAddress,
+                                                         RGX_COMMON_CONTEXT_INFO *psInfo,
+                                                         RGX_SERVER_RC_3D_DATA *ps3DData,
+                                                         IMG_UINT32 ui32CCBAllocSizeLog2,
+                                                         IMG_UINT32 ui32CCBMaxAllocSizeLog2,
+                                                         IMG_UINT32 ui32ContextFlags)
+{
+       PVRSRV_RGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+       PVRSRV_ERROR eError;
+       IMG_UINT        uiNumISPStoreRegs = RGXFWIF_IPP_RESUME_REG_COUNT; /* default 1 register for IPP_resume */
+       IMG_UINT        ui3DRegISPStateStoreSize = 0;
+
+       /*
+               Allocate device memory for the firmware GPU context suspend state.
+               Note: the FW reads/writes the state to memory by accessing the GPU register interface.
+       */
+       PDUMPCOMMENT(psDeviceNode, "Allocate RGX firmware 3D context suspend state");
+
+       uiNumISPStoreRegs += (RGX_GET_FEATURE_VALUE(psDevInfo, NUM_SPU) *
+                                                               RGX_GET_FEATURE_VALUE(psDevInfo, NUM_ISP_PER_SPU) *
+                                                               RGXFWIF_PIPE_COUNT_PER_ISP);
+
+
+       if (uiNumISPStoreRegs > (RGXFWIF_ISP_PIPE_COUNT_MAX + RGXFWIF_IPP_RESUME_REG_COUNT))
+       {
+               return PVRSRV_ERROR_NOT_SUPPORTED;
+       }
+
+       /* Size of the CS buffer */
+       /* Calculate the size of the 3DCTX ISP state */
+       ui3DRegISPStateStoreSize = sizeof(RGXFWIF_3DCTX_STATE) +
+                       (uiNumISPStoreRegs * sizeof(((RGXFWIF_3DCTX_STATE *)0)->au3DReg_ISP_STORE[0]));
+
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         ui3DRegISPStateStoreSize,
+                                                         RGX_FWCOMCTX_ALLOCFLAGS,
+                                                         "Fw3DContextState",
+                                                         &ps3DData->psContextStateMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to allocate firmware GPU context suspend state (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto fail_3dcontextsuspendalloc;
+       }
+
+       eError = FWCommonContextAllocate(psConnection,
+                                                                        psDeviceNode,
+                                                                        REQ_TYPE_3D,
+                                                                        RGXFWIF_DM_3D,
+                                                                        psServerMMUContext,
+                                                                        psAllocatedMemDesc,
+                                                                        ui32AllocatedOffset,
+                                                                        psFWMemContextMemDesc,
+                                                                        ps3DData->psContextStateMemDesc,
+                                                                        ui32CCBAllocSizeLog2 ? ui32CCBAllocSizeLog2 : RGX_3D_CCB_SIZE_LOG2,
+                                                                        ui32CCBMaxAllocSizeLog2 ? ui32CCBMaxAllocSizeLog2 : RGX_3D_CCB_MAX_SIZE_LOG2,
+                                                                        ui32ContextFlags,
+                                                                        ui32Priority,
+                                                                        ui32MaxDeadlineMS,
+                                                                        ui64RobustnessAddress,
+                                                                        psInfo,
+                                                                        &ps3DData->psServerCommonContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to init 3D fw common context (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto fail_3dcommoncontext;
+       }
+
+       /*
+        * Dump the FW 3D context suspend state buffer
+        */
+       PDUMPCOMMENT(psDeviceNode, "Dump the 3D context suspend state buffer");
+       DevmemPDumpLoadMem(ps3DData->psContextStateMemDesc,
+                                          0,
+                                          sizeof(RGXFWIF_3DCTX_STATE),
+                                          PDUMP_FLAGS_CONTINUOUS);
+
+       ps3DData->ui32Priority = ui32Priority;
+       return PVRSRV_OK;
+
+fail_3dcommoncontext:
+       DevmemFree(ps3DData->psContextStateMemDesc);
+fail_3dcontextsuspendalloc:
+       PVR_ASSERT(eError != PVRSRV_OK);
+
+       return eError;
+}
+
+
+/*
+ * PVRSRVRGXCreateRenderContextKM
+ */
+PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                            *psConnection,
+                                                                                       PVRSRV_DEVICE_NODE                      *psDeviceNode,
+                                                                                       IMG_UINT32                                      ui32Priority,
+                                                                                       IMG_UINT32                                      ui32FrameworkRegisterSize,
+                                                                                       IMG_PBYTE                                       pabyFrameworkRegisters,
+                                                                                       IMG_HANDLE                                      hMemCtxPrivData,
+                                                                                       IMG_UINT32                                      ui32StaticRenderContextStateSize,
+                                                                                       IMG_PBYTE                                       pStaticRenderContextState,
+                                                                                       IMG_UINT32                                      ui32PackedCCBSizeU8888,
+                                                                                       IMG_UINT32                                      ui32ContextFlags,
+                                                                                       IMG_UINT64                                      ui64RobustnessAddress,
+                                                                                       IMG_UINT32                                      ui32MaxTADeadlineMS,
+                                                                                       IMG_UINT32                                      ui32Max3DDeadlineMS,
+                                                                                       RGX_SERVER_RENDER_CONTEXT       **ppsRenderContext)
+{
+       PVRSRV_ERROR                            eError;
+       PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+       RGX_SERVER_RENDER_CONTEXT       *psRenderContext;
+       DEVMEM_MEMDESC                          *psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+       RGX_COMMON_CONTEXT_INFO         sInfo = {NULL};
+       RGXFWIF_FWRENDERCONTEXT         *psFWRenderContext;
+
+       *ppsRenderContext = NULL;
+
+       if (ui32StaticRenderContextStateSize > RGXFWIF_STATIC_RENDERCONTEXT_SIZE)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       psRenderContext = OSAllocZMem(sizeof(*psRenderContext));
+       if (psRenderContext == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       eError = OSLockCreate(&psRenderContext->hLock);
+
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_lock;
+       }
+
+       psRenderContext->psDeviceNode = psDeviceNode;
+
+       /*
+               Create the FW render context, this has the TA and 3D FW common
+               contexts embedded within it
+       */
+       eError = DevmemFwAllocate(psDevInfo,
+                                                         sizeof(RGXFWIF_FWRENDERCONTEXT),
+                                                         RGX_FWCOMCTX_ALLOCFLAGS,
+                                                         "FwRenderContext",
+                                                         &psRenderContext->psFWRenderContextMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_fwrendercontext;
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WorkEstInitTA3D(psDevInfo, &psRenderContext->sWorkEstData);
+#endif
+
+       if (ui32FrameworkRegisterSize)
+       {
+               /*
+                * Create the FW framework buffer
+                */
+               eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+                               &psRenderContext->psFWFrameworkMemDesc,
+                               ui32FrameworkRegisterSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to allocate firmware GPU framework state (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcreate;
+               }
+
+               /* Copy the Framework client data into the framework buffer */
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psRenderContext->psFWFrameworkMemDesc,
+                               pabyFrameworkRegisters,
+                               ui32FrameworkRegisterSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to populate the framework buffer (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcopy;
+               }
+               sInfo.psFWFrameworkMemDesc = psRenderContext->psFWFrameworkMemDesc;
+       }
+
+       eError = _Create3DContext(psConnection,
+                                                         psDeviceNode,
+                                                         hMemCtxPrivData,
+                                                         psRenderContext->psFWRenderContextMemDesc,
+                                                         offsetof(RGXFWIF_FWRENDERCONTEXT, s3DContext),
+                                                         psFWMemContextMemDesc,
+                                                         ui32Priority,
+                                                         ui32Max3DDeadlineMS,
+                                                         ui64RobustnessAddress,
+                                                         &sInfo,
+                                                         &psRenderContext->s3DData,
+                                                         U32toU8_Unpack3(ui32PackedCCBSizeU8888),
+                                                         U32toU8_Unpack4(ui32PackedCCBSizeU8888),
+                                                         ui32ContextFlags);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_3dcontext;
+       }
+
+       eError = _CreateTAContext(psConnection,
+                                                         psDeviceNode,
+                                                         hMemCtxPrivData,
+                                                         psRenderContext->psFWRenderContextMemDesc,
+                                                         offsetof(RGXFWIF_FWRENDERCONTEXT, sTAContext),
+                                                         psFWMemContextMemDesc,
+                                                         ui32Priority,
+                                                         ui32MaxTADeadlineMS,
+                                                         ui64RobustnessAddress,
+                                                         &sInfo,
+                                                         &psRenderContext->sTAData,
+                                                         U32toU8_Unpack1(ui32PackedCCBSizeU8888),
+                                                         U32toU8_Unpack2(ui32PackedCCBSizeU8888),
+                                                         ui32ContextFlags);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_tacontext;
+       }
+
+       eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
+                       (void **)&psFWRenderContext);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_acquire_cpu_mapping;
+       }
+
+       OSDeviceMemCopy(&psFWRenderContext->sStaticRenderContextState, pStaticRenderContextState, ui32StaticRenderContextStateSize);
+       DevmemPDumpLoadMem(psRenderContext->psFWRenderContextMemDesc, 0, sizeof(RGXFWIF_FWRENDERCONTEXT), PDUMP_FLAGS_CONTINUOUS);
+       DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       psRenderContext->psBufferSyncContext =
+               pvr_buffer_sync_context_create(psDeviceNode->psDevConfig->pvOSDevice,
+                                                                          "rogue-ta3d");
+       if (IS_ERR(psRenderContext->psBufferSyncContext))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: failed to create buffer_sync context (err=%ld)",
+                                __func__, PTR_ERR(psRenderContext->psBufferSyncContext)));
+
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto fail_buffer_sync_context_create;
+       }
+#endif
+
+       SyncAddrListInit(&psRenderContext->sSyncAddrListTAFence);
+       SyncAddrListInit(&psRenderContext->sSyncAddrListTAUpdate);
+       SyncAddrListInit(&psRenderContext->sSyncAddrList3DFence);
+       SyncAddrListInit(&psRenderContext->sSyncAddrList3DUpdate);
+
+       {
+               PVRSRV_RGXDEV_INFO                      *psDevInfo = psDeviceNode->pvDevice;
+
+               OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
+               dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
+               OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+       }
+
+       *ppsRenderContext = psRenderContext;
+       return PVRSRV_OK;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+fail_buffer_sync_context_create:
+#endif
+fail_acquire_cpu_mapping:
+       _DestroyTAContext(&psRenderContext->sTAData,
+                         psDeviceNode);
+fail_tacontext:
+       _Destroy3DContext(&psRenderContext->s3DData,
+                         psRenderContext->psDeviceNode);
+fail_3dcontext:
+fail_frameworkcopy:
+       if (psRenderContext->psFWFrameworkMemDesc != NULL)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
+       }
+fail_frameworkcreate:
+       DevmemFwUnmapAndFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
+fail_fwrendercontext:
+       OSLockDestroy(psRenderContext->hLock);
+fail_lock:
+       OSFreeMem(psRenderContext);
+       PVR_ASSERT(eError != PVRSRV_OK);
+
+       return eError;
+}
+
+/*
+ * PVRSRVRGXDestroyRenderContextKM
+ */
+PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext)
+{
+       PVRSRV_ERROR                            eError;
+       PVRSRV_RGXDEV_INFO      *psDevInfo = psRenderContext->psDeviceNode->pvDevice;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_FWRENDERCONTEXT *psFWRenderContext;
+       IMG_UINT32 ui32WorkEstCCBSubmitted;
+#endif
+
+       /* remove node from list before calling destroy - as destroy, if successful
+        * will invalidate the node
+        * must be re-added if destroy fails
+        */
+       OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
+       dllist_remove_node(&(psRenderContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       /* Check psBufferSyncContext has not been destroyed already (by a previous
+        * call to this function which then later returned PVRSRV_ERROR_RETRY)
+        */
+       if (psRenderContext->psBufferSyncContext != NULL)
+       {
+               pvr_buffer_sync_context_destroy(psRenderContext->psBufferSyncContext);
+               psRenderContext->psBufferSyncContext = NULL;
+       }
+#endif
+
+       /* Cleanup the TA if we haven't already */
+       if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_TA_COMPLETE) == 0)
+       {
+               eError = _DestroyTAContext(&psRenderContext->sTAData,
+                                                                  psRenderContext->psDeviceNode);
+               if (eError == PVRSRV_OK)
+               {
+                       psRenderContext->ui32CleanupStatus |= RC_CLEANUP_TA_COMPLETE;
+               }
+               else
+               {
+                       goto e0;
+               }
+       }
+
+       /* Cleanup the 3D if we haven't already */
+       if ((psRenderContext->ui32CleanupStatus & RC_CLEANUP_3D_COMPLETE) == 0)
+       {
+               eError = _Destroy3DContext(&psRenderContext->s3DData,
+                                                                  psRenderContext->psDeviceNode);
+               if (eError == PVRSRV_OK)
+               {
+                       psRenderContext->ui32CleanupStatus |= RC_CLEANUP_3D_COMPLETE;
+               }
+               else
+               {
+                       goto e0;
+               }
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       eError = DevmemAcquireCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc,
+                       (void **)&psFWRenderContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map firmware render context (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               goto e0;
+       }
+
+       ui32WorkEstCCBSubmitted = psFWRenderContext->ui32WorkEstCCBSubmitted;
+
+       DevmemReleaseCpuVirtAddr(psRenderContext->psFWRenderContextMemDesc);
+
+       /* Check if all of the workload estimation CCB commands for this workload are read */
+       if (ui32WorkEstCCBSubmitted != psRenderContext->sWorkEstData.ui32WorkEstCCBReceived)
+       {
+
+               PVR_DPF((PVR_DBG_WARNING,
+                       "%s: WorkEst # cmds submitted (%u) and received (%u) mismatch",
+                       __func__, ui32WorkEstCCBSubmitted,
+                       psRenderContext->sWorkEstData.ui32WorkEstCCBReceived));
+
+               eError = PVRSRV_ERROR_RETRY;
+               goto e0;
+       }
+#endif
+
+       /*
+               Only if both TA and 3D contexts have been cleaned up can we
+               free the shared resources
+       */
+       if (psRenderContext->ui32CleanupStatus == (RC_CLEANUP_3D_COMPLETE | RC_CLEANUP_TA_COMPLETE))
+       {
+               if (psRenderContext->psFWFrameworkMemDesc != NULL)
+               {
+                       /* Free the framework buffer */
+                       DevmemFwUnmapAndFree(psDevInfo, psRenderContext->psFWFrameworkMemDesc);
+               }
+
+               /* Free the firmware render context */
+               DevmemFwUnmapAndFree(psDevInfo, psRenderContext->psFWRenderContextMemDesc);
+
+               SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAFence);
+               SyncAddrListDeinit(&psRenderContext->sSyncAddrListTAUpdate);
+               SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DFence);
+               SyncAddrListDeinit(&psRenderContext->sSyncAddrList3DUpdate);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               WorkEstDeInitTA3D(psDevInfo, &psRenderContext->sWorkEstData);
+#endif
+               OSLockDestroy(psRenderContext->hLock);
+
+               OSFreeMem(psRenderContext);
+       }
+
+       return PVRSRV_OK;
+
+e0:
+       OSWRLockAcquireWrite(psDevInfo->hRenderCtxListLock);
+       dllist_add_to_tail(&(psDevInfo->sRenderCtxtListHead), &(psRenderContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hRenderCtxListLock);
+       return eError;
+}
+
+
+#if (ENABLE_TA3D_UFO_DUMP == 1)
+static void DumpUfoList(IMG_UINT32 ui32ClientTAFenceCount,
+                        IMG_UINT32 ui32ClientTAUpdateCount,
+                        IMG_UINT32 ui32Client3DFenceCount,
+                        IMG_UINT32 ui32Client3DUpdateCount,
+                        PRGXFWIF_UFO_ADDR *pauiClientTAFenceUFOAddress,
+                        IMG_UINT32 *paui32ClientTAFenceValue,
+                        PRGXFWIF_UFO_ADDR *pauiClientTAUpdateUFOAddress,
+                        IMG_UINT32 *paui32ClientTAUpdateValue,
+                        PRGXFWIF_UFO_ADDR *pauiClient3DFenceUFOAddress,
+                        IMG_UINT32 *paui32Client3DFenceValue,
+                        PRGXFWIF_UFO_ADDR *pauiClient3DUpdateUFOAddress,
+                        IMG_UINT32 *paui32Client3DUpdateValue)
+{
+       IMG_UINT32 i;
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: ~~~ After populating sync prims ~~~",
+                        __func__));
+
+       /* Dump Fence syncs, Update syncs and PR Update syncs */
+       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d TA fence syncs:",
+               __func__, ui32ClientTAFenceCount));
+       for (i = 0; i < ui32ClientTAFenceCount; i++)
+       {
+               if (BITMASK_HAS(pauiClientTAFenceUFOAddress->ui32Addr, 1))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x,"
+                               " CheckValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED",
+                               __func__, i + 1, ui32ClientTAFenceCount,
+                               (void *) pauiClientTAFenceUFOAddress,
+                               pauiClientTAFenceUFOAddress->ui32Addr));
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x, CheckValue=%d(0x%x)",
+                               __func__, i + 1, ui32ClientTAFenceCount,
+                               (void *) pauiClientTAFenceUFOAddress,
+                               pauiClientTAFenceUFOAddress->ui32Addr,
+                               *paui32ClientTAFenceValue,
+                               *paui32ClientTAFenceValue));
+                       paui32ClientTAFenceValue++;
+               }
+               pauiClientTAFenceUFOAddress++;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d TA update syncs:",
+                        __func__, ui32ClientTAUpdateCount));
+       for (i = 0; i < ui32ClientTAUpdateCount; i++)
+       {
+               if (BITMASK_HAS(pauiClientTAUpdateUFOAddress->ui32Addr, 1))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x,"
+                               " UpdateValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED",
+                               __func__, i + 1, ui32ClientTAUpdateCount,
+                               (void *) pauiClientTAUpdateUFOAddress,
+                               pauiClientTAUpdateUFOAddress->ui32Addr));
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=%d(0x%x)",
+                               __func__, i + 1, ui32ClientTAUpdateCount,
+                               (void *) pauiClientTAUpdateUFOAddress,
+                               pauiClientTAUpdateUFOAddress->ui32Addr,
+                               *paui32ClientTAUpdateValue,
+                               *paui32ClientTAUpdateValue));
+                       paui32ClientTAUpdateValue++;
+               }
+               pauiClientTAUpdateUFOAddress++;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d 3D fence syncs:",
+                        __func__, ui32Client3DFenceCount));
+       for (i = 0; i < ui32Client3DFenceCount; i++)
+       {
+               if (BITMASK_HAS(pauiClient3DFenceUFOAddress->ui32Addr, 1))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x,"
+                               " CheckValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED",
+                               __func__, i + 1, ui32Client3DFenceCount,
+                               (void *) pauiClient3DFenceUFOAddress,
+                               pauiClient3DFenceUFOAddress->ui32Addr));
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x, CheckValue=%d(0x%x)",
+                               __func__, i + 1, ui32Client3DFenceCount,
+                               (void *) pauiClient3DFenceUFOAddress,
+                               pauiClient3DFenceUFOAddress->ui32Addr,
+                               *paui32Client3DFenceValue,
+                               *paui32Client3DFenceValue));
+                       paui32Client3DFenceValue++;
+               }
+               pauiClient3DFenceUFOAddress++;
+       }
+
+       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d 3D update syncs:",
+                        __func__, ui32Client3DUpdateCount));
+       for (i = 0; i < ui32Client3DUpdateCount; i++)
+       {
+               if (BITMASK_HAS(pauiClient3DUpdateUFOAddress->ui32Addr, 1))
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x,"
+                               " UpdateValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED",
+                               __func__, i + 1, ui32Client3DUpdateCount,
+                               (void *) pauiClient3DUpdateUFOAddress,
+                               pauiClient3DUpdateUFOAddress->ui32Addr));
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=%d(0x%x)",
+                               __func__, i + 1, ui32Client3DUpdateCount,
+                               (void *) pauiClient3DUpdateUFOAddress,
+                               pauiClient3DUpdateUFOAddress->ui32Addr,
+                               *paui32Client3DUpdateValue,
+                               *paui32Client3DUpdateValue));
+                       paui32Client3DUpdateValue++;
+               }
+               pauiClient3DUpdateUFOAddress++;
+       }
+}
+#endif /* (ENABLE_TA3D_UFO_DUMP == 1) */
+
+/*
+ * PVRSRVRGXKickTA3DKM
+ */
+PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT     *psRenderContext,
+                                                                IMG_UINT32                                     ui32ClientTAFenceCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClientTAFenceSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32ClientTAFenceSyncOffset,
+                                                                IMG_UINT32                                     *paui32ClientTAFenceValue,
+                                                                IMG_UINT32                                     ui32ClientTAUpdateCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClientTAUpdateSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32ClientTAUpdateSyncOffset,
+                                                                IMG_UINT32                                     *paui32ClientTAUpdateValue,
+                                                                IMG_UINT32                                     ui32Client3DUpdateCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClient3DUpdateSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32Client3DUpdateSyncOffset,
+                                                                IMG_UINT32                                     *paui32Client3DUpdateValue,
+                                                                SYNC_PRIMITIVE_BLOCK           *psPRFenceSyncPrimBlock,
+                                                                IMG_UINT32                                     ui32PRFenceSyncOffset,
+                                                                IMG_UINT32                                     ui32PRFenceValue,
+                                                                PVRSRV_FENCE                           iCheckTAFence,
+                                                                PVRSRV_TIMELINE                        iUpdateTATimeline,
+                                                                PVRSRV_FENCE                           *piUpdateTAFence,
+                                                                IMG_CHAR                                       szFenceNameTA[PVRSRV_SYNC_NAME_LENGTH],
+                                                                PVRSRV_FENCE                           iCheck3DFence,
+                                                                PVRSRV_TIMELINE                        iUpdate3DTimeline,
+                                                                PVRSRV_FENCE                           *piUpdate3DFence,
+                                                                IMG_CHAR                                       szFenceName3D[PVRSRV_SYNC_NAME_LENGTH],
+                                                                IMG_UINT32                                     ui32TACmdSize,
+                                                                IMG_PBYTE                                      pui8TADMCmd,
+                                                                IMG_UINT32                                     ui323DPRCmdSize,
+                                                                IMG_PBYTE                                      pui83DPRDMCmd,
+                                                                IMG_UINT32                                     ui323DCmdSize,
+                                                                IMG_PBYTE                                      pui83DDMCmd,
+                                                                IMG_UINT32                                     ui32ExtJobRef,
+                                                                IMG_BOOL                                       bKickTA,
+                                                                IMG_BOOL                                       bKickPR,
+                                                                IMG_BOOL                                       bKick3D,
+                                                                IMG_BOOL                                       bAbort,
+                                                                IMG_UINT32                                     ui32PDumpFlags,
+                                                                RGX_KM_HW_RT_DATASET           *psKMHWRTDataSet,
+                                                                RGX_ZSBUFFER_DATA                      *psZSBuffer,
+                                                                RGX_ZSBUFFER_DATA                      *psMSAAScratchBuffer,
+                                                                IMG_UINT32                                     ui32SyncPMRCount,
+                                                                IMG_UINT32                                     *paui32SyncPMRFlags,
+                                                                PMR                                            **ppsSyncPMRs,
+                                                                IMG_UINT32                                     ui32RenderTargetSize,
+                                                                IMG_UINT32                                     ui32NumberOfDrawCalls,
+                                                                IMG_UINT32                                     ui32NumberOfIndices,
+                                                                IMG_UINT32                                     ui32NumberOfMRTs,
+                                                                IMG_UINT64                                     ui64DeadlineInus)
+{
+       /* per-context helper structures */
+       RGX_CCB_CMD_HELPER_DATA *pasTACmdHelperData = psRenderContext->asTACmdHelperData;
+       RGX_CCB_CMD_HELPER_DATA *pas3DCmdHelperData = psRenderContext->as3DCmdHelperData;
+
+       IMG_UINT64                              ui64FBSCEntryMask;
+
+       IMG_UINT32                              ui32TACmdCount=0;
+       IMG_UINT32                              ui323DCmdCount=0;
+       IMG_UINT32                              ui32TACmdOffset=0;
+       IMG_UINT32                              ui323DCmdOffset=0;
+       RGXFWIF_UFO                             sPRUFO;
+       IMG_UINT32                              i;
+       PVRSRV_ERROR                    eError = PVRSRV_OK;
+       PVRSRV_ERROR                    eError2 = PVRSRV_OK;
+
+       PVRSRV_RGXDEV_INFO      *psDevInfo = FWCommonContextGetRGXDevInfo(psRenderContext->s3DData.psServerCommonContext);
+       IMG_UINT32              ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
+       IMG_BOOL                bCCBStateOpen = IMG_FALSE;
+
+       IMG_UINT32                              ui32ClientPRUpdateCount = 0;
+       PRGXFWIF_UFO_ADDR               *pauiClientPRUpdateUFOAddress = NULL;
+       IMG_UINT32                              *paui32ClientPRUpdateValue = NULL;
+
+       PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+       PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+       PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+
+       PRGXFWIF_UFO_ADDR               *pauiClientTAFenceUFOAddress = NULL;
+       PRGXFWIF_UFO_ADDR               *pauiClientTAUpdateUFOAddress = NULL;
+       PRGXFWIF_UFO_ADDR               *pauiClient3DFenceUFOAddress = NULL;
+       PRGXFWIF_UFO_ADDR               *pauiClient3DUpdateUFOAddress = NULL;
+       PRGXFWIF_UFO_ADDR               uiPRFenceUFOAddress;
+
+       IMG_UINT64               uiCheckTAFenceUID = 0;
+       IMG_UINT64               uiCheck3DFenceUID = 0;
+       IMG_UINT64               uiUpdateTAFenceUID = 0;
+       IMG_UINT64               uiUpdate3DFenceUID = 0;
+
+       IMG_BOOL bUseCombined3DAnd3DPR = bKickPR && bKick3D && !pui83DPRDMCmd;
+
+       IMG_UINT32 ui32TACmdSizeTmp = 0, ui323DCmdSizeTmp = 0;
+
+       IMG_BOOL bTAFenceOnSyncCheckpointsOnly = IMG_FALSE;
+
+       RGXFWIF_KCCB_CMD_KICK_DATA      sTACmdKickData;
+       RGXFWIF_KCCB_CMD_KICK_DATA      s3DCmdKickData;
+       IMG_BOOL bUseSingleFWCommand = bKickTA && (bKickPR || bKick3D);
+
+       PVRSRV_FENCE    iUpdateTAFence = PVRSRV_NO_FENCE;
+       PVRSRV_FENCE    iUpdate3DFence = PVRSRV_NO_FENCE;
+
+       IMG_BOOL b3DFenceOnSyncCheckpointsOnly = IMG_FALSE;
+       IMG_UINT32 ui32TAFenceTimelineUpdateValue = 0;
+       IMG_UINT32 ui323DFenceTimelineUpdateValue = 0;
+
+       /*
+        * Count of the number of TA and 3D update values (may differ from number of
+        * TA and 3D updates later, as sync checkpoints do not need to specify a value)
+        */
+       IMG_UINT32 ui32ClientPRUpdateValueCount = 0;
+       IMG_UINT32 ui32ClientTAUpdateValueCount = ui32ClientTAUpdateCount;
+       IMG_UINT32 ui32Client3DUpdateValueCount = ui32Client3DUpdateCount;
+       PSYNC_CHECKPOINT *apsFenceTASyncCheckpoints = NULL;                             /*!< TA fence checkpoints */
+       PSYNC_CHECKPOINT *apsFence3DSyncCheckpoints = NULL;                             /*!< 3D fence checkpoints */
+       IMG_UINT32 ui32FenceTASyncCheckpointCount = 0;
+       IMG_UINT32 ui32Fence3DSyncCheckpointCount = 0;
+       PSYNC_CHECKPOINT psUpdateTASyncCheckpoint = NULL;                               /*!< TA update checkpoint (output) */
+       PSYNC_CHECKPOINT psUpdate3DSyncCheckpoint = NULL;                               /*!< 3D update checkpoint (output) */
+       PVRSRV_CLIENT_SYNC_PRIM *psTAFenceTimelineUpdateSync = NULL;
+       PVRSRV_CLIENT_SYNC_PRIM *ps3DFenceTimelineUpdateSync = NULL;
+       void *pvTAUpdateFenceFinaliseData = NULL;
+       void *pv3DUpdateFenceFinaliseData = NULL;
+
+       RGX_SYNC_DATA sTASyncData = {NULL};             /*!< Contains internal update syncs for TA */
+       RGX_SYNC_DATA s3DSyncData = {NULL};             /*!< Contains internal update syncs for 3D */
+
+       IMG_BOOL bTestSLRAdd3DCheck = IMG_FALSE;
+#if defined(SUPPORT_VALIDATION)
+       PVRSRV_FENCE hTestSLRTmpFence = PVRSRV_NO_FENCE;
+       PSYNC_CHECKPOINT psDummySyncCheckpoint = NULL;
+#endif
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       PSYNC_CHECKPOINT *apsBufferFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32BufferFenceSyncCheckpointCount = 0;
+       PSYNC_CHECKPOINT psBufferUpdateSyncCheckpoint = NULL;
+       struct pvr_buffer_sync_append_data *psBufferSyncData = NULL;
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_WORKEST_KICK_DATA sWorkloadKickDataTA = {0};
+       RGXFWIF_WORKEST_KICK_DATA sWorkloadKickData3D = {0};
+       IMG_UINT32 ui32TACommandOffset = 0;
+       IMG_UINT32 ui323DCommandOffset = 0;
+       IMG_UINT32 ui32TACmdHeaderOffset = 0;
+       IMG_UINT32 ui323DCmdHeaderOffset = 0;
+       IMG_UINT32 ui323DFullRenderCommandOffset = 0;
+       IMG_UINT32 ui32TACmdOffsetWrapCheck = 0;
+       IMG_UINT32 ui323DCmdOffsetWrapCheck = 0;
+       RGX_WORKLOAD sWorkloadCharacteristics = {0};
+#endif
+
+       IMG_UINT32 ui32TAFenceCount, ui323DFenceCount;
+       IMG_UINT32 ui32TAUpdateCount, ui323DUpdateCount;
+       IMG_UINT32 ui32PRUpdateCount;
+
+       IMG_PID uiCurrentProcess = OSGetCurrentClientProcessIDKM();
+
+       IMG_UINT32 ui32Client3DFenceCount = 0;
+
+       /* Ensure we haven't been given a null ptr to
+        * TA fence values if we have been told we
+        * have TA sync prim fences
+        */
+       if (ui32ClientTAFenceCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32ClientTAFenceValue != NULL,
+                                       "paui32ClientTAFenceValue NULL but "
+                                       "ui32ClientTAFenceCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       /* Ensure we haven't been given a null ptr to
+        * TA update values if we have been told we
+        * have TA updates
+        */
+       if (ui32ClientTAUpdateCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32ClientTAUpdateValue != NULL,
+                                       "paui32ClientTAUpdateValue NULL but "
+                                       "ui32ClientTAUpdateCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+       /* Ensure we haven't been given a null ptr to
+        * 3D update values if we have been told we
+        * have 3D updates
+        */
+       if (ui32Client3DUpdateCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32Client3DUpdateValue != NULL,
+                                       "paui32Client3DUpdateValue NULL but "
+                                       "ui32Client3DUpdateCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       /* Write FW addresses into CMD SHARED BLOCKs */
+       {
+               CMDTA3D_SHARED *psGeomCmdShared = (CMDTA3D_SHARED *)pui8TADMCmd;
+               CMDTA3D_SHARED *ps3DCmdShared = (CMDTA3D_SHARED *)pui83DDMCmd;
+               CMDTA3D_SHARED *psPR3DCmdShared = (CMDTA3D_SHARED *)pui83DPRDMCmd;
+
+               if (psKMHWRTDataSet == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "KMHWRTDataSet is a null-pointer"));
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+
+               /* Write FW address for TA CMD
+               */
+               if (psGeomCmdShared != NULL)
+               {
+                       psGeomCmdShared->sHWRTData = psKMHWRTDataSet->sHWRTDataFwAddr;
+
+                       if (psZSBuffer != NULL)
+                       {
+                               psGeomCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_ZSBUFFER] = psZSBuffer->sZSBufferFWDevVAddr;
+                       }
+                       if (psMSAAScratchBuffer != NULL)
+                       {
+                               psGeomCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_MSAABUFFER] = psMSAAScratchBuffer->sZSBufferFWDevVAddr;
+                       }
+               }
+
+               /* Write FW address for 3D CMD
+               */
+               if (ps3DCmdShared != NULL)
+               {
+                       ps3DCmdShared->sHWRTData = psKMHWRTDataSet->sHWRTDataFwAddr;
+
+                       if (psZSBuffer != NULL)
+                       {
+                               ps3DCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_ZSBUFFER] = psZSBuffer->sZSBufferFWDevVAddr;
+                       }
+                       if (psMSAAScratchBuffer != NULL)
+                       {
+                               ps3DCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_MSAABUFFER] = psMSAAScratchBuffer->sZSBufferFWDevVAddr;
+                       }
+               }
+
+               /* Write FW address for PR3D CMD
+               */
+               if (psPR3DCmdShared != NULL)
+               {
+                       psPR3DCmdShared->sHWRTData = psKMHWRTDataSet->sHWRTDataFwAddr;
+
+                       if (psZSBuffer != NULL)
+                       {
+                               psPR3DCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_ZSBUFFER] = psZSBuffer->sZSBufferFWDevVAddr;
+                       }
+                       if (psMSAAScratchBuffer != NULL)
+                       {
+                               psPR3DCmdShared->asPRBuffer[RGXFWIF_PRBUFFER_MSAABUFFER] = psMSAAScratchBuffer->sZSBufferFWDevVAddr;
+                       }
+               }
+       }
+
+       if (unlikely(iUpdateTATimeline >= 0 && !piUpdateTAFence))
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       if (unlikely(iUpdate3DTimeline >= 0 && !piUpdate3DFence))
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: ui32ClientTAFenceCount=%d, ui32ClientTAUpdateCount=%d, "
+                          "ui32Client3DFenceCount=%d, ui32Client3DUpdateCount=%d",
+                          __func__,
+                          ui32ClientTAFenceCount, ui32ClientTAUpdateCount,
+                          ui32Client3DFenceCount, ui32Client3DUpdateCount));
+
+       RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psRenderContext->psDeviceNode->pvDevice,
+                                 &pPreAddr,
+                                 &pPostAddr,
+                                 &pRMWUFOAddr);
+
+       /* Double-check we have a PR kick if there are client fences */
+       if (unlikely(!bKickPR && ui32Client3DFenceCount != 0))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: 3D fence passed without a PR kick",
+                       __func__));
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       /* Ensure the string is null-terminated (Required for safety) */
+       szFenceNameTA[PVRSRV_SYNC_NAME_LENGTH-1] = '\0';
+       szFenceName3D[PVRSRV_SYNC_NAME_LENGTH-1] = '\0';
+
+       OSLockAcquire(psRenderContext->hLock);
+
+       ui32TAFenceCount = ui32ClientTAFenceCount;
+       ui323DFenceCount = ui32Client3DFenceCount;
+       ui32TAUpdateCount = ui32ClientTAUpdateCount;
+       ui323DUpdateCount = ui32Client3DUpdateCount;
+       ui32PRUpdateCount = ui32ClientPRUpdateCount;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (ui32SyncPMRCount)
+       {
+               int err;
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Calling"
+                         " pvr_buffer_sync_resolve_and_create_fences", __func__));
+
+               err = pvr_buffer_sync_resolve_and_create_fences(
+                   psRenderContext->psBufferSyncContext,
+                   psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                   ui32SyncPMRCount,
+                   ppsSyncPMRs,
+                   paui32SyncPMRFlags,
+                   &ui32BufferFenceSyncCheckpointCount,
+                   &apsBufferFenceSyncCheckpoints,
+                   &psBufferUpdateSyncCheckpoint,
+                   &psBufferSyncData
+               );
+
+               if (unlikely(err))
+               {
+                       switch (err)
+                       {
+                               case -EINTR:
+                                       eError = PVRSRV_ERROR_RETRY;
+                                       break;
+                               case -ENOMEM:
+                                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                                       break;
+                               default:
+                                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                                       break;
+                       }
+
+                       if (eError != PVRSRV_ERROR_RETRY)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s:   "
+                                       "pvr_buffer_sync_resolve_and_create_fences failed (%d)",
+                                       __func__, eError));
+                       }
+                       OSLockRelease(psRenderContext->hLock);
+                       return eError;
+               }
+
+#if !defined(SUPPORT_STRIP_RENDERING)
+               if (bKickTA)
+               {
+                       ui32TAFenceCount += ui32BufferFenceSyncCheckpointCount;
+               }
+               else
+               {
+                       ui323DFenceCount += ui32BufferFenceSyncCheckpointCount;
+               }
+#else /* !defined(SUPPORT_STRIP_RENDERING) */
+               ui323DFenceCount += ui32BufferFenceSyncCheckpointCount;
+
+               PVR_UNREFERENCED_PARAMETER(bTAFenceOnSyncCheckpointsOnly);
+#endif /* !defined(SUPPORT_STRIP_RENDERING) */
+
+               if (psBufferUpdateSyncCheckpoint != NULL)
+               {
+                       if (bKick3D)
+                       {
+                               ui323DUpdateCount++;
+                       }
+                       else
+                       {
+                               ui32PRUpdateCount++;
+                       }
+               }
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+#if !defined(UPDATE_FENCE_CHECKPOINT_COUNT) || UPDATE_FENCE_CHECKPOINT_COUNT != 1 && UPDATE_FENCE_CHECKPOINT_COUNT != 2
+#error "Invalid value for UPDATE_FENCE_CHECKPOINT_COUNT. Must be either 1 or 2."
+#endif /* !defined(UPDATE_FENCE_CHECKPOINT_COUNT) || UPDATE_FENCE_CHECKPOINT_COUNT != 1 && UPDATE_FENCE_CHECKPOINT_COUNT != 2 */
+
+       if (iCheckTAFence != PVRSRV_NO_FENCE)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointResolveFence[TA]"
+                         " (iCheckFence=%d),"
+                         " psRenderContext->psDeviceNode->hSyncCheckpointContext=<%p>...",
+                         __func__, iCheckTAFence,
+                         (void *) psRenderContext->psDeviceNode->hSyncCheckpointContext));
+
+               /* Resolve the sync checkpoints that make up the input fence */
+               eError = SyncCheckpointResolveFence(
+                   psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                   iCheckTAFence,
+                   &ui32FenceTASyncCheckpointCount,
+                   &apsFenceTASyncCheckpoints,
+                   &uiCheckTAFenceUID,
+                   ui32PDumpFlags
+               );
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, returned ERROR (eError=%d)",
+                                 __func__, eError));
+                       goto fail_resolve_input_ta_fence;
+               }
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, fence %d contained %d "
+                         "checkpoints (apsFenceSyncCheckpoints=<%p>)",
+                         __func__, iCheckTAFence, ui32FenceTASyncCheckpointCount,
+                         (void *) apsFenceTASyncCheckpoints));
+
+#if defined(TA3D_CHECKPOINT_DEBUG)
+               if (apsFenceTASyncCheckpoints)
+               {
+                       _DebugSyncCheckpoints(__func__, "TA", apsFenceTASyncCheckpoints,
+                                             ui32FenceTASyncCheckpointCount);
+               }
+#endif /* defined(TA3D_CHECKPOINT_DEBUG) */
+       }
+
+       if (iCheck3DFence != PVRSRV_NO_FENCE)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: calling SyncCheckpointResolveFence[3D]"
+                         " (iCheckFence=%d), "
+                         "psRenderContext->psDeviceNode->hSyncCheckpointContext=<%p>...",
+                         __func__, iCheck3DFence,
+                         (void*)psRenderContext->psDeviceNode->hSyncCheckpointContext));
+
+               /* Resolve the sync checkpoints that make up the input fence */
+               eError = SyncCheckpointResolveFence(
+                   psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                   iCheck3DFence,
+                   &ui32Fence3DSyncCheckpointCount,
+                   &apsFence3DSyncCheckpoints,
+                   &uiCheck3DFenceUID,
+                   ui32PDumpFlags
+               );
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, returned ERROR (eError=%d)",
+                                 __func__, eError));
+                       goto fail_resolve_input_3d_fence;
+               }
+
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: ...done, fence %d contained %d "
+                         "checkpoints (apsFenceSyncCheckpoints=<%p>)",
+                         __func__, iCheck3DFence, ui32Fence3DSyncCheckpointCount,
+                         (void*)apsFence3DSyncCheckpoints));
+
+#if defined(TA3D_CHECKPOINT_DEBUG)
+               if (apsFence3DSyncCheckpoints)
+               {
+                       _DebugSyncCheckpoints(__func__, "3D", apsFence3DSyncCheckpoints,
+                                             ui32Fence3DSyncCheckpointCount);
+               }
+#endif /* defined(TA3D_CHECKPOINT_DEBUG) */
+       }
+
+       if (iCheckTAFence >= 0 || iUpdateTATimeline >= 0 ||
+           iCheck3DFence >= 0 || iUpdate3DTimeline >= 0)
+       {
+               IMG_UINT32 i;
+
+               if (bKickTA)
+               {
+                       ui32TAFenceCount += ui32FenceTASyncCheckpointCount;
+
+                       for (i = 0; i < ui32Fence3DSyncCheckpointCount; i++)
+                       {
+                               if (SyncCheckpointGetCreator(apsFence3DSyncCheckpoints[i]) !=
+                                   uiCurrentProcess)
+                               {
+                                       ui32TAFenceCount++;
+                               }
+                       }
+               }
+
+               if (bKick3D)
+               {
+                       ui323DFenceCount += ui32Fence3DSyncCheckpointCount;
+               }
+
+               ui32TAUpdateCount += iUpdateTATimeline != PVRSRV_NO_TIMELINE ?
+                               UPDATE_FENCE_CHECKPOINT_COUNT : 0;
+               ui323DUpdateCount += iUpdate3DTimeline != PVRSRV_NO_TIMELINE ?
+                               UPDATE_FENCE_CHECKPOINT_COUNT : 0;
+               ui32PRUpdateCount += iUpdate3DTimeline != PVRSRV_NO_TIMELINE && !bKick3D ?
+                               UPDATE_FENCE_CHECKPOINT_COUNT : 0;
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       /* Check if TestingSLR is adding an extra sync checkpoint to the
+        * 3D fence check (which we won't signal)
+        */
+       if ((psDevInfo->ui32TestSLRInterval > 0) &&
+           (--psDevInfo->ui32TestSLRCount == 0))
+       {
+               bTestSLRAdd3DCheck = IMG_TRUE;
+               psDevInfo->ui32TestSLRCount = psDevInfo->ui32TestSLRInterval;
+       }
+
+       if ((bTestSLRAdd3DCheck) && (iUpdate3DTimeline != PVRSRV_NO_TIMELINE))
+       {
+               if (iUpdate3DTimeline == PVRSRV_NO_TIMELINE)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Would append additional SLR checkpoint "
+                                "to 3D fence but no update 3D timeline provided", __func__));
+               }
+               else
+               {
+                       SyncCheckpointAlloc(psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                                           iUpdate3DTimeline,
+                                           hTestSLRTmpFence,
+                                           "TestSLRCheck",
+                                           &psDummySyncCheckpoint);
+                       PVR_DPF((PVR_DBG_WARNING, "%s: Appending additional SLR checkpoint to 3D fence "
+                                                 "checkpoints (psDummySyncCheckpoint=<%p>)",
+                                                 __func__, (void*)psDummySyncCheckpoint));
+                       SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DFence,
+                                                     1,
+                                                     &psDummySyncCheckpoint);
+                       if (!pauiClient3DFenceUFOAddress)
+                       {
+                               pauiClient3DFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
+                       }
+
+                       if (ui32Client3DFenceCount == 0)
+                       {
+                               b3DFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                       }
+                       ui323DFenceCount++;
+               }
+       }
+#endif /* defined(SUPPORT_VALIDATION) */
+
+       /*
+        * Extract the FBSC entries from MMU Context for the deferred FBSC invalidate command,
+        * in other words, take the value and set it to zero afterwards.
+        * FBSC Entry Mask must be extracted from MMU ctx and updated just before the kick starts
+        * as it must be ready at the time of context activation.
+        *
+        * NOTE: We use sTAData to get the ServerCommonContext giving us the ServerMMUCtx,
+        *       should we use s3DData in some cases?
+        *       Under assumption that sTAData and s3DData share the same psServerCommonContext,
+        *       the answer is NO.
+        *
+        *       The ui64FBSCEntryMask filled by the following call gets cleared
+        *       after the first KICK command and is ignored in the context of partial renders.
+        */
+       eError = RGXExtractFBSCEntryMaskFromMMUContext(
+           psRenderContext->psDeviceNode,
+           FWCommonContextGetServerMMUCtx(psRenderContext->sTAData.psServerCommonContext),
+           &ui64FBSCEntryMask
+       );
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "Failed to extract FBSC Entry Mask (%d)", eError));
+               goto fail_tacmdinvalfbsc;
+       }
+
+       if (bKickTA)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   calling RGXCmdHelperInitCmdCCB(),"
+                         " ui32ClientTAFenceCount=%d, ui32ClientTAUpdateCount=%d",
+                         __func__, ui32TAFenceCount, ui32TAUpdateCount));
+
+               RGXCmdHelperInitCmdCCB_CommandSize(
+                   psDevInfo,
+                       ui64FBSCEntryMask,
+                   ui32TAFenceCount,
+                   ui32TAUpdateCount,
+                   ui32TACmdSize,
+                   &pPreAddr,
+                   (bKick3D ? NULL : &pPostAddr),
+                   (bKick3D ? NULL : &pRMWUFOAddr),
+                   pasTACmdHelperData
+               );
+
+               /* Clear the mask as we don't want to invalidate the FBSC multiple times
+                * with the same value of ui64FBSCEntryMask.
+                */
+               ui64FBSCEntryMask = 0;
+       }
+
+       if (bKickPR)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   calling RGXCmdHelperInitCmdCCB(),"
+                         " ui32Client3DFenceCount=%d", __func__,
+                         ui323DFenceCount));
+
+               RGXCmdHelperInitCmdCCB_CommandSize(
+                   psDevInfo,
+                       0, /* empty ui64FBSCEntryMask it is assumed that PRs should
+                       * not invalidate FBSC */
+                   ui323DFenceCount,
+                   0,
+                   sizeof(sPRUFO),
+                       NULL,
+                       NULL,
+                       NULL,
+                   &pas3DCmdHelperData[ui323DCmdCount++]
+               );
+       }
+
+       if (bKickPR && !bUseCombined3DAnd3DPR)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s:   calling RGXCmdHelperInitCmdCCB(),"
+                         " ui32PRUpdateCount=%d", __func__,
+                         ui32PRUpdateCount));
+
+               RGXCmdHelperInitCmdCCB_CommandSize(
+                   psDevInfo,
+                       0, /* empty ui64FBSCEntryMask it is assumed that PRs should
+                       * not invalidate FBSC */
+                   0,
+                   ui32PRUpdateCount,
+                   /* if the client has not provided a 3DPR command, the regular 3D
+                    * command should be used instead */
+                   pui83DPRDMCmd ? ui323DPRCmdSize : ui323DCmdSize,
+                       NULL,
+                       NULL,
+                       NULL,
+                   &pas3DCmdHelperData[ui323DCmdCount++]
+               );
+       }
+
+       if (bKick3D || bAbort)
+       {
+               if (!bKickTA)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:   calling RGXCmdHelperInitCmdCCB(),"
+                         " ui32Client3DFenceCount=%d", __func__,
+                         ui323DFenceCount));
+               }
+
+               RGXCmdHelperInitCmdCCB_CommandSize(
+                   psDevInfo,
+                       ui64FBSCEntryMask, /* equals: [a] 0 if 3D is preceded by TA
+                                       *         [b] value from the MMU ctx otherwise */
+                       bKickTA ? 0 : ui323DFenceCount,
+                   ui323DUpdateCount,
+                   ui323DCmdSize,
+                       (bKickTA ? NULL : & pPreAddr),
+                       &pPostAddr,
+                       &pRMWUFOAddr,
+                   &pas3DCmdHelperData[ui323DCmdCount++]
+               );
+       }
+
+       if (bKickTA)
+       {
+               ui32TACmdSizeTmp = RGXCmdHelperGetCommandSize(1, pasTACmdHelperData);
+
+               eError = RGXCheckSpaceCCB(
+                   FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext),
+                   ui32TACmdSizeTmp
+               );
+               if (eError != PVRSRV_OK)
+               {
+                       goto err_not_enough_space;
+               }
+       }
+
+       if (ui323DCmdCount > 0)
+       {
+               ui323DCmdSizeTmp = RGXCmdHelperGetCommandSize(ui323DCmdCount, pas3DCmdHelperData);
+
+               eError = RGXCheckSpaceCCB(
+                   FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext),
+                   ui323DCmdSizeTmp
+               );
+               if (eError != PVRSRV_OK)
+               {
+                       goto err_not_enough_space;
+               }
+       }
+
+       /* need to reset the counter here */
+
+       ui323DCmdCount = 0;
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: SyncAddrListPopulate(psRenderContext->sSyncAddrListTAFence, %d fences)...",
+                          __func__, ui32ClientTAFenceCount));
+       eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAFence,
+                                                                               ui32ClientTAFenceCount,
+                                                                               apsClientTAFenceSyncPrimBlock,
+                                                                               paui32ClientTAFenceSyncOffset);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               goto err_populate_sync_addr_list_ta_fence;
+       }
+
+       if (ui32ClientTAFenceCount)
+       {
+               pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
+       }
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: pauiClientTAFenceUFOAddress=<%p> ",
+                          __func__, (void*)pauiClientTAFenceUFOAddress));
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: SyncAddrListPopulate(psRenderContext->sSyncAddrListTAUpdate, %d updates)...",
+                          __func__, ui32ClientTAUpdateCount));
+       eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrListTAUpdate,
+                                                                               ui32ClientTAUpdateCount,
+                                                                               apsClientTAUpdateSyncPrimBlock,
+                                                                               paui32ClientTAUpdateSyncOffset);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               goto err_populate_sync_addr_list_ta_update;
+       }
+
+       if (ui32ClientTAUpdateCount)
+       {
+               pauiClientTAUpdateUFOAddress = psRenderContext->sSyncAddrListTAUpdate.pasFWAddrs;
+       }
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: pauiClientTAUpdateUFOAddress=<%p> ",
+                          __func__, (void*)pauiClientTAUpdateUFOAddress));
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: SyncAddrListPopulate(psRenderContext->sSyncAddrList3DFence, %d fences)...",
+                          __func__, ui32Client3DFenceCount));
+       eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DFence,
+                                                                               ui32Client3DFenceCount,
+                                                                               NULL,
+                                                                               NULL);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               goto err_populate_sync_addr_list_3d_fence;
+       }
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: SyncAddrListPopulate(psRenderContext->sSyncAddrList3DUpdate, %d updates)...",
+                          __func__, ui32Client3DUpdateCount));
+       eError = SyncAddrListPopulate(&psRenderContext->sSyncAddrList3DUpdate,
+                                                                               ui32Client3DUpdateCount,
+                                                                               apsClient3DUpdateSyncPrimBlock,
+                                                                               paui32Client3DUpdateSyncOffset);
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               goto err_populate_sync_addr_list_3d_update;
+       }
+
+       if (ui32Client3DUpdateCount || (iUpdate3DTimeline != PVRSRV_NO_TIMELINE && piUpdate3DFence && bKick3D))
+       {
+               pauiClient3DUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
+       }
+       CHKPT_DBG((PVR_DBG_ERROR, "%s: pauiClient3DUpdateUFOAddress=<%p> ",
+                          __func__, (void*)pauiClient3DUpdateUFOAddress));
+
+       eError = SyncPrimitiveBlockToFWAddr(psPRFenceSyncPrimBlock,
+                                                                       ui32PRFenceSyncOffset,
+                                                                       &uiPRFenceUFOAddress);
+
+       if (unlikely(eError != PVRSRV_OK))
+       {
+               goto err_pr_fence_address;
+       }
+
+#if (ENABLE_TA3D_UFO_DUMP == 1)
+       DumpUfoList(ui32ClientTAFenceCount, ui32ClientTAUpdateCount,
+                   ui32Client3DFenceCount + (bTestSLRAdd3DCheck ? 1 : 0),
+                   ui32Client3DUpdateCount,
+                   pauiClientTAFenceUFOAddress, paui32ClientTAFenceValue,
+                   pauiClientTAUpdateUFOAddress, paui32ClientTAUpdateValue,
+                   pauiClient3DFenceUFOAddress, NULL,
+                   pauiClient3DUpdateUFOAddress, paui32Client3DUpdateValue);
+#endif /* (ENABLE_TA3D_UFO_DUMP == 1) */
+
+       if (ui32SyncPMRCount)
+       {
+#if defined(SUPPORT_BUFFER_SYNC)
+#if !defined(SUPPORT_STRIP_RENDERING)
+               /* Append buffer sync fences to TA fences */
+               if (ui32BufferFenceSyncCheckpointCount > 0 && bKickTA)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR,
+                                          "%s:   Append %d buffer sync checkpoints to TA Fence "
+                                          "(&psRenderContext->sSyncAddrListTAFence=<%p>, "
+                                          "pauiClientTAFenceUFOAddress=<%p>)...",
+                                          __func__,
+                                          ui32BufferFenceSyncCheckpointCount,
+                                          (void*)&psRenderContext->sSyncAddrListTAFence ,
+                                          (void*)pauiClientTAFenceUFOAddress));
+                       SyncAddrListAppendAndDeRefCheckpoints(&psRenderContext->sSyncAddrListTAFence,
+                                                             ui32BufferFenceSyncCheckpointCount,
+                                                             apsBufferFenceSyncCheckpoints);
+                       if (!pauiClientTAFenceUFOAddress)
+                       {
+                               pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
+                       }
+                       if (ui32ClientTAFenceCount == 0)
+                       {
+                               bTAFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                       }
+                       ui32ClientTAFenceCount += ui32BufferFenceSyncCheckpointCount;
+               }
+               else
+#endif /* !defined(SUPPORT_STRIP_RENDERING) */
+               /* Append buffer sync fences to 3D fences */
+               if (ui32BufferFenceSyncCheckpointCount > 0)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR,
+                                          "%s:   Append %d buffer sync checkpoints to 3D Fence "
+                                          "(&psRenderContext->sSyncAddrList3DFence=<%p>, "
+                                          "pauiClient3DFenceUFOAddress=<%p>)...",
+                                          __func__,
+                                          ui32BufferFenceSyncCheckpointCount,
+                                          (void*)&psRenderContext->sSyncAddrList3DFence,
+                                          (void*)pauiClient3DFenceUFOAddress));
+                       SyncAddrListAppendAndDeRefCheckpoints(&psRenderContext->sSyncAddrList3DFence,
+                                       ui32BufferFenceSyncCheckpointCount,
+                                       apsBufferFenceSyncCheckpoints);
+                       if (!pauiClient3DFenceUFOAddress)
+                       {
+                               pauiClient3DFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
+                       }
+                       if (ui32Client3DFenceCount == 0)
+                       {
+                               b3DFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                       }
+                       ui32Client3DFenceCount += ui32BufferFenceSyncCheckpointCount;
+               }
+
+               if (psBufferUpdateSyncCheckpoint)
+               {
+                       /* If we have a 3D kick append update to the 3D updates else append to the PR update */
+                       if (bKick3D)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s:   Append 1 buffer sync checkpoint<%p> to 3D Update"
+                                                  " (&psRenderContext->sSyncAddrList3DUpdate=<%p>,"
+                                                  " pauiClient3DUpdateUFOAddress=<%p>)...",
+                                                  __func__,
+                                                  (void*)psBufferUpdateSyncCheckpoint,
+                                                  (void*)&psRenderContext->sSyncAddrList3DUpdate,
+                                                  (void*)pauiClient3DUpdateUFOAddress));
+                               /* Append buffer sync update to 3D updates */
+                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DUpdate,
+                                                                                         1,
+                                                                                         &psBufferUpdateSyncCheckpoint);
+                               if (!pauiClient3DUpdateUFOAddress)
+                               {
+                                       pauiClient3DUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
+                               }
+                               ui32Client3DUpdateCount++;
+                       }
+                       else
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                          "%s:   Append 1 buffer sync checkpoint<%p> to PR Update"
+                                                  " (&psRenderContext->sSyncAddrList3DUpdate=<%p>,"
+                                                  " pauiClientPRUpdateUFOAddress=<%p>)...",
+                                          __func__,
+                                                  (void*)psBufferUpdateSyncCheckpoint,
+                                                  (void*)&psRenderContext->sSyncAddrList3DUpdate,
+                                                  (void*)pauiClientPRUpdateUFOAddress));
+                               /* Attach update to the 3D (used for PR) Updates */
+                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DUpdate,
+                                                                                         1,
+                                                                                         &psBufferUpdateSyncCheckpoint);
+                               if (!pauiClientPRUpdateUFOAddress)
+                               {
+                                       pauiClientPRUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
+                               }
+                               ui32ClientPRUpdateCount++;
+                       }
+               }
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   (after buffer_sync) ui32ClientTAFenceCount=%d, "
+                                  "ui32ClientTAUpdateCount=%d, ui32Client3DFenceCount=%d, "
+                                  "ui32Client3DUpdateCount=%d, ui32ClientPRUpdateCount=%d,",
+                                  __func__, ui32ClientTAFenceCount, ui32ClientTAUpdateCount,
+                                  ui32Client3DFenceCount, ui32Client3DUpdateCount,
+                                  ui32ClientPRUpdateCount));
+
+#else /* defined(SUPPORT_BUFFER_SYNC) */
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: Buffer sync not supported but got %u buffers",
+                                __func__, ui32SyncPMRCount));
+
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto err_no_buffer_sync_invalid_params;
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+       }
+
+       /*
+        * The hardware requires a PR to be submitted if there is a TA (otherwise
+        * it can wedge if we run out of PB space with no PR to run)
+        *
+        * If we only have a TA, attach native checks to the TA and updates to the PR
+        * If we have a TA and 3D, attach checks to TA, updates to 3D
+        * If we only have a 3D, attach checks and updates to the 3D
+        *
+        * Note that 'updates' includes the cleanup syncs for 'check' fence FDs, in
+        * addition to the update fence FD (if supplied)
+        *
+        * Currently, the client driver never kicks only the 3D, so we only support
+        * that for the time being.
+        */
+       if (iCheckTAFence >= 0 || iUpdateTATimeline >= 0 ||
+           iCheck3DFence >= 0 || iUpdate3DTimeline >= 0)
+       {
+               PRGXFWIF_UFO_ADDR       *pauiClientTAIntUpdateUFOAddress = NULL;
+               PRGXFWIF_UFO_ADDR       *pauiClient3DIntUpdateUFOAddress = NULL;
+
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s: [TA] iCheckFence = %d, iUpdateTimeline = %d",
+                                  __func__, iCheckTAFence, iUpdateTATimeline));
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s: [3D] iCheckFence = %d, iUpdateTimeline = %d",
+                                  __func__, iCheck3DFence, iUpdate3DTimeline));
+
+               {
+                       /* Create the output fence for TA (if required) */
+                       if (iUpdateTATimeline != PVRSRV_NO_TIMELINE)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: calling SyncCheckpointCreateFence[TA] "
+                                                  "(iUpdateFence=%d, iUpdateTimeline=%d, "
+                                                  "psRenderContext->psDeviceNode->hSyncCheckpointContext=<%p>)",
+                                                  __func__, iUpdateTAFence, iUpdateTATimeline,
+                                                  (void*)psRenderContext->psDeviceNode->hSyncCheckpointContext));
+                               eError = SyncCheckpointCreateFence(psRenderContext->psDeviceNode,
+                                               szFenceNameTA,
+                                               iUpdateTATimeline,
+                                               psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                                               &iUpdateTAFence,
+                                               &uiUpdateTAFenceUID,
+                                               &pvTAUpdateFenceFinaliseData,
+                                               &psUpdateTASyncCheckpoint,
+                                               (void*)&psTAFenceTimelineUpdateSync,
+                                               &ui32TAFenceTimelineUpdateValue,
+                                               ui32PDumpFlags);
+                               if (unlikely(eError != PVRSRV_OK))
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   SyncCheckpointCreateFence[TA] failed (%d)", __func__, eError));
+                                       goto fail_create_ta_fence;
+                               }
+
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: returned from SyncCheckpointCreateFence[TA] "
+                                                  "(iUpdateFence=%d, psFenceTimelineUpdateSync=<%p>, "
+                                                  "ui32FenceTimelineUpdateValue=0x%x)",
+                                                  __func__, iUpdateTAFence,
+                                                  (void*)psTAFenceTimelineUpdateSync,
+                                                  ui32TAFenceTimelineUpdateValue));
+
+                               /* Store the FW address of the update sync checkpoint in pauiClientTAIntUpdateUFOAddress */
+                               pauiClientTAIntUpdateUFOAddress = SyncCheckpointGetRGXFWIFUFOAddr(psUpdateTASyncCheckpoint);
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: pauiClientIntUpdateUFOAddress[TA]->ui32Addr=0x%x",
+                                                  __func__, pauiClientTAIntUpdateUFOAddress->ui32Addr));
+                       }
+
+                       /* Append the sync prim update for the TA timeline (if required) */
+                       if (psTAFenceTimelineUpdateSync)
+                       {
+                               sTASyncData.ui32ClientUpdateCount                = ui32ClientTAUpdateCount;
+                               sTASyncData.ui32ClientUpdateValueCount   = ui32ClientTAUpdateValueCount;
+                               sTASyncData.ui32ClientPRUpdateValueCount = (bKick3D) ? 0 : ui32ClientPRUpdateValueCount;
+                               sTASyncData.paui32ClientUpdateValue              = paui32ClientTAUpdateValue;
+
+                               eError = RGXSyncAppendTimelineUpdate(ui32TAFenceTimelineUpdateValue,
+                                                                                       &psRenderContext->sSyncAddrListTAUpdate,
+                                                                                       (bKick3D) ? NULL : &psRenderContext->sSyncAddrList3DUpdate,
+                                                                                       psTAFenceTimelineUpdateSync,
+                                                                                       &sTASyncData,
+                                                                                       bKick3D);
+                               if (unlikely(eError != PVRSRV_OK))
+                               {
+                                       goto fail_alloc_update_values_mem_TA;
+                               }
+
+                               paui32ClientTAUpdateValue = sTASyncData.paui32ClientUpdateValue;
+                               ui32ClientTAUpdateValueCount = sTASyncData.ui32ClientUpdateValueCount;
+                               pauiClientTAUpdateUFOAddress = sTASyncData.pauiClientUpdateUFOAddress;
+                               ui32ClientTAUpdateCount = sTASyncData.ui32ClientUpdateCount;
+                       }
+
+                       /* Create the output fence for 3D (if required) */
+                       if (iUpdate3DTimeline != PVRSRV_NO_TIMELINE)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: calling SyncCheckpointCreateFence[3D] "
+                                                  "(iUpdateFence=%d, iUpdateTimeline=%d, "
+                                                  "psRenderContext->psDeviceNode->hSyncCheckpointContext=<%p>)",
+                                                  __func__, iUpdate3DFence, iUpdate3DTimeline,
+                                                  (void*)psRenderContext->psDeviceNode->hSyncCheckpointContext));
+                               eError = SyncCheckpointCreateFence(psRenderContext->psDeviceNode,
+                                               szFenceName3D,
+                                               iUpdate3DTimeline,
+                                               psRenderContext->psDeviceNode->hSyncCheckpointContext,
+                                               &iUpdate3DFence,
+                                               &uiUpdate3DFenceUID,
+                                               &pv3DUpdateFenceFinaliseData,
+                                               &psUpdate3DSyncCheckpoint,
+                                               (void*)&ps3DFenceTimelineUpdateSync,
+                                               &ui323DFenceTimelineUpdateValue,
+                                               ui32PDumpFlags);
+                               if (unlikely(eError != PVRSRV_OK))
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   SyncCheckpointCreateFence[3D] failed (%d)", __func__, eError));
+                                       goto fail_create_3d_fence;
+                               }
+
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: returned from SyncCheckpointCreateFence[3D] "
+                                                  "(iUpdateFence=%d, psFenceTimelineUpdateSync=<%p>, "
+                                                  "ui32FenceTimelineUpdateValue=0x%x)",
+                                                  __func__, iUpdate3DFence,
+                                                  (void*)ps3DFenceTimelineUpdateSync,
+                                                  ui323DFenceTimelineUpdateValue));
+
+                               /* Store the FW address of the update sync checkpoint in pauiClient3DIntUpdateUFOAddress */
+                               pauiClient3DIntUpdateUFOAddress = SyncCheckpointGetRGXFWIFUFOAddr(psUpdate3DSyncCheckpoint);
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s: pauiClientIntUpdateUFOAddress[3D]->ui32Addr=0x%x",
+                                                  __func__, pauiClient3DIntUpdateUFOAddress->ui32Addr));
+                       }
+
+                       /* Append the sync prim update for the 3D timeline (if required) */
+                       if (ps3DFenceTimelineUpdateSync)
+                       {
+                               s3DSyncData.ui32ClientUpdateCount = ui32Client3DUpdateCount;
+                               s3DSyncData.ui32ClientUpdateValueCount = ui32Client3DUpdateValueCount;
+                               s3DSyncData.ui32ClientPRUpdateValueCount = ui32ClientPRUpdateValueCount;
+                               s3DSyncData.paui32ClientUpdateValue = paui32Client3DUpdateValue;
+
+                               eError = RGXSyncAppendTimelineUpdate(ui323DFenceTimelineUpdateValue,
+                                                                                       &psRenderContext->sSyncAddrList3DUpdate,
+                                                                                       &psRenderContext->sSyncAddrList3DUpdate,        /*!< PR update: is this required? */
+                                                                                       ps3DFenceTimelineUpdateSync,
+                                                                                       &s3DSyncData,
+                                                                                       bKick3D);
+                               if (unlikely(eError != PVRSRV_OK))
+                               {
+                                       goto fail_alloc_update_values_mem_3D;
+                               }
+
+                               paui32Client3DUpdateValue = s3DSyncData.paui32ClientUpdateValue;
+                               ui32Client3DUpdateValueCount = s3DSyncData.ui32ClientUpdateValueCount;
+                               pauiClient3DUpdateUFOAddress = s3DSyncData.pauiClientUpdateUFOAddress;
+                               ui32Client3DUpdateCount = s3DSyncData.ui32ClientUpdateCount;
+
+                               if (!bKick3D)
+                               {
+                                       paui32ClientPRUpdateValue = s3DSyncData.paui32ClientPRUpdateValue;
+                                       ui32ClientPRUpdateValueCount = s3DSyncData.ui32ClientPRUpdateValueCount;
+                                       pauiClientPRUpdateUFOAddress = s3DSyncData.pauiClientPRUpdateUFOAddress;
+                                       ui32ClientPRUpdateCount = s3DSyncData.ui32ClientPRUpdateCount;
+                               }
+                       }
+
+                       /*
+                        * The hardware requires a PR to be submitted if there is a TA OOM.
+                        * If we only have a TA, attach native checks and updates to the TA
+                        * and 3D updates to the PR.
+                        * If we have a TA and 3D, attach the native TA checks and updates
+                        * to the TA and similarly for the 3D.
+                        * Note that 'updates' includes the cleanup syncs for 'check' fence
+                        * FDs, in addition to the update fence FD (if supplied).
+                        * Currently, the client driver never kicks only the 3D, so we don't
+                        * support that for the time being.
+                        */
+
+                       {
+                               if (bKickTA)
+                               {
+                                       /* Attach checks and updates to TA */
+
+                                       /* Checks (from input fence) */
+                                       if (ui32FenceTASyncCheckpointCount > 0)
+                                       {
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   Append %d sync checkpoints to TA Fence (apsFenceSyncCheckpoints=<%p>)...",
+                                                                  __func__,
+                                                                  ui32FenceTASyncCheckpointCount,
+                                                                  (void*)apsFenceTASyncCheckpoints));
+                                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrListTAFence,
+                                                                                                         ui32FenceTASyncCheckpointCount,
+                                                                                                         apsFenceTASyncCheckpoints);
+                                               if (!pauiClientTAFenceUFOAddress)
+                                               {
+                                                       pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
+                                               }
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   {ui32ClientTAFenceCount was %d, now %d}",
+                                                                  __func__, ui32ClientTAFenceCount,
+                                                                  ui32ClientTAFenceCount + ui32FenceTASyncCheckpointCount));
+                                               if (ui32ClientTAFenceCount == 0)
+                                               {
+                                                       bTAFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                                               }
+                                               ui32ClientTAFenceCount += ui32FenceTASyncCheckpointCount;
+                                       }
+                                       CHKPT_DBG((PVR_DBG_ERROR,
+                                                          "%s:   {ui32ClientTAFenceCount now %d}",
+                                                          __func__, ui32ClientTAFenceCount));
+
+                                       if (psUpdateTASyncCheckpoint)
+                                       {
+                                               /* Update (from output fence) */
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   Append 1 sync checkpoint<%p> (ID=%d) to TA Update...",
+                                                                  __func__, (void*)psUpdateTASyncCheckpoint,
+                                                                  SyncCheckpointGetId(psUpdateTASyncCheckpoint)));
+                                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrListTAUpdate,
+                                                                                                         1,
+                                                                                                         &psUpdateTASyncCheckpoint);
+                                               if (!pauiClientTAUpdateUFOAddress)
+                                               {
+                                                       pauiClientTAUpdateUFOAddress = psRenderContext->sSyncAddrListTAUpdate.pasFWAddrs;
+                                               }
+                                               ui32ClientTAUpdateCount++;
+                                       }
+
+                                       if (!bKick3D && psUpdate3DSyncCheckpoint)
+                                       {
+                                               /* Attach update to the 3D (used for PR) Updates */
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   Append 1 sync checkpoint<%p> (ID=%d) to 3D(PR) Update...",
+                                                                  __func__, (void*)psUpdate3DSyncCheckpoint,
+                                                                  SyncCheckpointGetId(psUpdate3DSyncCheckpoint)));
+                                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DUpdate,
+                                                                                                         1,
+                                                                                                         &psUpdate3DSyncCheckpoint);
+                                               if (!pauiClientPRUpdateUFOAddress)
+                                               {
+                                                       pauiClientPRUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
+                                               }
+                                               ui32ClientPRUpdateCount++;
+                                       }
+                               }
+
+                               if (bKick3D)
+                               {
+                                       /* Attach checks and updates to the 3D */
+
+                                       /* Checks (from input fence) */
+                                       if (ui32Fence3DSyncCheckpointCount > 0)
+                                       {
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   Append %d sync checkpoints to 3D Fence...",
+                                                                  __func__, ui32Fence3DSyncCheckpointCount));
+                                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DFence,
+                                                                                                         ui32Fence3DSyncCheckpointCount,
+                                                                                                         apsFence3DSyncCheckpoints);
+                                               if (!pauiClient3DFenceUFOAddress)
+                                               {
+                                                       pauiClient3DFenceUFOAddress = psRenderContext->sSyncAddrList3DFence.pasFWAddrs;
+                                               }
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   {ui32Client3DFenceCount was %d, now %d}",
+                                                                  __func__, ui32Client3DFenceCount,
+                                                                  ui32Client3DFenceCount + ui32Fence3DSyncCheckpointCount));
+                                               if (ui32Client3DFenceCount == 0)
+                                               {
+                                                       b3DFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                                               }
+                                               ui32Client3DFenceCount += ui32Fence3DSyncCheckpointCount;
+                                       }
+                                       CHKPT_DBG((PVR_DBG_ERROR,
+                                                          "%s:   {ui32Client3DFenceCount was %d}",
+                                                          __func__, ui32Client3DFenceCount));
+
+                                       if (psUpdate3DSyncCheckpoint)
+                                       {
+                                               /* Update (from output fence) */
+                                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                                  "%s:   Append 1 sync checkpoint<%p> (ID=%d) to 3D Update...",
+                                                                  __func__, (void*)psUpdate3DSyncCheckpoint,
+                                                                  SyncCheckpointGetId(psUpdate3DSyncCheckpoint)));
+                                               SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrList3DUpdate,
+                                                                                                         1,
+                                                                                                         &psUpdate3DSyncCheckpoint);
+                                               if (!pauiClient3DUpdateUFOAddress)
+                                               {
+                                                       pauiClient3DUpdateUFOAddress = psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs;
+                                               }
+                                               ui32Client3DUpdateCount++;
+                                       }
+                               }
+
+                               /*
+                                * Relocate sync check points from the 3D fence that are
+                                * external to the current process, to the TA fence.
+                                * This avoids a sync lockup when dependent renders are
+                                * submitted out-of-order and a PR must be scheduled.
+                                */
+                               if (bKickTA)
+                               {
+                                       /* Search for external timeline dependencies */
+                                       CHKPT_DBG((PVR_DBG_ERROR,
+                                                          "%s: Checking 3D fence for external sync points (%d)...",
+                                                          __func__, ui32Fence3DSyncCheckpointCount));
+
+                                       for (i=0; i<ui32Fence3DSyncCheckpointCount; i++)
+                                       {
+                                               /* Check to see if the checkpoint is on a TL owned by
+                                                * another process.
+                                                */
+                                               if (SyncCheckpointGetCreator(apsFence3DSyncCheckpoints[i]) != uiCurrentProcess)
+                                               {
+                                                       /* 3D Sync point represents cross process
+                                                        * dependency, copy sync point to TA command fence. */
+                                                       CHKPT_DBG((PVR_DBG_ERROR,
+                                                                          "%s:   Append 1 sync checkpoint<%p> (ID=%d) to TA Fence...",
+                                                                          __func__, (void*)apsFence3DSyncCheckpoints[i],
+                                                                          SyncCheckpointGetId(apsFence3DSyncCheckpoints[i])));
+
+                                                       SyncAddrListAppendCheckpoints(&psRenderContext->sSyncAddrListTAFence,
+                                                                                                                 1,
+                                                                                                                 &apsFence3DSyncCheckpoints[i]);
+
+                                                       if (!pauiClientTAFenceUFOAddress)
+                                                       {
+                                                               pauiClientTAFenceUFOAddress = psRenderContext->sSyncAddrListTAFence.pasFWAddrs;
+                                                       }
+
+                                                       CHKPT_DBG((PVR_DBG_ERROR,
+                                                                          "%s:   {ui32ClientTAFenceCount was %d, now %d}",
+                                                                          __func__,
+                                                                          ui32ClientTAFenceCount,
+                                                                          ui32ClientTAFenceCount + 1));
+
+                                                       if (ui32ClientTAFenceCount == 0)
+                                                       {
+                                                               bTAFenceOnSyncCheckpointsOnly = IMG_TRUE;
+                                                       }
+
+                                                       ui32ClientTAFenceCount++;
+                                               }
+                                       }
+                               }
+
+                               CHKPT_DBG((PVR_DBG_ERROR,
+                                                  "%s:   (after pvr_sync) ui32ClientTAFenceCount=%d, "
+                                                  "ui32ClientTAUpdateCount=%d, ui32Client3DFenceCount=%d, "
+                                                  "ui32Client3DUpdateCount=%d, ui32ClientPRUpdateCount=%d,",
+                                                  __func__,
+                                                  ui32ClientTAFenceCount, ui32ClientTAUpdateCount,
+                                                  ui32Client3DFenceCount, ui32Client3DUpdateCount,
+                                                  ui32ClientPRUpdateCount));
+                       }
+               }
+
+               if (ui32ClientTAFenceCount)
+               {
+                       PVR_ASSERT(pauiClientTAFenceUFOAddress);
+                       if (!bTAFenceOnSyncCheckpointsOnly)
+                       {
+                               PVR_ASSERT(paui32ClientTAFenceValue);
+                       }
+               }
+               if (ui32ClientTAUpdateCount)
+               {
+                       PVR_ASSERT(pauiClientTAUpdateUFOAddress);
+                       if (ui32ClientTAUpdateValueCount>0)
+                       {
+                               PVR_ASSERT(paui32ClientTAUpdateValue);
+                       }
+               }
+               if (ui32Client3DFenceCount)
+               {
+                       PVR_ASSERT(pauiClient3DFenceUFOAddress);
+                       PVR_ASSERT(b3DFenceOnSyncCheckpointsOnly);
+               }
+               if (ui32Client3DUpdateCount)
+               {
+                       PVR_ASSERT(pauiClient3DUpdateUFOAddress);
+                       if (ui32Client3DUpdateValueCount>0)
+                       {
+                               PVR_ASSERT(paui32Client3DUpdateValue);
+                       }
+               }
+               if (ui32ClientPRUpdateCount)
+               {
+                       PVR_ASSERT(pauiClientPRUpdateUFOAddress);
+                       if (ui32ClientPRUpdateValueCount>0)
+                       {
+                               PVR_ASSERT(paui32ClientPRUpdateValue);
+                       }
+               }
+
+       }
+
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: ui32ClientTAFenceCount=%d, pauiClientTAFenceUFOAddress=<%p> Line ",
+                          __func__,
+                          ui32ClientTAFenceCount,
+                          (void*)paui32ClientTAFenceValue));
+       CHKPT_DBG((PVR_DBG_ERROR,
+                          "%s: ui32ClientTAUpdateCount=%d, pauiClientTAUpdateUFOAddress=<%p> Line ",
+                          __func__,
+                          ui32ClientTAUpdateCount,
+                          (void*)pauiClientTAUpdateUFOAddress));
+#if (ENABLE_TA3D_UFO_DUMP == 1)
+       DumpUfoList(ui32ClientTAFenceCount, ui32ClientTAUpdateCount,
+                   ui32Client3DFenceCount + (bTestSLRAdd3DCheck ? 1 : 0),
+                   ui32Client3DUpdateCount,
+                   pauiClientTAFenceUFOAddress, paui32ClientTAFenceValue,
+                   pauiClientTAUpdateUFOAddress, paui32ClientTAUpdateValue,
+                   pauiClient3DFenceUFOAddress, NULL,
+                   pauiClient3DUpdateUFOAddress, paui32Client3DUpdateValue);
+#endif /* (ENABLE_TA3D_UFO_DUMP == 1) */
+
+       /* Command size check */
+       if (ui32TAFenceCount != ui32ClientTAFenceCount)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "TA pre-calculated number of fences"
+                       " is different than the actual number (%u != %u)",
+                       ui32TAFenceCount, ui32ClientTAFenceCount));
+       }
+       if (ui32TAUpdateCount != ui32ClientTAUpdateCount)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "TA pre-calculated number of updates"
+                       " is different than the actual number (%u != %u)",
+                       ui32TAUpdateCount, ui32ClientTAUpdateCount));
+       }
+       if (!bTestSLRAdd3DCheck && (ui323DFenceCount != ui32Client3DFenceCount))
+       {
+               PVR_DPF((PVR_DBG_ERROR, "3D pre-calculated number of fences"
+                       " is different than the actual number (%u != %u)",
+                       ui323DFenceCount, ui32Client3DFenceCount));
+       }
+       if (ui323DUpdateCount != ui32Client3DUpdateCount)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "3D pre-calculated number of updates"
+                       " is different than the actual number (%u != %u)",
+                       ui323DUpdateCount, ui32Client3DUpdateCount));
+       }
+       if (ui32PRUpdateCount != ui32ClientPRUpdateCount)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "PR pre-calculated number of updates"
+                       " is different than the actual number (%u != %u)",
+                       ui32PRUpdateCount, ui32ClientPRUpdateCount));
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       if (bKickTA || bKick3D || bAbort)
+       {
+               sWorkloadCharacteristics.sTA3D.ui32RenderTargetSize  = ui32RenderTargetSize;
+               sWorkloadCharacteristics.sTA3D.ui32NumberOfDrawCalls = ui32NumberOfDrawCalls;
+               sWorkloadCharacteristics.sTA3D.ui32NumberOfIndices   = ui32NumberOfIndices;
+               sWorkloadCharacteristics.sTA3D.ui32NumberOfMRTs      = ui32NumberOfMRTs;
+       }
+#endif
+
+       /* Init and acquire to TA command if required */
+       if (bKickTA)
+       {
+               RGX_SERVER_RC_TA_DATA *psTAData = &psRenderContext->sTAData;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* Prepare workload estimation */
+               WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
+                               &psRenderContext->sWorkEstData,
+                               &psRenderContext->sWorkEstData.uWorkloadMatchingData.sTA3D.sDataTA,
+                               RGXFWIF_CCB_CMD_TYPE_GEOM,
+                               &sWorkloadCharacteristics,
+                               ui64DeadlineInus,
+                               &sWorkloadKickDataTA);
+#endif
+
+               /* Init the TA command helper */
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   calling RGXCmdHelperInitCmdCCB(), ui32ClientTAFenceCount=%d, ui32ClientTAUpdateCount=%d",
+                                  __func__, ui32ClientTAFenceCount, ui32ClientTAUpdateCount));
+               RGXCmdHelperInitCmdCCB_OtherData(FWCommonContextGetClientCCB(psTAData->psServerCommonContext),
+                                                ui32ClientTAFenceCount,
+                                                pauiClientTAFenceUFOAddress,
+                                                paui32ClientTAFenceValue,
+                                                ui32ClientTAUpdateCount,
+                                                pauiClientTAUpdateUFOAddress,
+                                                paui32ClientTAUpdateValue,
+                                                ui32TACmdSize,
+                                                pui8TADMCmd,
+                                                                        &pPreAddr,
+                                                                        (bKick3D ? NULL : & pPostAddr),
+                                                                        (bKick3D ? NULL : & pRMWUFOAddr),
+                                                RGXFWIF_CCB_CMD_TYPE_GEOM,
+                                                ui32ExtJobRef,
+                                                ui32IntJobRef,
+                                                ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+                                                &sWorkloadKickDataTA,
+#else
+                                                NULL,
+#endif
+                                                "TA",
+                                                bCCBStateOpen,
+                                                pasTACmdHelperData);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* The following is used to determine the offset of the command header containing
+                  the workload estimation data so that can be accessed when the KCCB is read */
+               ui32TACmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(pasTACmdHelperData);
+#endif
+
+               eError = RGXCmdHelperAcquireCmdCCB(CCB_CMD_HELPER_NUM_TA_COMMANDS, pasTACmdHelperData);
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line",
+                                          __func__, eError));
+                       goto fail_taacquirecmd;
+               }
+               else
+               {
+                       ui32TACmdCount++;
+               }
+       }
+
+       /* Only kick the 3D if required */
+       if (bKickPR)
+       {
+               RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
+
+               /*
+                       The command helper doesn't know about the PR fence so create
+                       the command with all the fences against it and later create
+                       the PR command itself which _must_ come after the PR fence.
+               */
+               sPRUFO.puiAddrUFO = uiPRFenceUFOAddress;
+               sPRUFO.ui32Value = ui32PRFenceValue;
+
+               /* Init the PR fence command helper */
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   calling RGXCmdHelperInitCmdCCB(), ui32Client3DFenceCount=%d",
+                                  __func__, ui32Client3DFenceCount));
+               RGXCmdHelperInitCmdCCB_OtherData(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+                                                ui32Client3DFenceCount + (bTestSLRAdd3DCheck ? 1 : 0),
+                                                pauiClient3DFenceUFOAddress,
+                                                NULL,
+                                                0,
+                                                NULL,
+                                                NULL,
+                                                sizeof(sPRUFO),
+                                                (IMG_UINT8*) &sPRUFO,
+                                                NULL,
+                                                NULL,
+                                                NULL,
+                                                RGXFWIF_CCB_CMD_TYPE_FENCE_PR,
+                                                ui32ExtJobRef,
+                                                ui32IntJobRef,
+                                                ui32PDumpFlags,
+                                                NULL,
+                                                "3D-PR-Fence",
+                                                bCCBStateOpen,
+                                                &pas3DCmdHelperData[ui323DCmdCount++]);
+
+               /* Init the 3D PR command helper */
+               /*
+                       Updates for Android (fence sync and Timeline sync prim) are provided in the PR-update
+                       if no 3D is present. This is so the timeline update cannot happen out of order with any
+                       other 3D already in flight for the same timeline (PR-updates are done in the 3D cCCB).
+                       This out of order timeline sync prim update could happen if we attach it to the TA update.
+               */
+               if (ui32ClientPRUpdateCount)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR,
+                                          "%s: Line %d, ui32ClientPRUpdateCount=%d, "
+                                          "pauiClientPRUpdateUFOAddress=0x%x, "
+                                          "ui32ClientPRUpdateValueCount=%d, "
+                                          "paui32ClientPRUpdateValue=0x%x",
+                                          __func__, __LINE__, ui32ClientPRUpdateCount,
+                                          pauiClientPRUpdateUFOAddress->ui32Addr,
+                                          ui32ClientPRUpdateValueCount,
+                                          (ui32ClientPRUpdateValueCount == 0) ? PVRSRV_SYNC_CHECKPOINT_SIGNALLED : *paui32ClientPRUpdateValue));
+               }
+               if (!bUseCombined3DAnd3DPR)
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR,
+                                          "%s:   calling RGXCmdHelperInitCmdCCB(), ui32ClientPRUpdateCount=%d",
+                                          __func__, ui32ClientPRUpdateCount));
+                       RGXCmdHelperInitCmdCCB_OtherData(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+                                                        0,
+                                                        NULL,
+                                                        NULL,
+                                                        ui32ClientPRUpdateCount,
+                                                        pauiClientPRUpdateUFOAddress,
+                                                        paui32ClientPRUpdateValue,
+                                                        pui83DPRDMCmd ? ui323DPRCmdSize : ui323DCmdSize, // If the client has not provided a 3DPR command, the regular 3D command should be used instead
+                                                        pui83DPRDMCmd ? pui83DPRDMCmd : pui83DDMCmd,
+                                                        NULL,
+                                                        NULL,
+                                                        NULL,
+                                                        RGXFWIF_CCB_CMD_TYPE_3D_PR,
+                                                        ui32ExtJobRef,
+                                                        ui32IntJobRef,
+                                                        ui32PDumpFlags,
+                                                        NULL,
+                                                        "3D-PR",
+                                                        bCCBStateOpen,
+                                                        &pas3DCmdHelperData[ui323DCmdCount++]);
+               }
+       }
+
+       if (bKick3D || bAbort)
+       {
+               RGX_SERVER_RC_3D_DATA *ps3DData = &psRenderContext->s3DData;
+               const RGXFWIF_CCB_CMD_TYPE e3DCmdType = bAbort ? RGXFWIF_CCB_CMD_TYPE_ABORT : RGXFWIF_CCB_CMD_TYPE_3D;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* Prepare workload estimation */
+               WorkEstPrepare(psRenderContext->psDeviceNode->pvDevice,
+                               &psRenderContext->sWorkEstData,
+                               &psRenderContext->sWorkEstData.uWorkloadMatchingData.sTA3D.sData3D,
+                               e3DCmdType,
+                               &sWorkloadCharacteristics,
+                               ui64DeadlineInus,
+                               &sWorkloadKickData3D);
+#endif
+
+               /* Init the 3D command helper */
+               RGXCmdHelperInitCmdCCB_OtherData(FWCommonContextGetClientCCB(ps3DData->psServerCommonContext),
+                                                bKickTA ? 0 : ui32Client3DFenceCount,  /* For a kick with a TA, the 3D fences are added before the PR command instead */
+                                                bKickTA ? NULL : pauiClient3DFenceUFOAddress,
+                                                NULL,
+                                                ui32Client3DUpdateCount,
+                                                pauiClient3DUpdateUFOAddress,
+                                                paui32Client3DUpdateValue,
+                                                ui323DCmdSize,
+                                                pui83DDMCmd,
+                                                (bKickTA ? NULL : & pPreAddr),
+                                                &pPostAddr,
+                                                &pRMWUFOAddr,
+                                                e3DCmdType,
+                                                ui32ExtJobRef,
+                                                ui32IntJobRef,
+                                                ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+                                                &sWorkloadKickData3D,
+#else
+                                                NULL,
+#endif
+                                                "3D",
+                                                bCCBStateOpen,
+                                                &pas3DCmdHelperData[ui323DCmdCount++]);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* The following are used to determine the offset of the command header containing the workload estimation
+                  data so that can be accessed when the KCCB is read */
+               ui323DCmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(&pas3DCmdHelperData[ui323DCmdCount - 1]);
+               ui323DFullRenderCommandOffset = RGXCmdHelperGetCommandOffset(pas3DCmdHelperData, ui323DCmdCount - 1);
+#endif
+       }
+
+       /* Protect against array overflow in RGXCmdHelperAcquireCmdCCB() */
+       if (unlikely(ui323DCmdCount > CCB_CMD_HELPER_NUM_3D_COMMANDS))
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line", __func__, eError));
+               goto fail_3dcmdinit;
+       }
+
+       if (ui323DCmdCount)
+       {
+               PVR_ASSERT(bKickPR || bKick3D);
+
+               /* Acquire space for all the 3D command(s) */
+               eError = RGXCmdHelperAcquireCmdCCB(ui323DCmdCount, pas3DCmdHelperData);
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       /* If RGXCmdHelperAcquireCmdCCB fails we skip the scheduling
+                        * of a new TA command with the same Write offset in Kernel CCB.
+                        */
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line", __func__, eError));
+                       goto fail_3dacquirecmd;
+               }
+       }
+
+       /*
+               We should acquire the space in the kernel CCB here as after this point
+               we release the commands which will take operations on server syncs
+               which can't be undone
+       */
+
+       /*
+               Everything is ready to go now, release the commands
+       */
+       if (ui32TACmdCount)
+       {
+               ui32TACmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
+               RGXCmdHelperReleaseCmdCCB(ui32TACmdCount,
+                                                                 pasTACmdHelperData,
+                                                                 "TA",
+                                                                 FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               ui32TACmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext));
+
+               /* This checks if the command would wrap around at the end of the CCB and therefore  would start at an
+                  offset of 0 rather than the current command offset */
+               if (ui32TACmdOffset < ui32TACmdOffsetWrapCheck)
+               {
+                       ui32TACommandOffset = ui32TACmdOffset;
+               }
+               else
+               {
+                       ui32TACommandOffset = 0;
+               }
+#endif
+       }
+
+       if (ui323DCmdCount)
+       {
+               ui323DCmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
+               RGXCmdHelperReleaseCmdCCB(ui323DCmdCount,
+                                                                 pas3DCmdHelperData,
+                                                                 "3D",
+                                                                 FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               ui323DCmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext));
+
+               if (ui323DCmdOffset < ui323DCmdOffsetWrapCheck)
+               {
+                       ui323DCommandOffset = ui323DCmdOffset;
+               }
+               else
+               {
+                       ui323DCommandOffset = 0;
+               }
+#endif
+       }
+
+       if (ui32TACmdCount)
+       {
+               IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext).ui32Addr;
+               RGX_CLIENT_CCB *psClientCCB = FWCommonContextGetClientCCB(psRenderContext->sTAData.psServerCommonContext);
+               CMDTA3D_SHARED *psGeomCmdShared = IMG_OFFSET_ADDR(pui8TADMCmd, 0);
+
+               sTACmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->sTAData.psServerCommonContext);
+               sTACmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+               sTACmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* Add the Workload data into the KCCB kick */
+               sTACmdKickData.ui32WorkEstCmdHeaderOffset = ui32TACommandOffset + ui32TACmdHeaderOffset;
+#else
+               sTACmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+#endif
+
+               eError = AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &sTACmdKickData.apsCleanupCtl,
+                               &sTACmdKickData.ui32NumCleanupCtl,
+                               RGXFWIF_DM_GEOM,
+                               bKickTA,
+                               psKMHWRTDataSet,
+                               psZSBuffer,
+                               psMSAAScratchBuffer);
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line",
+                                          __func__, eError));
+                       goto fail_taattachcleanupctls;
+               }
+
+               if (psGeomCmdShared)
+               {
+                       HTBLOGK(HTB_SF_MAIN_KICK_TA,
+                                       sTACmdKickData.psContext,
+                                       ui32TACmdOffset,
+                                       psGeomCmdShared->sCmn.ui32FrameNum,
+                                       ui32ExtJobRef,
+                                       ui32IntJobRef);
+               }
+
+               RGXSRV_HWPERF_ENQ(psRenderContext,
+                                 OSGetCurrentClientProcessIDKM(),
+                                 ui32FWCtx,
+                                 ui32ExtJobRef,
+                                 ui32IntJobRef,
+                                 RGX_HWPERF_KICK_TYPE_TA,
+                                 iCheckTAFence,
+                                 iUpdateTAFence,
+                                 iUpdateTATimeline,
+                                 uiCheckTAFenceUID,
+                                 uiUpdateTAFenceUID,
+                                 ui64DeadlineInus,
+                                 WORKEST_CYCLES_PREDICTION_GET(sWorkloadKickDataTA));
+
+               if (!bUseSingleFWCommand)
+               {
+                       /* Construct the kernel TA CCB command. */
+                       RGXFWIF_KCCB_CMD sTAKCCBCmd;
+                       sTAKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+                       sTAKCCBCmd.uCmdData.sCmdKickData = sTACmdKickData;
+
+                       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+                       {
+                               eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
+                                               RGXFWIF_DM_GEOM,
+                                               &sTAKCCBCmd,
+                                               ui32PDumpFlags);
+                               if (eError2 != PVRSRV_ERROR_RETRY)
+                               {
+                                       break;
+                               }
+                               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+                       } END_LOOP_UNTIL_TIMEOUT();
+               }
+
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKicKTA3DKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_taacquirecmd;
+               }
+
+               PVRGpuTraceEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
+                                       ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
+                                       RGX_HWPERF_KICK_TYPE_TA);
+       }
+
+       if (ui323DCmdCount)
+       {
+               RGXFWIF_KCCB_CMD s3DKCCBCmd = { 0 };
+               IMG_UINT32 ui32FWCtx = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext).ui32Addr;
+               RGX_CLIENT_CCB *psClientCCB = FWCommonContextGetClientCCB(psRenderContext->s3DData.psServerCommonContext);
+               CMDTA3D_SHARED *ps3DCmdShared = IMG_OFFSET_ADDR(pui83DDMCmd, 0);
+
+               s3DCmdKickData.psContext = FWCommonContextGetFWAddress(psRenderContext->s3DData.psServerCommonContext);
+               s3DCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+               s3DCmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+
+               /* Add the Workload data into the KCCB kick */
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* Store the offset to the CCCB command header so that it can be referenced when the KCCB command reaches the FW */
+               s3DCmdKickData.ui32WorkEstCmdHeaderOffset = ui323DCommandOffset + ui323DCmdHeaderOffset + ui323DFullRenderCommandOffset;
+#else
+               s3DCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+#endif
+
+               eError = AttachKickResourcesCleanupCtls((PRGXFWIF_CLEANUP_CTL *) &s3DCmdKickData.apsCleanupCtl,
+                               &s3DCmdKickData.ui32NumCleanupCtl,
+                               RGXFWIF_DM_3D,
+                               bKick3D,
+                               psKMHWRTDataSet,
+                               psZSBuffer,
+                               psMSAAScratchBuffer);
+               if (unlikely(eError != PVRSRV_OK))
+               {
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line",
+                                          __func__, eError));
+                       goto fail_3dattachcleanupctls;
+               }
+
+               if (ps3DCmdShared)
+               {
+                       HTBLOGK(HTB_SF_MAIN_KICK_3D,
+                                       s3DCmdKickData.psContext,
+                                       ui323DCmdOffset,
+                                       ps3DCmdShared->sCmn.ui32FrameNum,
+                                       ui32ExtJobRef,
+                                       ui32IntJobRef);
+               }
+
+               RGXSRV_HWPERF_ENQ(psRenderContext,
+                                 OSGetCurrentClientProcessIDKM(),
+                                 ui32FWCtx,
+                                 ui32ExtJobRef,
+                                 ui32IntJobRef,
+                                 RGX_HWPERF_KICK_TYPE_3D,
+                                 iCheck3DFence,
+                                 iUpdate3DFence,
+                                 iUpdate3DTimeline,
+                                 uiCheck3DFenceUID,
+                                 uiUpdate3DFenceUID,
+                                 ui64DeadlineInus,
+                                 WORKEST_CYCLES_PREDICTION_GET(sWorkloadKickData3D));
+
+               if (bUseSingleFWCommand)
+               {
+                       /* Construct the kernel TA/3D CCB command. */
+                       s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_COMBINED_TA_3D_KICK;
+                       s3DKCCBCmd.uCmdData.sCombinedTA3DCmdKickData.sTACmdKickData = sTACmdKickData;
+                       s3DKCCBCmd.uCmdData.sCombinedTA3DCmdKickData.s3DCmdKickData = s3DCmdKickData;
+               }
+               else
+               {
+                       /* Construct the kernel 3D CCB command. */
+                       s3DKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+                       s3DKCCBCmd.uCmdData.sCmdKickData = s3DCmdKickData;
+               }
+
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       eError2 = RGXScheduleCommand(psRenderContext->psDeviceNode->pvDevice,
+                                                                                RGXFWIF_DM_3D,
+                                                                                &s3DKCCBCmd,
+                                                                                ui32PDumpFlags);
+                       if (eError2 != PVRSRV_ERROR_RETRY)
+                       {
+                               break;
+                       }
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXKicKTA3DKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_3dacquirecmd;
+               }
+
+               PVRGpuTraceEnqueueEvent(psRenderContext->psDeviceNode->pvDevice,
+                                       ui32FWCtx, ui32ExtJobRef, ui32IntJobRef,
+                                       RGX_HWPERF_KICK_TYPE_3D);
+       }
+
+       /*
+        * Now check eError (which may have returned an error from our earlier calls
+        * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
+        * so we check it now...
+        */
+       if (unlikely(eError != PVRSRV_OK ))
+       {
+               CHKPT_DBG((PVR_DBG_ERROR, "%s: Failed, eError=%d, Line",
+                                  __func__, eError));
+               goto fail_3dacquirecmd;
+       }
+
+#if defined(NO_HARDWARE)
+       /* If NO_HARDWARE, signal the output fence's sync checkpoint and sync prim */
+       if (psUpdateTASyncCheckpoint)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   Signalling NOHW sync checkpoint [TA] <%p>, ID:%d, FwAddr=0x%x",
+                                  __func__, (void*)psUpdateTASyncCheckpoint,
+                                  SyncCheckpointGetId(psUpdateTASyncCheckpoint),
+                                  SyncCheckpointGetFirmwareAddr(psUpdateTASyncCheckpoint)));
+               SyncCheckpointSignalNoHW(psUpdateTASyncCheckpoint);
+       }
+       if (psTAFenceTimelineUpdateSync)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   Updating NOHW sync prim [TA] <%p> to %d",
+                                  __func__, (void*)psTAFenceTimelineUpdateSync,
+                                  ui32TAFenceTimelineUpdateValue));
+               SyncPrimNoHwUpdate(psTAFenceTimelineUpdateSync, ui32TAFenceTimelineUpdateValue);
+       }
+
+       if (psUpdate3DSyncCheckpoint)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   Signalling NOHW sync checkpoint [3D] <%p>, ID:%d, FwAddr=0x%x",
+                                  __func__, (void*)psUpdate3DSyncCheckpoint,
+                                  SyncCheckpointGetId(psUpdate3DSyncCheckpoint),
+                                  SyncCheckpointGetFirmwareAddr(psUpdate3DSyncCheckpoint)));
+               SyncCheckpointSignalNoHW(psUpdate3DSyncCheckpoint);
+       }
+       if (ps3DFenceTimelineUpdateSync)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   Updating NOHW sync prim [3D] <%p> to %d",
+                                  __func__, (void*)ps3DFenceTimelineUpdateSync,
+                                  ui323DFenceTimelineUpdateValue));
+               SyncPrimNoHwUpdate(ps3DFenceTimelineUpdateSync, ui323DFenceTimelineUpdateValue);
+       }
+       SyncCheckpointNoHWUpdateTimelines(NULL);
+
+#endif /* defined(NO_HARDWARE) */
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               CHKPT_DBG((PVR_DBG_ERROR,
+                                  "%s:   calling pvr_buffer_sync_kick_succeeded(psBufferSyncData=<%p>)...",
+                                  __func__, (void*)psBufferSyncData));
+               pvr_buffer_sync_kick_succeeded(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+       if (piUpdateTAFence)
+       {
+               *piUpdateTAFence = iUpdateTAFence;
+       }
+       if (piUpdate3DFence)
+       {
+               *piUpdate3DFence = iUpdate3DFence;
+       }
+
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence.
+        * NOTE: 3D fence is always submitted, either via 3D or TA(PR).
+        */
+       if (bKickTA)
+       {
+               SyncAddrListDeRefCheckpoints(ui32FenceTASyncCheckpointCount, apsFenceTASyncCheckpoints);
+       }
+       SyncAddrListDeRefCheckpoints(ui32Fence3DSyncCheckpointCount, apsFence3DSyncCheckpoints);
+
+       if (pvTAUpdateFenceFinaliseData && (iUpdateTAFence != PVRSRV_NO_FENCE))
+       {
+               SyncCheckpointFinaliseFence(psRenderContext->psDeviceNode, iUpdateTAFence,
+                                                                       pvTAUpdateFenceFinaliseData,
+                                                                       psUpdateTASyncCheckpoint, szFenceNameTA);
+       }
+       if (pv3DUpdateFenceFinaliseData && (iUpdate3DFence != PVRSRV_NO_FENCE))
+       {
+               SyncCheckpointFinaliseFence(psRenderContext->psDeviceNode, iUpdate3DFence,
+                                                                       pv3DUpdateFenceFinaliseData,
+                                                                       psUpdate3DSyncCheckpoint, szFenceName3D);
+       }
+
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceTASyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceTASyncCheckpoints);
+       }
+       if (apsFence3DSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFence3DSyncCheckpoints);
+       }
+
+       if (sTASyncData.paui32ClientUpdateValue)
+       {
+               OSFreeMem(sTASyncData.paui32ClientUpdateValue);
+       }
+       if (s3DSyncData.paui32ClientUpdateValue)
+       {
+               OSFreeMem(s3DSyncData.paui32ClientUpdateValue);
+       }
+
+#if defined(SUPPORT_VALIDATION)
+       if (bTestSLRAdd3DCheck)
+       {
+               SyncCheckpointFree(psDummySyncCheckpoint);
+       }
+#endif
+       OSLockRelease(psRenderContext->hLock);
+
+       return PVRSRV_OK;
+
+fail_3dattachcleanupctls:
+fail_taattachcleanupctls:
+fail_3dacquirecmd:
+fail_3dcmdinit:
+fail_taacquirecmd:
+       SyncAddrListRollbackCheckpoints(psRenderContext->psDeviceNode, &psRenderContext->sSyncAddrListTAFence);
+       SyncAddrListRollbackCheckpoints(psRenderContext->psDeviceNode, &psRenderContext->sSyncAddrListTAUpdate);
+       SyncAddrListRollbackCheckpoints(psRenderContext->psDeviceNode, &psRenderContext->sSyncAddrList3DFence);
+       SyncAddrListRollbackCheckpoints(psRenderContext->psDeviceNode, &psRenderContext->sSyncAddrList3DUpdate);
+       /* Where a TA-only kick (ie no 3D) is submitted, the PR update will make use of the unused 3DUpdate list.
+        * If this has happened, performing a rollback on pauiClientPRUpdateUFOAddress will simply repeat what
+        * has already been done for the sSyncAddrList3DUpdate above and result in a double decrement of the
+        * sync checkpoint's hEnqueuedCCBCount, so we need to check before rolling back the PRUpdate.
+        */
+       if (pauiClientPRUpdateUFOAddress && (pauiClientPRUpdateUFOAddress != psRenderContext->sSyncAddrList3DUpdate.pasFWAddrs))
+       {
+               SyncCheckpointRollbackFromUFO(psRenderContext->psDeviceNode, pauiClientPRUpdateUFOAddress->ui32Addr);
+       }
+
+fail_alloc_update_values_mem_3D:
+       if (iUpdate3DFence != PVRSRV_NO_FENCE)
+       {
+               SyncCheckpointRollbackFenceData(iUpdate3DFence, pv3DUpdateFenceFinaliseData);
+       }
+fail_create_3d_fence:
+fail_alloc_update_values_mem_TA:
+       if (iUpdateTAFence != PVRSRV_NO_FENCE)
+       {
+               SyncCheckpointRollbackFenceData(iUpdateTAFence, pvTAUpdateFenceFinaliseData);
+       }
+fail_create_ta_fence:
+#if !defined(SUPPORT_BUFFER_SYNC)
+err_no_buffer_sync_invalid_params:
+#endif /* !defined(SUPPORT_BUFFER_SYNC) */
+err_pr_fence_address:
+err_populate_sync_addr_list_3d_update:
+err_populate_sync_addr_list_3d_fence:
+err_populate_sync_addr_list_ta_update:
+err_populate_sync_addr_list_ta_fence:
+err_not_enough_space:
+fail_tacmdinvalfbsc:
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence.
+        * NOTE: 3D fence is always submitted, either via 3D or TA(PR).
+        */
+#if defined(SUPPORT_BUFFER_SYNC)
+       SyncAddrListDeRefCheckpoints(ui32BufferFenceSyncCheckpointCount,
+                                    apsBufferFenceSyncCheckpoints);
+#endif
+       SyncAddrListDeRefCheckpoints(ui32Fence3DSyncCheckpointCount, apsFence3DSyncCheckpoints);
+fail_resolve_input_3d_fence:
+       if (bKickTA)
+       {
+               SyncAddrListDeRefCheckpoints(ui32FenceTASyncCheckpointCount, apsFenceTASyncCheckpoints);
+       }
+fail_resolve_input_ta_fence:
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceTASyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceTASyncCheckpoints);
+       }
+       if (apsFence3DSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFence3DSyncCheckpoints);
+       }
+       if (sTASyncData.paui32ClientUpdateValue)
+       {
+               OSFreeMem(sTASyncData.paui32ClientUpdateValue);
+       }
+       if (s3DSyncData.paui32ClientUpdateValue)
+       {
+               OSFreeMem(s3DSyncData.paui32ClientUpdateValue);
+       }
+#if defined(SUPPORT_VALIDATION)
+       if (bTestSLRAdd3DCheck)
+       {
+               SyncCheckpointFree(psDummySyncCheckpoint);
+       }
+#endif
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               pvr_buffer_sync_kick_failed(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+       PVR_ASSERT(eError != PVRSRV_OK);
+       OSLockRelease(psRenderContext->hLock);
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                 PVRSRV_DEVICE_NODE * psDeviceNode,
+                                                 RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+                                                 IMG_UINT32 ui32Priority)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+       OSLockAcquire(psRenderContext->hLock);
+
+       if (psRenderContext->sTAData.ui32Priority != ui32Priority)
+       {
+               eError = ContextSetPriority(psRenderContext->sTAData.psServerCommonContext,
+                                                                       psConnection,
+                                                                       psRenderContext->psDeviceNode->pvDevice,
+                                                                       ui32Priority,
+                                                                       RGXFWIF_DM_GEOM);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to set the priority of the TA part of the rendercontext (%s)",
+                                        __func__, PVRSRVGetErrorString(eError)));
+                       goto fail_tacontext;
+               }
+               psRenderContext->sTAData.ui32Priority = ui32Priority;
+       }
+
+       if (psRenderContext->s3DData.ui32Priority != ui32Priority)
+       {
+               eError = ContextSetPriority(psRenderContext->s3DData.psServerCommonContext,
+                                                                       psConnection,
+                                                                       psRenderContext->psDeviceNode->pvDevice,
+                                                                       ui32Priority,
+                                                                       RGXFWIF_DM_3D);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                        "%s: Failed to set the priority of the 3D part of the rendercontext (%s)",
+                                        __func__, PVRSRVGetErrorString(eError)));
+                       goto fail_3dcontext;
+               }
+               psRenderContext->s3DData.ui32Priority = ui32Priority;
+       }
+
+       OSLockRelease(psRenderContext->hLock);
+       return PVRSRV_OK;
+
+fail_3dcontext:
+fail_tacontext:
+       OSLockRelease(psRenderContext->hLock);
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPropertyKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+                                                 RGX_CONTEXT_PROPERTY eContextProperty,
+                                                 IMG_UINT64 ui64Input,
+                                                 IMG_UINT64 *pui64Output)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       switch (eContextProperty)
+       {
+               case RGX_CONTEXT_PROPERTY_FLAGS:
+               {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
+                       OSLockAcquire(psRenderContext->hLock);
+                       eError = FWCommonContextSetFlags(psRenderContext->sTAData.psServerCommonContext,
+                                                        ui32ContextFlags);
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = FWCommonContextSetFlags(psRenderContext->s3DData.psServerCommonContext,
+                                                            ui32ContextFlags);
+                       }
+                       OSLockRelease(psRenderContext->hLock);
+                       break;
+               }
+
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_ERROR_NOT_SUPPORTED - asked to set unknown property (%d)", __func__, eContextProperty));
+                       eError = PVRSRV_ERROR_NOT_SUPPORTED;
+               }
+       }
+
+       return eError;
+}
+
+void DumpRenderCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                         DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                         void *pvDumpDebugFile,
+                         IMG_UINT32 ui32VerbLevel)
+{
+       DLLIST_NODE *psNode, *psNext;
+       OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock);
+       dllist_foreach_node(&psDevInfo->sRenderCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
+
+               DumpFWCommonContextInfo(psCurrentServerRenderCtx->sTAData.psServerCommonContext,
+                                       pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+               DumpFWCommonContextInfo(psCurrentServerRenderCtx->s3DData.psServerCommonContext,
+                                       pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+       }
+       OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
+}
+
+IMG_UINT32 CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       DLLIST_NODE *psNode, *psNext;
+       IMG_UINT32 ui32ContextBitMask = 0;
+
+       OSWRLockAcquireRead(psDevInfo->hRenderCtxListLock);
+
+       dllist_foreach_node(&psDevInfo->sRenderCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_RENDER_CONTEXT *psCurrentServerRenderCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_RENDER_CONTEXT, sListNode);
+               if (NULL != psCurrentServerRenderCtx->sTAData.psServerCommonContext)
+               {
+                       if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->sTAData.psServerCommonContext, RGX_KICK_TYPE_DM_TA) == PVRSRV_ERROR_CCCB_STALLED)
+                       {
+                               ui32ContextBitMask |= RGX_KICK_TYPE_DM_TA;
+                       }
+               }
+
+               if (NULL != psCurrentServerRenderCtx->s3DData.psServerCommonContext)
+               {
+                       if (CheckStalledClientCommonContext(psCurrentServerRenderCtx->s3DData.psServerCommonContext, RGX_KICK_TYPE_DM_3D) == PVRSRV_ERROR_CCCB_STALLED)
+                       {
+                               ui32ContextBitMask |= RGX_KICK_TYPE_DM_3D;
+                       }
+               }
+       }
+
+       OSWRLockReleaseRead(psDevInfo->hRenderCtxListLock);
+       return ui32ContextBitMask;
+}
+
+/*
+ * RGXRenderContextStalledKM
+ */
+PVRSRV_ERROR RGXRenderContextStalledKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext)
+{
+       RGXCheckForStalledClientContexts((PVRSRV_RGXDEV_INFO *) psRenderContext->psDeviceNode->pvDevice, IMG_TRUE);
+       return PVRSRV_OK;
+}
+
+/******************************************************************************
+ End of file (rgxta3d.c)
+******************************************************************************/
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.h b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxta3d.h
new file mode 100644 (file)
index 0000000..3e523c4
--- /dev/null
@@ -0,0 +1,503 @@
+/*************************************************************************/ /*!
+@File
+@Title          RGX TA and 3D Functionality
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Header for the RGX TA and 3D Functionality
+@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.
+*/ /**************************************************************************/
+
+#ifndef RGXTA3D_H
+#define RGXTA3D_H
+
+#include "devicemem.h"
+#include "devicemem_server.h"
+#include "device.h"
+#include "rgxdevice.h"
+#include "rgx_fwif_shared.h"
+#include "rgx_fwif_resetframework.h"
+#include "sync_server.h"
+#include "connection_server.h"
+#include "rgxdebug.h"
+#include "pvr_notifier.h"
+#include "ri_server.h"
+
+typedef struct _RGX_SERVER_RENDER_CONTEXT_ RGX_SERVER_RENDER_CONTEXT;
+typedef struct _RGX_FREELIST_ RGX_FREELIST;
+typedef struct _RGX_PMR_NODE_ RGX_PMR_NODE;
+
+/*****************************************************************************
+ * The Design of Data Storage System for Render Targets                      *
+ * ====================================================                      *
+ *   Relevant for                                                            *
+ *     understanding RGXCreateHWRTDataSet & RGXDestroyHWRTDataSet            *
+ *                                                                           *
+ *                                                                           *
+ *        +=========================================+                        *
+ *        |           RenderTargetDataSet           |                        *
+ *        +---------------|---------|---------------+                        *
+ *                        |         |                                        *
+ *                        V         V                                        *
+ *  +- - - - - - - - - - - - +   +- - - - - - - - - - - - +                  *
+ *  | KM_HW_RT_DATA_HANDLE_0 |   | KM_HW_RT_DATA_HANDLE_1 |                  *
+ *  +- - -|- - - - - - - - - +   +- - - - - - - - - | - - +                  *
+ *        |                                         |                        *
+ *        |                                         |           [UM]Client   *
+ *  ------|-----------------------------------------|----------------------- *
+ *        |                                         |               Bridge   *
+ *  ------|-----------------------------------------|----------------------- *
+ *        |                                         |           [KM]Server   *
+ *        |                                         |                        *
+ *        | KM-ptr                                  | KM-ptr                 *
+ *        V                                         V                        *
+ *  +====================+           +====================+                  *
+ *  |  KM_HW_RT_DATA_0   |           |   KM_HW_RT_DATA_1  |                  *
+ *  +-----|------------|-+           +-|------------|-----+                  *
+ *        |            |               |            |                        *
+ *        |            |               |            |                        *
+ *        |            |               |            |                        *
+ *        |            |               |            |                        *
+ *        |            | KM-ptr        | KM-ptr     |                        *
+ *        |            V               V            |                        *
+ *        |      +==========================+       |                        *
+ *        |      | HW_RT_DATA_COMMON_COOKIE |       |                        *
+ *        |      +--------------------------+       |                        *
+ *        |                   |                     |                        *
+ *        |                   |                     |                        *
+ *  ------|-------------------|---------------------|----------------------- *
+ *        |                   |                     |         [FW]Firmware   *
+ *        |                   |                     |                        *
+ *        | FW-addr           |                     | FW-addr                *
+ *        V                   |                     V                        *
+ *  +===============+         |           +===============+                  *
+ *  | HW_RT_DATA_0  |         |           | HW_RT_DATA_1  |                  *
+ *  +------------|--+         |           +--|------------+                  *
+ *               |            |              |                               *
+ *               | FW-addr    | FW-addr      | FW-addr                       *
+ *               V            V              V                               *
+ *        +=========================================+                        *
+ *        |           HW_RT_DATA_COMMON             |                        *
+ *        +-----------------------------------------+                        *
+ *                                                                           *
+ *****************************************************************************/
+
+typedef struct _RGX_HWRTDATA_COMMON_COOKIE_
+{
+       DEVMEM_MEMDESC                  *psHWRTDataCommonFwMemDesc;
+       RGXFWIF_DEV_VIRTADDR    sHWRTDataCommonFwAddr;
+       IMG_UINT32                              ui32RefCount;
+
+} RGX_HWRTDATA_COMMON_COOKIE;
+
+typedef struct _RGX_KM_HW_RT_DATASET_
+{
+       RGX_HWRTDATA_COMMON_COOKIE *psHWRTDataCommonCookie;
+
+       /* RGX_RTDATA_CLEANUP_DATA */
+       /* RGXMKIF_NUM_RTDATAS */
+    PVRSRV_DEVICE_NODE *psDeviceNode;
+       RGXFWIF_DEV_VIRTADDR sHWRTDataFwAddr;
+
+    DEVMEM_MEMDESC *psHWRTDataFwMemDesc;
+    DEVMEM_MEMDESC *psRTArrayFwMemDesc;
+    DEVMEM_MEMDESC *psRendersAccArrayFwMemDesc;
+
+    RGX_FREELIST *apsFreeLists[RGXFW_MAX_FREELISTS];
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+    DLLIST_NODE sNodeHWRTData;
+#endif
+
+} RGX_KM_HW_RT_DATASET;
+
+struct _RGX_FREELIST_ {
+       PVRSRV_RGXDEV_INFO              *psDevInfo;
+       CONNECTION_DATA                 *psConnection;
+
+       /* Free list PMR */
+       PMR                                             *psFreeListPMR;
+       IMG_DEVMEM_OFFSET_T             uiFreeListPMROffset;
+
+       /* Free list PM state PMR */
+       PMR                                             *psFreeListStatePMR;
+       IMG_DEVMEM_OFFSET_T             uiFreeListStatePMROffset;
+
+       /* Freelist config */
+       IMG_UINT32                              ui32MaxFLPages;
+       IMG_UINT32                              ui32InitFLPages;
+       IMG_UINT32                              ui32CurrentFLPages;
+       IMG_UINT32                              ui32GrowFLPages;
+       IMG_UINT32                              ui32ReadyFLPages;
+       IMG_UINT32                              ui32GrowThreshold;              /* Percentage of FL memory used that should trigger a new grow request */
+       IMG_UINT32                              ui32FreelistID;
+       IMG_UINT32                              ui32FreelistGlobalID;   /* related global freelist for this freelist */
+       IMG_UINT64                              ui64FreelistChecksum;   /* checksum over freelist content */
+       IMG_BOOL                                bCheckFreelist;                 /* freelist check enabled */
+       IMG_UINT32                              ui32RefCount;                   /* freelist reference counting */
+
+       IMG_UINT32                              ui32NumGrowReqByApp;    /* Total number of grow requests by Application */
+       IMG_UINT32                              ui32NumGrowReqByFW;             /* Total Number of grow requests by Firmware */
+       IMG_UINT32                              ui32NumHighPages;               /* High Mark of pages in the freelist */
+
+       IMG_PID                                 ownerPid;                               /* Pid of the owner of the list */
+
+       /* Memory Blocks */
+       DLLIST_NODE                             sMemoryBlockHead;
+       DLLIST_NODE                             sMemoryBlockInitHead;
+       DLLIST_NODE                             sNode;
+#if !defined(SUPPORT_SHADOW_FREELISTS)
+       /* HWRTData nodes linked to local freelist */
+       DLLIST_NODE                             sNodeHWRTDataHead;
+#endif
+
+       /* FW data structures */
+       DEVMEM_MEMDESC                  *psFWFreelistMemDesc;
+       RGXFWIF_DEV_VIRTADDR    sFreeListFWDevVAddr;
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       HASH_TABLE*                             psWorkloadHashTable;
+#endif
+};
+
+struct _RGX_PMR_NODE_ {
+       RGX_FREELIST                    *psFreeList;
+       PMR                                             *psPMR;
+       PMR_PAGELIST                    *psPageList;
+       DLLIST_NODE                             sMemoryBlock;
+       IMG_UINT32                              ui32NumPages;
+       IMG_BOOL                                bFirstPageMissing;
+#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
+       RI_HANDLE                               hRIHandle;
+#endif
+};
+
+typedef struct {
+       PVRSRV_RGXDEV_INFO              *psDevInfo;
+       DEVMEM_MEMDESC                  *psFWZSBufferMemDesc;
+       RGXFWIF_DEV_VIRTADDR    sZSBufferFWDevVAddr;
+
+       DEVMEMINT_RESERVATION   *psReservation;
+       PMR                                             *psPMR;
+       DEVMEMINT_MAPPING               *psMapping;
+       PVRSRV_MEMALLOCFLAGS_T  uiMapFlags;
+       IMG_UINT32                              ui32ZSBufferID;
+       IMG_UINT32                              ui32RefCount;
+       IMG_BOOL                                bOnDemand;
+
+       IMG_BOOL                                ui32NumReqByApp;                /* Number of Backing Requests from Application */
+       IMG_BOOL                                ui32NumReqByFW;                 /* Number of Backing Requests from Firmware */
+
+       IMG_PID                                 owner;
+
+       DLLIST_NODE     sNode;
+}RGX_ZSBUFFER_DATA;
+
+typedef struct {
+       RGX_ZSBUFFER_DATA               *psZSBuffer;
+} RGX_POPULATION;
+
+/* Dump the physical pages of a freelist */
+IMG_BOOL RGXDumpFreeListPageList(RGX_FREELIST *psFreeList);
+
+
+
+/* Create HWRTDataSet */
+PVRSRV_ERROR RGXCreateHWRTDataSet(CONNECTION_DATA          *psConnection,
+                                  PVRSRV_DEVICE_NODE       *psDeviceNode,
+                                                                 IMG_DEV_VIRTADDR          psVHeapTableDevVAddr,
+                                                                 IMG_DEV_VIRTADDR          sPMDataDevVAddr[RGXMKIF_NUM_RTDATAS],
+                                                                 IMG_DEV_VIRTADDR          sPMSecureDataDevVAddr[RGXMKIF_NUM_RTDATAS],
+                                                             RGX_FREELIST                 *apsFreeLists[RGXMKIF_NUM_RTDATA_FREELISTS],
+                                                             IMG_UINT32                ui32ScreenPixelMax,
+                                                             IMG_UINT64                ui64PPPMultiSampleCtl,
+                                                             IMG_UINT32                ui32TEStride,
+                                                             IMG_DEV_VIRTADDR          asTailPtrsDevVAddr[RGXMKIF_NUM_GEOMDATAS],
+                                                             IMG_UINT32                ui32TPCSize,
+                                                             IMG_UINT32                ui32TEScreen,
+                                                             IMG_UINT32                ui32TEAA,
+                                                             IMG_UINT32                ui32TEMTILE1,
+                                                             IMG_UINT32                ui32TEMTILE2,
+                                                             IMG_UINT32                ui32RgnStride,
+                                                             IMG_UINT32                ui32ISPMergeLowerX,
+                                                             IMG_UINT32                ui32ISPMergeLowerY,
+                                                             IMG_UINT32                ui32ISPMergeUpperX,
+                                                             IMG_UINT32                ui32ISPMergeUpperY,
+                                                             IMG_UINT32                ui32ISPMergeScaleX,
+                                                             IMG_UINT32                ui32ISPMergeScaleY,
+                                                             IMG_UINT16                ui16MaxRTs,
+                                                             RGX_KM_HW_RT_DATASET     *pasKMHWRTDataSet[RGXMKIF_NUM_RTDATAS]);
+
+/* Destroy HWRTDataSet */
+PVRSRV_ERROR RGXDestroyHWRTDataSet(RGX_KM_HW_RT_DATASET *psKmHwRTDataSet);
+
+/*
+       RGXCreateZSBuffer
+*/
+PVRSRV_ERROR RGXCreateZSBufferKM(CONNECTION_DATA * psConnection,
+                                 PVRSRV_DEVICE_NODE    * psDeviceNode,
+                                 DEVMEMINT_RESERVATION *psReservation,
+                                 PMR                                   *psPMR,
+                                 PVRSRV_MEMALLOCFLAGS_T                uiMapFlags,
+                                 RGX_ZSBUFFER_DATA                     **ppsZSBuffer);
+
+/*
+       RGXDestroyZSBufferKM
+*/
+PVRSRV_ERROR RGXDestroyZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer);
+
+
+/*
+ * RGXBackingZSBuffer()
+ *
+ * Backs ZS-Buffer with physical pages
+ */
+PVRSRV_ERROR
+RGXBackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer);
+
+/*
+ * RGXPopulateZSBufferKM()
+ *
+ * Backs ZS-Buffer with physical pages (called by Bridge calls)
+ */
+PVRSRV_ERROR RGXPopulateZSBufferKM(RGX_ZSBUFFER_DATA *psZSBuffer,
+                                                                  RGX_POPULATION **ppsPopulation);
+
+/*
+ * RGXUnbackingZSBuffer()
+ *
+ * Frees ZS-Buffer's physical pages
+ */
+PVRSRV_ERROR RGXUnbackingZSBuffer(RGX_ZSBUFFER_DATA *psZSBuffer);
+
+/*
+ * RGXUnpopulateZSBufferKM()
+ *
+ * Frees ZS-Buffer's physical pages (called by Bridge calls)
+ */
+PVRSRV_ERROR RGXUnpopulateZSBufferKM(RGX_POPULATION *psPopulation);
+
+/*
+       RGXProcessRequestZSBufferBacking
+*/
+void RGXProcessRequestZSBufferBacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                         IMG_UINT32 ui32ZSBufferID);
+
+/*
+       RGXProcessRequestZSBufferUnbacking
+*/
+void RGXProcessRequestZSBufferUnbacking(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                               IMG_UINT32 ui32ZSBufferID);
+
+/*
+       RGXGrowFreeList
+*/
+PVRSRV_ERROR RGXGrowFreeList(RGX_FREELIST *psFreeList,
+                             IMG_UINT32 ui32NumPages,
+                             PDLLIST_NODE pListHeader);
+
+/* Create free list */
+PVRSRV_ERROR RGXCreateFreeList(CONNECTION_DATA      *psConnection,
+                               PVRSRV_DEVICE_NODE      *psDeviceNode,
+                                                          IMG_HANDLE                   hMemCtxPrivData,
+                                                          IMG_UINT32                   ui32MaxFLPages,
+                                                          IMG_UINT32                   ui32InitFLPages,
+                                                          IMG_UINT32                   ui32GrowFLPages,
+                               IMG_UINT32           ui32GrowParamThreshold,
+                                                          RGX_FREELIST                 *psGlobalFreeList,
+                                                          IMG_BOOL                             bCheckFreelist,
+                                                          IMG_DEV_VIRTADDR             sFreeListBaseDevVAddr,
+                                                          IMG_DEV_VIRTADDR             sFreeListStateDevVAddr,
+                                                          PMR                                  *psFreeListPMR,
+                                                          IMG_DEVMEM_OFFSET_T  uiFreeListPMROffset,
+                                                          PMR                                  *psFreeListStatePMR,
+                                                          IMG_DEVMEM_OFFSET_T  uiFreeListStatePMROffset,
+                                                          RGX_FREELIST                 **ppsFreeList);
+
+/* Destroy free list */
+PVRSRV_ERROR RGXDestroyFreeList(RGX_FREELIST *psFreeList);
+
+/*
+       RGXProcessRequestGrow
+*/
+void RGXProcessRequestGrow(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                  IMG_UINT32 ui32FreelistID);
+
+
+/* Reconstruct free list after Hardware Recovery */
+void RGXProcessRequestFreelistsReconstruction(PVRSRV_RGXDEV_INFO *psDevInfo,
+                                                                                         IMG_UINT32 ui32FreelistsCount,
+                                                                                         const IMG_UINT32 *paui32Freelists);
+
+/*!
+*******************************************************************************
+
+ @Function     PVRSRVRGXCreateRenderContextKM
+
+ @Description
+       Server-side implementation of RGXCreateRenderContext
+
+ @Input pvDeviceNode - device node
+ @Input ui32Priority - context priority
+ @Input hMemCtxPrivData - memory context private data
+ @Input ui32PackedCCBSizeU8888 :
+               ui8TACCBAllocSizeLog2 - TA CCB size
+               ui8TACCBMaxAllocSizeLog2 - maximum size to which TA CCB can grow
+               ui83DCCBAllocSizeLog2 - 3D CCB size
+               ui83DCCBMaxAllocSizeLog2 - maximum size to which 3D CCB can grow
+ @Input ui32ContextFlags - flags which specify properties of the context
+ @Output ppsRenderContext - clean up data
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXCreateRenderContextKM(CONNECTION_DATA                            *psConnection,
+                                                                                       PVRSRV_DEVICE_NODE                      *psDeviceNode,
+                                                                                       IMG_UINT32                                      ui32Priority,
+                                                                                       IMG_UINT32                                      ui32FrameworkCommandSize,
+                                                                                       IMG_PBYTE                                       pabyFrameworkCommand,
+                                                                                       IMG_HANDLE                                      hMemCtxPrivData,
+                                                                                       IMG_UINT32                                      ui32StaticRenderContextStateSize,
+                                                                                       IMG_PBYTE                                       pStaticRenderContextState,
+                                                                                       IMG_UINT32                                      ui32PackedCCBSizeU8888,
+                                                                                       IMG_UINT32                                      ui32ContextFlags,
+                                                                                       IMG_UINT64                                      ui64RobustnessAddress,
+                                                                                       IMG_UINT32                                      ui32MaxTADeadlineMS,
+                                                                                       IMG_UINT32                                      ui32Max3DDeadlineMS,
+                                                                                       RGX_SERVER_RENDER_CONTEXT       **ppsRenderContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function     PVRSRVRGXDestroyRenderContextKM
+
+ @Description
+       Server-side implementation of RGXDestroyRenderContext
+
+ @Input psRenderContext -
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXDestroyRenderContextKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext);
+
+
+/*!
+*******************************************************************************
+
+ @Function     PVRSRVRGXKickTA3DKM
+
+ @Description
+       Server-side implementation of RGXKickTA3D
+
+ @Input psRTDataCleanup - RT data associated with the kick (or NULL)
+ @Input psZBuffer - Z-buffer associated with the kick (or NULL)
+ @Input psSBuffer - S-buffer associated with the kick (or NULL)
+
+ @Return   PVRSRV_ERROR
+
+******************************************************************************/
+PVRSRV_ERROR PVRSRVRGXKickTA3DKM(RGX_SERVER_RENDER_CONTEXT     *psRenderContext,
+                                                                IMG_UINT32                                     ui32ClientTAFenceCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClientTAFenceSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32ClientTAFenceSyncOffset,
+                                                                IMG_UINT32                                     *paui32ClientTAFenceValue,
+                                                                IMG_UINT32                                     ui32ClientTAUpdateCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClientUpdateSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32ClientUpdateSyncOffset,
+                                                                IMG_UINT32                                     *paui32ClientTAUpdateValue,
+                                                                IMG_UINT32                                     ui32Client3DUpdateCount,
+                                                                SYNC_PRIMITIVE_BLOCK           **apsClient3DUpdateSyncPrimBlock,
+                                                                IMG_UINT32                                     *paui32Client3DUpdateSyncOffset,
+                                                                IMG_UINT32                                     *paui32Client3DUpdateValue,
+                                                                SYNC_PRIMITIVE_BLOCK           *psPRSyncPrimBlock,
+                                                                IMG_UINT32                                     ui32PRSyncOffset,
+                                                                IMG_UINT32                                     ui32PRFenceValue,
+                                                                PVRSRV_FENCE                           iCheckFence,
+                                                                PVRSRV_TIMELINE                        iUpdateTimeline,
+                                                                PVRSRV_FENCE                           *piUpdateFence,
+                                                                IMG_CHAR                                       szFenceName[PVRSRV_SYNC_NAME_LENGTH],
+                                                                PVRSRV_FENCE                           iCheckFence3D,
+                                                                PVRSRV_TIMELINE                        iUpdateTimeline3D,
+                                                                PVRSRV_FENCE                           *piUpdateFence3D,
+                                                                IMG_CHAR                                       szFenceName3D[PVRSRV_SYNC_NAME_LENGTH],
+                                                                IMG_UINT32                                     ui32TACmdSize,
+                                                                IMG_PBYTE                                      pui8TADMCmd,
+                                                                IMG_UINT32                                     ui323DPRCmdSize,
+                                                                IMG_PBYTE                                      pui83DPRDMCmd,
+                                                                IMG_UINT32                                     ui323DCmdSize,
+                                                                IMG_PBYTE                                      pui83DDMCmd,
+                                                                IMG_UINT32                                     ui32ExtJobRef,
+                                                                IMG_BOOL                                       bKickTA,
+                                                                IMG_BOOL                                       bKickPR,
+                                                                IMG_BOOL                                       bKick3D,
+                                                                IMG_BOOL                                       bAbort,
+                                                                IMG_UINT32                                     ui32PDumpFlags,
+                                                                RGX_KM_HW_RT_DATASET           *psKMHWRTDataSet,
+                                                                RGX_ZSBUFFER_DATA                      *psZSBuffer,
+                                                                RGX_ZSBUFFER_DATA                      *psMSAAScratchBuffer,
+                                                                IMG_UINT32                                     ui32SyncPMRCount,
+                                                                IMG_UINT32                                     *paui32SyncPMRFlags,
+                                                                PMR                                            **ppsSyncPMRs,
+                                                                IMG_UINT32                                     ui32RenderTargetSize,
+                                                                IMG_UINT32                                     ui32NumberOfDrawCalls,
+                                                                IMG_UINT32                                     ui32NumberOfIndices,
+                                                                IMG_UINT32                                     ui32NumberOfMRTs,
+                                                                IMG_UINT64                                     ui64DeadlineInus);
+
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                 PVRSRV_DEVICE_NODE * psDevNode,
+                                                 RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+                                                 IMG_UINT32 ui32Priority);
+
+PVRSRV_ERROR PVRSRVRGXSetRenderContextPropertyKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext,
+                                                                                                RGX_CONTEXT_PROPERTY eContextProperty,
+                                                                                                IMG_UINT64 ui64Input,
+                                                                                                IMG_UINT64 *pui64Output);
+
+/* Debug - Dump debug info of render contexts on this device */
+void DumpRenderCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                         DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                         void *pvDumpDebugFile,
+                         IMG_UINT32 ui32VerbLevel);
+
+/* Debug/Watchdog - check if client contexts are stalled */
+IMG_UINT32 CheckForStalledClientRenderCtxt(PVRSRV_RGXDEV_INFO *psDevInfo);
+
+PVRSRV_ERROR RGXRenderContextStalledKM(RGX_SERVER_RENDER_CONTEXT *psRenderContext);
+
+#endif /* RGXTA3D_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxtdmtransfer.c b/drivers/gpu/drm/img/img-rogue/services/server/devices/volcanic/rgxtdmtransfer.c
new file mode 100644 (file)
index 0000000..3454e7f
--- /dev/null
@@ -0,0 +1,1334 @@
+/*************************************************************************/ /*!
+@File           rgxtdmtransfer.c
+@Title          Device specific TDM transfer queue routines
+@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description    Device specific functions
+@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.
+*/ /**************************************************************************/
+
+#include "pdump_km.h"
+#include "rgxdevice.h"
+#include "rgxccb.h"
+#include "rgxutils.h"
+#include "rgxfwutils.h"
+#include "rgxtdmtransfer.h"
+#include "rgx_tq_shared.h"
+#include "rgxmem.h"
+#include "allocmem.h"
+#include "devicemem.h"
+#include "devicemem_pdump.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "pvrsrv.h"
+#include "rgx_memallocflags.h"
+#include "rgxhwperf.h"
+#include "ospvr_gputrace.h"
+#include "htbuffer.h"
+#include "rgxshader.h"
+
+#include "pdump_km.h"
+
+#include "sync_server.h"
+#include "sync_internal.h"
+#include "sync.h"
+
+#if defined(SUPPORT_BUFFER_SYNC)
+#include "pvr_buffer_sync.h"
+#endif
+
+#if defined(SUPPORT_VALIDATION) && defined(SUPPORT_SOC_TIMER)
+#include "validation_soc.h"
+#endif
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+#include "rgxworkest.h"
+#endif
+
+#include "rgxtimerquery.h"
+
+/* Enable this to dump the compiled list of UFOs prior to kick call */
+#define ENABLE_TDM_UFO_DUMP    0
+
+//#define TDM_CHECKPOINT_DEBUG 1
+
+#if defined(TDM_CHECKPOINT_DEBUG)
+#define CHKPT_DBG(X) PVR_DPF(X)
+#else
+#define CHKPT_DBG(X)
+#endif
+
+typedef struct {
+       RGX_SERVER_COMMON_CONTEXT * psServerCommonContext;
+       IMG_UINT32                  ui32Priority;
+#if defined(SUPPORT_BUFFER_SYNC)
+       struct pvr_buffer_sync_context *psBufferSyncContext;
+#endif
+} RGX_SERVER_TQ_TDM_DATA;
+
+
+struct _RGX_SERVER_TQ_TDM_CONTEXT_ {
+       PVRSRV_DEVICE_NODE      *psDeviceNode;
+       DEVMEM_MEMDESC          *psFWTransferContextMemDesc;
+       DEVMEM_MEMDESC          *psFWFrameworkMemDesc;
+       IMG_UINT32              ui32Flags;
+       RGX_SERVER_TQ_TDM_DATA  sTDMData;
+       DLLIST_NODE             sListNode;
+       SYNC_ADDR_LIST          sSyncAddrListFence;
+       SYNC_ADDR_LIST          sSyncAddrListUpdate;
+       POS_LOCK                hLock;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WORKEST_HOST_DATA       sWorkEstData;
+#endif
+};
+
+static PVRSRV_ERROR _CreateTDMTransferContext(
+       CONNECTION_DATA         * psConnection,
+       PVRSRV_DEVICE_NODE      * psDeviceNode,
+       DEVMEM_MEMDESC          * psAllocatedMemDesc,
+       IMG_UINT32                ui32AllocatedOffset,
+       SERVER_MMU_CONTEXT      * psServerMMUContext,
+       DEVMEM_MEMDESC          * psFWMemContextMemDesc,
+       IMG_UINT32                ui32Priority,
+       RGX_COMMON_CONTEXT_INFO * psInfo,
+       RGX_SERVER_TQ_TDM_DATA  * psTDMData,
+       IMG_UINT32                ui32CCBAllocSizeLog2,
+       IMG_UINT32                ui32CCBMaxAllocSizeLog2,
+       IMG_UINT32                ui32ContextFlags,
+       IMG_UINT64                ui64RobustnessAddress)
+{
+       PVRSRV_ERROR eError;
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       psTDMData->psBufferSyncContext =
+               pvr_buffer_sync_context_create(psDeviceNode->psDevConfig->pvOSDevice,
+                                                                          "rogue-tdm");
+       if (IS_ERR(psTDMData->psBufferSyncContext))
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "%s: failed to create buffer_sync context (err=%ld)",
+                                __func__, PTR_ERR(psTDMData->psBufferSyncContext)));
+
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto fail_buffer_sync_context_create;
+       }
+#endif
+
+       eError = FWCommonContextAllocate(
+                       psConnection,
+                       psDeviceNode,
+                       REQ_TYPE_TQ_TDM,
+                       RGXFWIF_DM_TDM,
+                       psServerMMUContext,
+                       psAllocatedMemDesc,
+                       ui32AllocatedOffset,
+                       psFWMemContextMemDesc,
+                       NULL,
+                       ui32CCBAllocSizeLog2 ? ui32CCBAllocSizeLog2 : RGX_TDM_CCB_SIZE_LOG2,
+                       ui32CCBMaxAllocSizeLog2 ? ui32CCBMaxAllocSizeLog2 : RGX_TDM_CCB_MAX_SIZE_LOG2,
+                       ui32ContextFlags,
+                       ui32Priority,
+                       UINT_MAX, /* max deadline MS */
+                       ui64RobustnessAddress,
+                       psInfo,
+                       &psTDMData->psServerCommonContext);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_contextalloc;
+       }
+
+       psTDMData->ui32Priority = ui32Priority;
+       return PVRSRV_OK;
+
+fail_contextalloc:
+#if defined(SUPPORT_BUFFER_SYNC)
+       pvr_buffer_sync_context_destroy(psTDMData->psBufferSyncContext);
+       psTDMData->psBufferSyncContext = NULL;
+fail_buffer_sync_context_create:
+#endif
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+
+static PVRSRV_ERROR _DestroyTDMTransferContext(
+       RGX_SERVER_TQ_TDM_DATA  * psTDMData,
+       PVRSRV_DEVICE_NODE      * psDeviceNode)
+{
+       PVRSRV_ERROR eError;
+
+       /* Check if the FW has finished with this resource ... */
+       eError = RGXFWRequestCommonContextCleanUp(
+               psDeviceNode,
+               psTDMData->psServerCommonContext,
+               RGXFWIF_DM_TDM,
+               PDUMP_FLAGS_CONTINUOUS);
+       if (eError == PVRSRV_ERROR_RETRY)
+       {
+               return eError;
+       }
+       else if (eError != PVRSRV_OK)
+       {
+               PVR_LOG(("%s: Unexpected error from RGXFWRequestCommonContextCleanUp (%s)",
+                                __func__,
+                                PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       /* ... it has so we can free it's resources */
+       FWCommonContextFree(psTDMData->psServerCommonContext);
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       pvr_buffer_sync_context_destroy(psTDMData->psBufferSyncContext);
+       psTDMData->psBufferSyncContext = NULL;
+#endif
+
+       return PVRSRV_OK;
+}
+
+/*
+ * PVRSRVCreateTransferContextKM
+ */
+PVRSRV_ERROR PVRSRVRGXTDMCreateTransferContextKM(
+       CONNECTION_DATA            * psConnection,
+       PVRSRV_DEVICE_NODE         * psDeviceNode,
+       IMG_UINT32                   ui32Priority,
+       IMG_UINT32                   ui32FrameworkCommandSize,
+       IMG_PBYTE                    pabyFrameworkCommand,
+       IMG_HANDLE                   hMemCtxPrivData,
+       IMG_UINT32                   ui32PackedCCBSizeU88,
+       IMG_UINT32                   ui32ContextFlags,
+       IMG_UINT64                   ui64RobustnessAddress,
+       RGX_SERVER_TQ_TDM_CONTEXT ** ppsTransferContext)
+{
+       RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext;
+
+       DEVMEM_MEMDESC          * psFWMemContextMemDesc = RGXGetFWMemDescFromMemoryContextHandle(hMemCtxPrivData);
+       PVRSRV_RGXDEV_INFO      * psDevInfo = psDeviceNode->pvDevice;
+       RGX_COMMON_CONTEXT_INFO   sInfo = {NULL};
+       PVRSRV_ERROR              eError = PVRSRV_OK;
+
+       /* Allocate the server side structure */
+       *ppsTransferContext = NULL;
+       psTransferContext = OSAllocZMem(sizeof(*psTransferContext));
+       if (psTransferContext == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       /*
+               Create the FW transfer context, this has the TDM common
+               context embedded within it
+        */
+       eError = DevmemFwAllocate(psDevInfo,
+                       sizeof(RGXFWIF_FWTDMCONTEXT),
+                       RGX_FWCOMCTX_ALLOCFLAGS,
+                       "FwTransferContext",
+                       &psTransferContext->psFWTransferContextMemDesc);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_fwtransfercontext;
+       }
+
+       eError = OSLockCreate(&psTransferContext->hLock);
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create lock (%s)",
+                                                                       __func__,
+                                               PVRSRVGetErrorString(eError)));
+               goto fail_lockcreate;
+       }
+
+       psTransferContext->psDeviceNode = psDeviceNode;
+
+       if (ui32FrameworkCommandSize)
+       {
+               eError = PVRSRVRGXFrameworkCreateKM(psDeviceNode,
+                               &psTransferContext->psFWFrameworkMemDesc,
+                               ui32FrameworkCommandSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to allocate firmware GPU framework state (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcreate;
+               }
+
+               /* Copy the Framework client data into the framework buffer */
+               eError = PVRSRVRGXFrameworkCopyCommand(psDeviceNode,
+                               psTransferContext->psFWFrameworkMemDesc,
+                               pabyFrameworkCommand,
+                               ui32FrameworkCommandSize);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Failed to populate the framework buffer (%s)",
+                                       __func__,
+                                       PVRSRVGetErrorString(eError)));
+                       goto fail_frameworkcopy;
+               }
+               sInfo.psFWFrameworkMemDesc = psTransferContext->psFWFrameworkMemDesc;
+       }
+
+       eError = _CreateTDMTransferContext(psConnection,
+                                          psDeviceNode,
+                                          psTransferContext->psFWTransferContextMemDesc,
+                                          offsetof(RGXFWIF_FWTDMCONTEXT, sTDMContext),
+                                          hMemCtxPrivData,
+                                          psFWMemContextMemDesc,
+                                          ui32Priority,
+                                          &sInfo,
+                                          &psTransferContext->sTDMData,
+                                                                          U32toU8_Unpack1(ui32PackedCCBSizeU88),
+                                                                          U32toU8_Unpack2(ui32PackedCCBSizeU88),
+                                          ui32ContextFlags,
+                                          ui64RobustnessAddress);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_tdmtransfercontext;
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WorkEstInitTDM(psDevInfo, &psTransferContext->sWorkEstData);
+#endif
+
+       SyncAddrListInit(&psTransferContext->sSyncAddrListFence);
+       SyncAddrListInit(&psTransferContext->sSyncAddrListUpdate);
+
+       OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+       dllist_add_to_tail(&(psDevInfo->sTDMCtxtListHead), &(psTransferContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+       *ppsTransferContext = psTransferContext;
+
+       return PVRSRV_OK;
+
+fail_tdmtransfercontext:
+fail_frameworkcopy:
+       if (psTransferContext->psFWFrameworkMemDesc != NULL)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
+       }
+fail_frameworkcreate:
+       OSLockDestroy(psTransferContext->hLock);
+fail_lockcreate:
+       DevmemFwUnmapAndFree(psDevInfo, psTransferContext->psFWTransferContextMemDesc);
+fail_fwtransfercontext:
+       OSFreeMem(psTransferContext);
+       PVR_ASSERT(eError != PVRSRV_OK);
+       *ppsTransferContext = NULL;
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXTDMGetSharedMemoryKM(
+       CONNECTION_DATA           * psConnection,
+       PVRSRV_DEVICE_NODE        * psDeviceNode,
+       PMR                      ** ppsCLIPMRMem,
+       PMR                      ** ppsUSCPMRMem)
+{
+       PVRSRVTQAcquireShaders(psDeviceNode, ppsCLIPMRMem, ppsUSCPMRMem);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRGXTDMReleaseSharedMemoryKM(PMR * psPMRMem)
+{
+       PVR_UNREFERENCED_PARAMETER(psPMRMem);
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRGXTDMDestroyTransferContextKM(RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext)
+{
+       PVRSRV_ERROR eError;
+       PVRSRV_RGXDEV_INFO *psDevInfo = psTransferContext->psDeviceNode->pvDevice;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_FWTDMCONTEXT    *psFWTransferContext;
+       IMG_UINT32 ui32WorkEstCCBSubmitted;
+
+       eError = DevmemAcquireCpuVirtAddr(psTransferContext->psFWTransferContextMemDesc,
+                       (void **)&psFWTransferContext);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to map firmware transfer context (%s)",
+                               __func__,
+                               PVRSRVGetErrorString(eError)));
+               return eError;
+       }
+
+       ui32WorkEstCCBSubmitted = psFWTransferContext->ui32WorkEstCCBSubmitted;
+
+       DevmemReleaseCpuVirtAddr(psTransferContext->psFWTransferContextMemDesc);
+
+       /* Check if all of the workload estimation CCB commands for this workload are read */
+       if (ui32WorkEstCCBSubmitted != psTransferContext->sWorkEstData.ui32WorkEstCCBReceived)
+       {
+               PVR_DPF((PVR_DBG_WARNING,
+                               "%s: WorkEst # cmds submitted (%u) and received (%u) mismatch",
+                               __func__, ui32WorkEstCCBSubmitted,
+                               psTransferContext->sWorkEstData.ui32WorkEstCCBReceived));
+
+               return PVRSRV_ERROR_RETRY;
+       }
+#endif
+
+
+       /* remove node from list before calling destroy - as destroy, if successful
+        * will invalidate the node
+        * must be re-added if destroy fails
+        */
+       OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+       dllist_remove_node(&(psTransferContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+
+
+       eError = _DestroyTDMTransferContext(&psTransferContext->sTDMData,
+                                           psTransferContext->psDeviceNode);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_destroyTDM;
+       }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       WorkEstDeInitTDM(psDevInfo, &psTransferContext->sWorkEstData);
+#endif
+
+       SyncAddrListDeinit(&psTransferContext->sSyncAddrListFence);
+       SyncAddrListDeinit(&psTransferContext->sSyncAddrListUpdate);
+
+       if (psTransferContext->psFWFrameworkMemDesc != NULL)
+       {
+               DevmemFwUnmapAndFree(psDevInfo, psTransferContext->psFWFrameworkMemDesc);
+       }
+       DevmemFwUnmapAndFree(psDevInfo, psTransferContext->psFWTransferContextMemDesc);
+
+       OSLockDestroy(psTransferContext->hLock);
+
+       OSFreeMem(psTransferContext);
+
+       return PVRSRV_OK;
+
+fail_destroyTDM:
+
+       OSWRLockAcquireWrite(psDevInfo->hTDMCtxListLock);
+       dllist_add_to_tail(&(psDevInfo->sTDMCtxtListHead), &(psTransferContext->sListNode));
+       OSWRLockReleaseWrite(psDevInfo->hTDMCtxListLock);
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+
+/*
+ * PVRSRVSubmitTQ3DKickKM
+ */
+PVRSRV_ERROR PVRSRVRGXTDMSubmitTransferKM(
+       RGX_SERVER_TQ_TDM_CONTEXT * psTransferContext,
+       IMG_UINT32                  ui32PDumpFlags,
+       IMG_UINT32                  ui32ClientUpdateCount,
+       SYNC_PRIMITIVE_BLOCK     ** pauiClientUpdateUFODevVarBlock,
+       IMG_UINT32                * paui32ClientUpdateSyncOffset,
+       IMG_UINT32                * paui32ClientUpdateValue,
+       PVRSRV_FENCE                iCheckFence,
+       PVRSRV_TIMELINE             iUpdateTimeline,
+       PVRSRV_FENCE              * piUpdateFence,
+       IMG_CHAR                    szUpdateFenceName[PVRSRV_SYNC_NAME_LENGTH],
+       IMG_UINT32                  ui32FWCommandSize,
+       IMG_UINT8                 * pui8FWCommand,
+       IMG_UINT32                  ui32ExtJobRef,
+       IMG_UINT32                  ui32SyncPMRCount,
+       IMG_UINT32                * paui32SyncPMRFlags,
+       PMR                      ** ppsSyncPMRs,
+       IMG_UINT32                  ui32TDMCharacteristic1,
+       IMG_UINT32                  ui32TDMCharacteristic2,
+       IMG_UINT64                  ui64DeadlineInus)
+{
+       PVRSRV_DEVICE_NODE *psDeviceNode = psTransferContext->psDeviceNode;
+       RGX_CCB_CMD_HELPER_DATA *psCmdHelper;
+       PRGXFWIF_UFO_ADDR * pauiIntFenceUFOAddress   = NULL;
+       PRGXFWIF_UFO_ADDR * pauiIntUpdateUFOAddress  = NULL;
+       IMG_UINT32          ui32IntClientFenceCount  = 0;
+       IMG_UINT32        * paui32IntUpdateValue     = paui32ClientUpdateValue;
+       IMG_UINT32          ui32IntClientUpdateCount = ui32ClientUpdateCount;
+       PVRSRV_ERROR eError;
+       PVRSRV_ERROR eError2;
+       PVRSRV_FENCE iUpdateFence = PVRSRV_NO_FENCE;
+       PVRSRV_RGXDEV_INFO  *psDevInfo = FWCommonContextGetRGXDevInfo(psTransferContext->sTDMData.psServerCommonContext);
+       RGX_CLIENT_CCB      *psClientCCB = FWCommonContextGetClientCCB(psTransferContext->sTDMData.psServerCommonContext);
+       IMG_UINT32          ui32IntJobRef = OSAtomicIncrement(&psDevInfo->iCCBSubmissionOrdinal);
+
+       IMG_UINT64          ui64FBSCEntryMask;
+
+       IMG_UINT32 ui32CmdOffset = 0;
+       IMG_BOOL bCCBStateOpen;
+
+       PRGXFWIF_TIMESTAMP_ADDR pPreAddr;
+       PRGXFWIF_TIMESTAMP_ADDR pPostAddr;
+       PRGXFWIF_UFO_ADDR       pRMWUFOAddr;
+
+       IMG_UINT64               uiCheckFenceUID = 0;
+       IMG_UINT64               uiUpdateFenceUID = 0;
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       RGXFWIF_WORKEST_KICK_DATA sWorkloadKickDataTransfer = {0};
+       IMG_UINT32 ui32TDMWorkloadDataRO = 0;
+       IMG_UINT32 ui32TDMCmdHeaderOffset = 0;
+       IMG_UINT32 ui32TDMCmdOffsetWrapCheck = 0;
+       RGX_WORKLOAD sWorkloadCharacteristics = {0};
+#endif
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       struct pvr_buffer_sync_append_data *psBufferSyncData = NULL;
+       PSYNC_CHECKPOINT *apsBufferFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32BufferFenceSyncCheckpointCount = 0;
+       PSYNC_CHECKPOINT psBufferUpdateSyncCheckpoint = NULL;
+#endif
+
+       PSYNC_CHECKPOINT psUpdateSyncCheckpoint = NULL;
+       PSYNC_CHECKPOINT *apsFenceSyncCheckpoints = NULL;
+       IMG_UINT32 ui32FenceSyncCheckpointCount = 0;
+       IMG_UINT32 *pui32IntAllocatedUpdateValues = NULL;
+       PVRSRV_CLIENT_SYNC_PRIM *psFenceTimelineUpdateSync = NULL;
+       IMG_UINT32 ui32FenceTimelineUpdateValue = 0;
+       void *pvUpdateFenceFinaliseData = NULL;
+
+       if (iUpdateTimeline >= 0 && !piUpdateFence)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+#if !defined(SUPPORT_WORKLOAD_ESTIMATION)
+       PVR_UNREFERENCED_PARAMETER(ui32TDMCharacteristic1);
+       PVR_UNREFERENCED_PARAMETER(ui32TDMCharacteristic2);
+       PVR_UNREFERENCED_PARAMETER(ui64DeadlineInus);
+#endif
+
+       /* Ensure we haven't been given a null ptr to
+        * update values if we have been told we
+        * have updates
+        */
+       if (ui32ClientUpdateCount > 0)
+       {
+               PVR_LOG_RETURN_IF_FALSE(paui32ClientUpdateValue != NULL,
+                                       "paui32ClientUpdateValue NULL but "
+                                       "ui32ClientUpdateCount > 0",
+                                       PVRSRV_ERROR_INVALID_PARAMS);
+       }
+
+       /* Ensure the string is null-terminated (Required for safety) */
+       szUpdateFenceName[31] = '\0';
+
+       if (ui32SyncPMRCount != 0)
+       {
+               if (!ppsSyncPMRs)
+               {
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+               }
+       }
+
+       OSLockAcquire(psTransferContext->hLock);
+
+       /* We can't allocate the required amount of stack space on all consumer architectures */
+       psCmdHelper = OSAllocMem(sizeof(RGX_CCB_CMD_HELPER_DATA));
+       if (psCmdHelper == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto fail_allochelper;
+       }
+
+
+       /*
+               Init the command helper commands for all the prepares
+       */
+       {
+               IMG_CHAR *pszCommandName;
+               RGXFWIF_CCB_CMD_TYPE eType;
+#if defined(SUPPORT_BUFFER_SYNC)
+               struct pvr_buffer_sync_context *psBufferSyncContext;
+#endif
+
+               pszCommandName = "TQ-TDM";
+
+               if (ui32FWCommandSize == 0)
+               {
+                       /* A NULL CMD for TDM is used to append updates to a non finished
+                        * FW command. bCCBStateOpen is used in case capture range is
+                        * entered on this command, to not drain CCB up to the Roff for this
+                        * command, but the finished command prior to this.
+                        */
+                       bCCBStateOpen = IMG_TRUE;
+                       eType = RGXFWIF_CCB_CMD_TYPE_NULL;
+               }
+               else
+               {
+                       bCCBStateOpen = IMG_FALSE;
+                       eType = RGXFWIF_CCB_CMD_TYPE_TQ_TDM;
+               }
+
+#if defined(SUPPORT_BUFFER_SYNC)
+               psBufferSyncContext = psTransferContext->sTDMData.psBufferSyncContext;
+#endif
+
+               eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListFence,
+                                             0,
+                                             NULL,
+                                             NULL);
+               if (eError != PVRSRV_OK)
+               {
+                       goto fail_populate_sync_addr_list;
+               }
+
+               eError = SyncAddrListPopulate(&psTransferContext->sSyncAddrListUpdate,
+                                                                               ui32ClientUpdateCount,
+                                                                               pauiClientUpdateUFODevVarBlock,
+                                                                               paui32ClientUpdateSyncOffset);
+               if (eError != PVRSRV_OK)
+               {
+                       goto fail_populate_sync_addr_list;
+               }
+               paui32IntUpdateValue    = paui32ClientUpdateValue;
+               pauiIntUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
+
+
+               if (ui32SyncPMRCount)
+               {
+#if defined(SUPPORT_BUFFER_SYNC)
+                       int err;
+
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:   Calling pvr_buffer_sync_resolve_and_create_fences", __func__));
+                       err = pvr_buffer_sync_resolve_and_create_fences(psBufferSyncContext,
+                                                                       psTransferContext->psDeviceNode->hSyncCheckpointContext,
+                                                                       ui32SyncPMRCount,
+                                                                       ppsSyncPMRs,
+                                                                       paui32SyncPMRFlags,
+                                                                       &ui32BufferFenceSyncCheckpointCount,
+                                                                       &apsBufferFenceSyncCheckpoints,
+                                                                       &psBufferUpdateSyncCheckpoint,
+                                                                       &psBufferSyncData);
+                       if (err)
+                       {
+                               switch (err)
+                               {
+                                       case -EINTR:
+                                               eError = PVRSRV_ERROR_RETRY;
+                                               break;
+                                       case -ENOMEM:
+                                               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                                               break;
+                                       default:
+                                               eError = PVRSRV_ERROR_INVALID_PARAMS;
+                                               break;
+                               }
+
+                               if (eError != PVRSRV_ERROR_RETRY)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   pvr_buffer_sync_resolve_and_create_fences failed (%s)", __func__, PVRSRVGetErrorString(eError)));
+                               }
+                               goto fail_resolve_input_fence;
+                       }
+
+                       /* Append buffer sync fences */
+                       if (ui32BufferFenceSyncCheckpointCount > 0)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append %d buffer sync checkpoints to TQ Fence (&psTransferContext->sSyncAddrListFence=<%p>, pauiIntFenceUFOAddress=<%p>)...", __func__, ui32BufferFenceSyncCheckpointCount, (void*)&psTransferContext->sSyncAddrListFence , (void*)pauiIntFenceUFOAddress));
+                               SyncAddrListAppendAndDeRefCheckpoints(&psTransferContext->sSyncAddrListFence,
+                                                                                                         ui32BufferFenceSyncCheckpointCount,
+                                                                                                         apsBufferFenceSyncCheckpoints);
+                               if (!pauiIntFenceUFOAddress)
+                               {
+                                       pauiIntFenceUFOAddress = psTransferContext->sSyncAddrListFence.pasFWAddrs;
+                               }
+                               ui32IntClientFenceCount += ui32BufferFenceSyncCheckpointCount;
+                       }
+
+                       if (psBufferUpdateSyncCheckpoint)
+                       {
+                               /* Append the update (from output fence) */
+                               SyncAddrListAppendCheckpoints(&psTransferContext->sSyncAddrListUpdate,
+                                                                                         1,
+                                                                                         &psBufferUpdateSyncCheckpoint);
+                               if (!pauiIntUpdateUFOAddress)
+                               {
+                                       pauiIntUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
+                               }
+                               ui32IntClientUpdateCount++;
+                       }
+#else /* defined(SUPPORT_BUFFER_SYNC) */
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Buffer sync not supported but got %u buffers", __func__, ui32SyncPMRCount));
+                       eError = PVRSRV_ERROR_INVALID_PARAMS;
+                       goto fail_populate_sync_addr_list;
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+               }
+
+               /* Resolve the sync checkpoints that make up the input fence */
+               eError = SyncCheckpointResolveFence(psTransferContext->psDeviceNode->hSyncCheckpointContext,
+                                                   iCheckFence,
+                                                   &ui32FenceSyncCheckpointCount,
+                                                   &apsFenceSyncCheckpoints,
+                                                   &uiCheckFenceUID,
+                                                   ui32PDumpFlags);
+               if (eError != PVRSRV_OK)
+               {
+                       goto fail_resolve_input_fence;
+               }
+#if defined(TDM_CHECKPOINT_DEBUG)
+               {
+                       IMG_UINT32 ii;
+                       for (ii=0; ii<32; ii++)
+                       {
+                               PSYNC_CHECKPOINT psNextCheckpoint = *(apsFenceSyncCheckpoints +  ii);
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s:    apsFenceSyncCheckpoints[%d]=<%p>", __func__, ii, (void*)psNextCheckpoint)); //psFenceSyncCheckpoints[ii]));
+                       }
+               }
+#endif
+               /* Create the output fence (if required) */
+               if (iUpdateTimeline != PVRSRV_NO_TIMELINE)
+               {
+                       eError = SyncCheckpointCreateFence(psTransferContext->psDeviceNode,
+                                                                                       szUpdateFenceName,
+                                                                                          iUpdateTimeline,
+                                                                                          psTransferContext->psDeviceNode->hSyncCheckpointContext,
+                                                                                          &iUpdateFence,
+                                                                                          &uiUpdateFenceUID,
+                                                                                          &pvUpdateFenceFinaliseData,
+                                                                                          &psUpdateSyncCheckpoint,
+                                                                                          (void*)&psFenceTimelineUpdateSync,
+                                                                                          &ui32FenceTimelineUpdateValue,
+                                                                                          ui32PDumpFlags);
+                       if (eError != PVRSRV_OK)
+                       {
+                               goto fail_create_output_fence;
+                       }
+
+                       /* Append the sync prim update for the timeline (if required) */
+                       if (psFenceTimelineUpdateSync)
+                       {
+                               IMG_UINT32 *pui32TimelineUpdateWp = NULL;
+
+                               /* Allocate memory to hold the list of update values (including our timeline update) */
+                               pui32IntAllocatedUpdateValues = OSAllocMem(sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                               if (!pui32IntAllocatedUpdateValues)
+                               {
+                                       /* Failed to allocate memory */
+                                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+                                       goto fail_alloc_update_values_mem;
+                               }
+                               OSCachedMemSet(pui32IntAllocatedUpdateValues, 0xbb, sizeof(*pui32IntAllocatedUpdateValues) * (ui32IntClientUpdateCount+1));
+                               /* Copy the update values into the new memory, then append our timeline update value */
+                               if (paui32IntUpdateValue)
+                               {
+                                       OSCachedMemCopy(pui32IntAllocatedUpdateValues, paui32IntUpdateValue, sizeof(*pui32IntAllocatedUpdateValues) * ui32IntClientUpdateCount);
+                               }
+                               /* Now set the additional update value */
+                               pui32TimelineUpdateWp = pui32IntAllocatedUpdateValues + ui32IntClientUpdateCount;
+                               *pui32TimelineUpdateWp = ui32FenceTimelineUpdateValue;
+                               ui32IntClientUpdateCount++;
+#if defined(TDM_CHECKPOINT_DEBUG)
+                               {
+                                       IMG_UINT32 iii;
+                                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                                       {
+                                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                               pui32Tmp++;
+                                       }
+                               }
+#endif
+                               /* Now append the timeline sync prim addr to the transfer context update list */
+                               SyncAddrListAppendSyncPrim(&psTransferContext->sSyncAddrListUpdate,
+                                                          psFenceTimelineUpdateSync);
+#if defined(TDM_CHECKPOINT_DEBUG)
+                               {
+                                       IMG_UINT32 iii;
+                                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                                       {
+                                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                               pui32Tmp++;
+                                       }
+                               }
+#endif
+                               /* Ensure paui32IntUpdateValue is now pointing to our new array of update values */
+                               paui32IntUpdateValue = pui32IntAllocatedUpdateValues;
+                       }
+               }
+
+               if (ui32FenceSyncCheckpointCount)
+               {
+                       /* Append the checks (from input fence) */
+                       if (ui32FenceSyncCheckpointCount > 0)
+                       {
+                               CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append %d sync checkpoints to TQ Fence (&psTransferContext->sSyncAddrListFence=<%p>)...", __func__, ui32FenceSyncCheckpointCount, (void*)&psTransferContext->sSyncAddrListFence));
+#if defined(TDM_CHECKPOINT_DEBUG)
+                               {
+                                       IMG_UINT32 iii;
+                                       IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pauiIntFenceUFOAddress;
+
+                                       for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                                       {
+                                               CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                               pui32Tmp++;
+                                       }
+                               }
+#endif
+                               SyncAddrListAppendCheckpoints(&psTransferContext->sSyncAddrListFence,
+                                                             ui32FenceSyncCheckpointCount,
+                                                             apsFenceSyncCheckpoints);
+                               if (!pauiIntFenceUFOAddress)
+                               {
+                                       pauiIntFenceUFOAddress = psTransferContext->sSyncAddrListFence.pasFWAddrs;
+                               }
+                               ui32IntClientFenceCount += ui32FenceSyncCheckpointCount;
+                       }
+#if defined(TDM_CHECKPOINT_DEBUG)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+               }
+               if (psUpdateSyncCheckpoint)
+               {
+                       /* Append the update (from output fence) */
+                       CHKPT_DBG((PVR_DBG_ERROR, "%s:   Append 1 sync checkpoint to TQ Update (&psTransferContext->sSyncAddrListUpdate=<%p>, pauiIntUpdateUFOAddress=<%p>)...", __func__, (void*)&psTransferContext->sSyncAddrListUpdate , (void*)pauiIntUpdateUFOAddress));
+                       SyncAddrListAppendCheckpoints(&psTransferContext->sSyncAddrListUpdate,
+                                                     1,
+                                                     &psUpdateSyncCheckpoint);
+                       if (!pauiIntUpdateUFOAddress)
+                       {
+                               pauiIntUpdateUFOAddress = psTransferContext->sSyncAddrListUpdate.pasFWAddrs;
+                       }
+                       ui32IntClientUpdateCount++;
+#if defined(TDM_CHECKPOINT_DEBUG)
+                       {
+                               IMG_UINT32 iii;
+                               IMG_UINT32 *pui32Tmp = (IMG_UINT32*)pui32IntAllocatedUpdateValues;
+
+                               for (iii=0; iii<ui32IntClientUpdateCount; iii++)
+                               {
+                                       CHKPT_DBG((PVR_DBG_ERROR, "%s: pui32IntAllocatedUpdateValues[%d](<%p>) = 0x%x", __func__, iii, (void*)pui32Tmp, *pui32Tmp));
+                                       pui32Tmp++;
+                               }
+                       }
+#endif
+               }
+
+#if (ENABLE_TDM_UFO_DUMP == 1)
+               PVR_DPF((PVR_DBG_ERROR, "%s: dumping TDM fence/updates syncs...", __func__));
+               {
+                       IMG_UINT32 ii;
+                       PRGXFWIF_UFO_ADDR *psTmpIntFenceUFOAddress = pauiIntFenceUFOAddress;
+                       PRGXFWIF_UFO_ADDR *psTmpIntUpdateUFOAddress = pauiIntUpdateUFOAddress;
+                       IMG_UINT32 *pui32TmpIntUpdateValue = paui32IntUpdateValue;
+
+                       /* Dump Fence syncs and Update syncs */
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d TDM fence syncs (&psTransferContext->sSyncAddrListFence=<%p>, pauiIntFenceUFOAddress=<%p>):", __func__, ui32IntClientFenceCount, (void*)&psTransferContext->sSyncAddrListFence, (void*)pauiIntFenceUFOAddress));
+                       for (ii=0; ii<ui32IntClientFenceCount; ii++)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, CheckValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientFenceCount, (void*)psTmpIntFenceUFOAddress, psTmpIntFenceUFOAddress->ui32Addr));
+                               psTmpIntFenceUFOAddress++;
+                       }
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Prepared %d TDM update syncs (&psTransferContext->sSyncAddrListUpdate=<%p>, pauiIntUpdateUFOAddress=<%p>):", __func__, ui32IntClientUpdateCount, (void*)&psTransferContext->sSyncAddrListUpdate, (void*)pauiIntUpdateUFOAddress));
+                       for (ii=0; ii<ui32IntClientUpdateCount; ii++)
+                       {
+                               if (psTmpIntUpdateUFOAddress->ui32Addr & 0x1)
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=PVRSRV_SYNC_CHECKPOINT_SIGNALLED", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr));
+                               }
+                               else
+                               {
+                                       PVR_DPF((PVR_DBG_ERROR, "%s:   %d/%d<%p>. FWAddr=0x%x, UpdateValue=%d", __func__, ii+1, ui32IntClientUpdateCount, (void*)psTmpIntUpdateUFOAddress, psTmpIntUpdateUFOAddress->ui32Addr, *pui32TmpIntUpdateValue));
+                                       pui32TmpIntUpdateValue++;
+                               }
+                               psTmpIntUpdateUFOAddress++;
+                       }
+               }
+#endif
+
+               RGX_GetTimestampCmdHelper((PVRSRV_RGXDEV_INFO*) psTransferContext->psDeviceNode->pvDevice,
+                                         &pPreAddr,
+                                         &pPostAddr,
+                                         &pRMWUFOAddr);
+               /*
+                * Extract the FBSC entries from MMU Context for the deferred FBSC invalidate command,
+                * in other words, take the value and set it to zero afterwards.
+                * FBSC Entry Mask must be extracted from MMU ctx and updated just before the kick starts
+                * as it must be ready at the time of context activation.
+                */
+               {
+                       eError = RGXExtractFBSCEntryMaskFromMMUContext(psTransferContext->psDeviceNode,
+                                                                                                                  FWCommonContextGetServerMMUCtx(psTransferContext->sTDMData.psServerCommonContext),
+                                                                                                                  &ui64FBSCEntryMask);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "Failed to extract FBSC Entry Mask (%d)", eError));
+                               goto fail_invalfbsc;
+                       }
+               }
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               sWorkloadCharacteristics.sTransfer.ui32Characteristic1 = ui32TDMCharacteristic1;
+               sWorkloadCharacteristics.sTransfer.ui32Characteristic2 = ui32TDMCharacteristic2;
+
+               /* Prepare workload estimation */
+               WorkEstPrepare(psDeviceNode->pvDevice,
+                               &psTransferContext->sWorkEstData,
+                               &psTransferContext->sWorkEstData.uWorkloadMatchingData.sTransfer.sDataTDM,
+                               eType,
+                               &sWorkloadCharacteristics,
+                               ui64DeadlineInus,
+                               &sWorkloadKickDataTransfer);
+#endif
+
+               /*
+                       Create the command helper data for this command
+               */
+               RGXCmdHelperInitCmdCCB(psDevInfo,
+                                      psClientCCB,
+                                      ui64FBSCEntryMask,
+                                      ui32IntClientFenceCount,
+                                      pauiIntFenceUFOAddress,
+                                      NULL,
+                                      ui32IntClientUpdateCount,
+                                      pauiIntUpdateUFOAddress,
+                                      paui32IntUpdateValue,
+                                      ui32FWCommandSize,
+                                      pui8FWCommand,
+                                      &pPreAddr,
+                                      &pPostAddr,
+                                      &pRMWUFOAddr,
+                                      eType,
+                                      ui32ExtJobRef,
+                                      ui32IntJobRef,
+                                      ui32PDumpFlags,
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+                                      &sWorkloadKickDataTransfer,
+#else /* SUPPORT_WORKLOAD_ESTIMATION */
+                                      NULL,
+#endif /* SUPPORT_WORKLOAD_ESTIMATION */
+                                      pszCommandName,
+                                      bCCBStateOpen,
+                                      psCmdHelper);
+       }
+
+       /*
+               Acquire space for all the commands in one go
+       */
+
+       eError = RGXCmdHelperAcquireCmdCCB(1, psCmdHelper);
+       if (eError != PVRSRV_OK)
+       {
+               goto fail_3dcmdacquire;
+       }
+
+
+       /*
+               We should acquire the kernel CCB(s) space here as the schedule could fail
+               and we would have to roll back all the syncs
+       */
+
+       /*
+               Only do the command helper release (which takes the server sync
+               operations if the acquire succeeded
+       */
+       ui32CmdOffset = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->sTDMData.psServerCommonContext));
+       RGXCmdHelperReleaseCmdCCB(1,
+                                 psCmdHelper,
+                                 "TQ_TDM",
+                                 FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext).ui32Addr);
+
+
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+       /* The following is used to determine the offset of the command header containing
+          the workload estimation data so that can be accessed when the KCCB is read */
+       ui32TDMCmdHeaderOffset = RGXCmdHelperGetDMCommandHeaderOffset(psCmdHelper);
+
+       ui32TDMCmdOffsetWrapCheck = RGXGetHostWriteOffsetCCB(FWCommonContextGetClientCCB(psTransferContext->sTDMData.psServerCommonContext));
+
+       /* This checks if the command would wrap around at the end of the CCB and
+        * therefore would start at an offset of 0 rather than the current command
+        * offset */
+       if (ui32CmdOffset < ui32TDMCmdOffsetWrapCheck)
+       {
+               ui32TDMWorkloadDataRO = ui32CmdOffset;
+       }
+       else
+       {
+               ui32TDMWorkloadDataRO = 0;
+       }
+#endif
+
+       /*
+               Even if we failed to acquire the client CCB space we might still need
+               to kick the HW to process a padding packet to release space for us next
+               time round
+       */
+       {
+               RGXFWIF_KCCB_CMD sTDMKCCBCmd;
+               IMG_UINT32 ui32FWAddr = FWCommonContextGetFWAddress(
+                       psTransferContext->sTDMData.psServerCommonContext).ui32Addr;
+
+               /* Construct the kernel 3D CCB command. */
+               sTDMKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_KICK;
+               sTDMKCCBCmd.uCmdData.sCmdKickData.psContext = FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext);
+               sTDMKCCBCmd.uCmdData.sCmdKickData.ui32CWoffUpdate = RGXGetHostWriteOffsetCCB(psClientCCB);
+               sTDMKCCBCmd.uCmdData.sCmdKickData.ui32CWrapMaskUpdate = RGXGetWrapMaskCCB(psClientCCB);
+               sTDMKCCBCmd.uCmdData.sCmdKickData.ui32NumCleanupCtl = 0;
+
+               /* Add the Workload data into the KCCB kick */
+#if defined(SUPPORT_WORKLOAD_ESTIMATION)
+               /* Store the offset to the CCCB command header so that it can be referenced
+                * when the KCCB command reaches the FW */
+               sTDMKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = ui32TDMWorkloadDataRO + ui32TDMCmdHeaderOffset;
+#else
+               sTDMKCCBCmd.uCmdData.sCmdKickData.ui32WorkEstCmdHeaderOffset = 0;
+#endif
+
+               /* HTBLOGK(HTB_SF_MAIN_KICK_TDM, */
+               /*              s3DKCCBCmd.uCmdData.sCmdKickData.psContext, */
+               /*              ui323DCmdOffset); */
+               RGXSRV_HWPERF_ENQ(psTransferContext,
+                                 OSGetCurrentClientProcessIDKM(),
+                                 FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext).ui32Addr,
+                                 ui32ExtJobRef,
+                                 ui32IntJobRef,
+                                 RGX_HWPERF_KICK_TYPE_TQTDM,
+                                 iCheckFence,
+                                 iUpdateFence,
+                                 iUpdateTimeline,
+                                 uiCheckFenceUID,
+                                 uiUpdateFenceUID,
+                                 NO_DEADLINE,
+                                 NO_CYCEST);
+
+               LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+               {
+                       eError2 = RGXScheduleCommand(psDeviceNode->pvDevice,
+                                                                                RGXFWIF_DM_TDM,
+                                                                                & sTDMKCCBCmd,
+                                                                                ui32PDumpFlags);
+                       if (eError2 != PVRSRV_ERROR_RETRY)
+                       {
+                               break;
+                       }
+                       OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+               } END_LOOP_UNTIL_TIMEOUT();
+
+               if (eError2 != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "PVRSRVRGXTDMSubmitTransferKM failed to schedule kernel CCB command. (0x%x)", eError2));
+                       if (eError == PVRSRV_OK)
+                       {
+                               eError = eError2;
+                       }
+                       goto fail_2dcmdacquire;
+               }
+
+               PVRGpuTraceEnqueueEvent(psDeviceNode->pvDevice, ui32FWAddr, ui32ExtJobRef,
+                                       ui32IntJobRef, RGX_HWPERF_KICK_TYPE_TQTDM);
+       }
+
+       /*
+        * Now check eError (which may have returned an error from our earlier calls
+        * to RGXCmdHelperAcquireCmdCCB) - we needed to process any flush command first
+        * so we check it now...
+        */
+       if (eError != PVRSRV_OK )
+       {
+               goto fail_2dcmdacquire;
+       }
+
+#if defined(NO_HARDWARE)
+       /* If NO_HARDWARE, signal the output fence's sync checkpoint and sync prim */
+       if (psUpdateSyncCheckpoint)
+       {
+               SyncCheckpointSignalNoHW(psUpdateSyncCheckpoint);
+       }
+       if (psFenceTimelineUpdateSync)
+       {
+               SyncPrimNoHwUpdate(psFenceTimelineUpdateSync, ui32FenceTimelineUpdateValue);
+       }
+       SyncCheckpointNoHWUpdateTimelines(NULL);
+#endif /* defined(NO_HARDWARE) */
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               pvr_buffer_sync_kick_succeeded(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+       * piUpdateFence = iUpdateFence;
+       if (pvUpdateFenceFinaliseData && (iUpdateFence != PVRSRV_NO_FENCE))
+       {
+               SyncCheckpointFinaliseFence(psDeviceNode, iUpdateFence, pvUpdateFenceFinaliseData,
+                                           psUpdateSyncCheckpoint, szUpdateFenceName);
+       }
+
+       OSFreeMem(psCmdHelper);
+
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                    apsFenceSyncCheckpoints);
+       /* Free the memory that was allocated for the sync checkpoint list returned by ResolveFence() */
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       /* Free memory allocated to hold the internal list of update values */
+       if (pui32IntAllocatedUpdateValues)
+       {
+               OSFreeMem(pui32IntAllocatedUpdateValues);
+               pui32IntAllocatedUpdateValues = NULL;
+       }
+
+       OSLockRelease(psTransferContext->hLock);
+       return PVRSRV_OK;
+
+/*
+       No resources are created in this function so there is nothing to free
+       unless we had to merge syncs.
+       If we fail after the client CCB acquire there is still nothing to do
+       as only the client CCB release will modify the client CCB
+*/
+fail_2dcmdacquire:
+fail_3dcmdacquire:
+
+fail_invalfbsc:
+       SyncAddrListRollbackCheckpoints(psTransferContext->psDeviceNode, &psTransferContext->sSyncAddrListFence);
+       SyncAddrListRollbackCheckpoints(psTransferContext->psDeviceNode, &psTransferContext->sSyncAddrListUpdate);
+fail_alloc_update_values_mem:
+
+/* fail_pdumpcheck: */
+/* fail_cmdtype: */
+
+       if (iUpdateFence != PVRSRV_NO_FENCE)
+       {
+               SyncCheckpointRollbackFenceData(iUpdateFence, pvUpdateFenceFinaliseData);
+       }
+fail_create_output_fence:
+       /* Drop the references taken on the sync checkpoints in the
+        * resolved input fence */
+       SyncAddrListDeRefCheckpoints(ui32FenceSyncCheckpointCount,
+                                    apsFenceSyncCheckpoints);
+
+fail_resolve_input_fence:
+
+#if defined(SUPPORT_BUFFER_SYNC)
+       if (psBufferSyncData)
+       {
+               pvr_buffer_sync_kick_failed(psBufferSyncData);
+       }
+       if (apsBufferFenceSyncCheckpoints)
+       {
+               kfree(apsBufferFenceSyncCheckpoints);
+       }
+#endif /* defined(SUPPORT_BUFFER_SYNC) */
+
+fail_populate_sync_addr_list:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       OSFreeMem(psCmdHelper);
+fail_allochelper:
+
+       if (apsFenceSyncCheckpoints)
+       {
+               SyncCheckpointFreeCheckpointListMem(apsFenceSyncCheckpoints);
+       }
+       OSLockRelease(psTransferContext->hLock);
+       return eError;
+}
+
+
+PVRSRV_ERROR PVRSRVRGXTDMNotifyWriteOffsetUpdateKM(
+       RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+       IMG_UINT32                 ui32PDumpFlags)
+{
+       RGXFWIF_KCCB_CMD  sKCCBCmd;
+       PVRSRV_ERROR      eError;
+
+       OSLockAcquire(psTransferContext->hLock);
+
+       /* Schedule the firmware command */
+       sKCCBCmd.eCmdType = RGXFWIF_KCCB_CMD_NOTIFY_WRITE_OFFSET_UPDATE;
+       sKCCBCmd.uCmdData.sWriteOffsetUpdateData.psContext = FWCommonContextGetFWAddress(psTransferContext->sTDMData.psServerCommonContext);
+
+       LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+       {
+               eError = RGXScheduleCommand(psTransferContext->psDeviceNode->pvDevice,
+                                           RGXFWIF_DM_TDM,
+                                           &sKCCBCmd,
+                                           ui32PDumpFlags);
+               if (eError != PVRSRV_ERROR_RETRY)
+               {
+                       break;
+               }
+               OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+       } END_LOOP_UNTIL_TIMEOUT();
+
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: Failed to schedule the FW command %d (%s)",
+                               __func__, eError, PVRSRVGETERRORSTRING(eError)));
+       }
+
+       OSLockRelease(psTransferContext->hLock);
+       return eError;
+}
+
+PVRSRV_ERROR PVRSRVRGXTDMSetTransferContextPriorityKM(CONNECTION_DATA *psConnection,
+                                                      PVRSRV_DEVICE_NODE * psDevNode,
+                                                      RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+                                                      IMG_UINT32 ui32Priority)
+{
+       PVRSRV_ERROR eError;
+
+       PVR_UNREFERENCED_PARAMETER(psDevNode);
+
+       OSLockAcquire(psTransferContext->hLock);
+
+       if (psTransferContext->sTDMData.ui32Priority != ui32Priority)
+       {
+               eError = ContextSetPriority(psTransferContext->sTDMData.psServerCommonContext,
+                                           psConnection,
+                                           psTransferContext->psDeviceNode->pvDevice,
+                                           ui32Priority,
+                                           RGXFWIF_DM_TDM);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to set the priority (%s)", __func__, PVRSRVGetErrorString(eError)));
+
+                       OSLockRelease(psTransferContext->hLock);
+                       return eError;
+               }
+       }
+
+       OSLockRelease(psTransferContext->hLock);
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRGXTDMSetTransferContextPropertyKM(RGX_SERVER_TQ_TDM_CONTEXT *psTransferContext,
+                                                                                                         RGX_CONTEXT_PROPERTY eContextProperty,
+                                                                                                         IMG_UINT64 ui64Input,
+                                                                                                         IMG_UINT64 *pui64Output)
+{
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       switch (eContextProperty)
+       {
+               case RGX_CONTEXT_PROPERTY_FLAGS:
+               {
+                       IMG_UINT32 ui32ContextFlags = (IMG_UINT32)ui64Input;
+
+                       OSLockAcquire(psTransferContext->hLock);
+                       eError = FWCommonContextSetFlags(psTransferContext->sTDMData.psServerCommonContext,
+                                                        ui32ContextFlags);
+                       OSLockRelease(psTransferContext->hLock);
+                       break;
+               }
+
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_ERROR_NOT_SUPPORTED - asked to set unknown property (%d)", __func__, eContextProperty));
+                       eError = PVRSRV_ERROR_NOT_SUPPORTED;
+               }
+       }
+
+       return eError;
+}
+
+void DumpTDMTransferCtxtsInfo(PVRSRV_RGXDEV_INFO *psDevInfo,
+                              DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+                              void *pvDumpDebugFile,
+                              IMG_UINT32 ui32VerbLevel)
+{
+       DLLIST_NODE *psNode, *psNext;
+
+       OSWRLockAcquireRead(psDevInfo->hTDMCtxListLock);
+
+       dllist_foreach_node(&psDevInfo->sTDMCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_TQ_TDM_CONTEXT *psCurrentServerTransferCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_TDM_CONTEXT, sListNode);
+
+               DumpFWCommonContextInfo(psCurrentServerTransferCtx->sTDMData.psServerCommonContext,
+                                       pfnDumpDebugPrintf, pvDumpDebugFile, ui32VerbLevel);
+       }
+
+       OSWRLockReleaseRead(psDevInfo->hTDMCtxListLock);
+}
+
+
+IMG_UINT32 CheckForStalledClientTDMTransferCtxt(PVRSRV_RGXDEV_INFO *psDevInfo)
+{
+       DLLIST_NODE *psNode, *psNext;
+       IMG_UINT32 ui32ContextBitMask = 0;
+
+       OSWRLockAcquireRead(psDevInfo->hTDMCtxListLock);
+
+       dllist_foreach_node(&psDevInfo->sTDMCtxtListHead, psNode, psNext)
+       {
+               RGX_SERVER_TQ_TDM_CONTEXT *psCurrentServerTransferCtx =
+                       IMG_CONTAINER_OF(psNode, RGX_SERVER_TQ_TDM_CONTEXT, sListNode);
+
+               if (CheckStalledClientCommonContext(
+                                    psCurrentServerTransferCtx->sTDMData.psServerCommonContext, RGX_KICK_TYPE_DM_TDM_2D)
+                                == PVRSRV_ERROR_CCCB_STALLED) {
+                       ui32ContextBitMask = RGX_KICK_TYPE_DM_TDM_2D;
+               }
+       }
+
+       OSWRLockReleaseRead(psDevInfo->hTDMCtxListLock);
+       return ui32ContextBitMask;
+}
+
+/**************************************************************************//**
+ End of file (rgxtdmtransfer.c)
+******************************************************************************/
old mode 100755 (executable)
new mode 100644 (file)
index 9a7f4c1..4ba7716
 
 # Window system
 ccflags-y += -DWINDOW_SYSTEM=\"$(WINDOW_SYSTEM)\"
-ifeq ($(FPGA_VERIFICATION),1)
-ccflags-y += -D__FPGA_VERIFICATION__=$(FPGA_VERIFICATION)
-endif
 
 # Linux kernel headers
 ccflags-y += \
  -Iinclude \
- -Iinclude/drm \
- -Iinclude/mm
-# -I$(srctree)/mm
+ -Iinclude/drm
 
 # Compatibility BVNC
-ccflags-y += -I$(TOP)/services/shared/devices/$(PVR_ARCH)
+ccflags-y += -I$(TOP)/services/shared/devices/$(PVR_ARCH_DEFS)
 
 # Errata files
 ccflags-y += -I$(HWDEFS_DIR) -I$(HWDEFS_DIR)/$(RGX_BNC)
@@ -61,11 +56,9 @@ ccflags-y += -I$(HWDEFS_DIR) -I$(HWDEFS_DIR)/$(RGX_BNC)
 # Linux-specific headers
 ccflags-y += \
  -I$(TOP)/include/drm \
- -I$(srctree)/drivers/gpu/drm/img \
  -I$(TOP)/services/include/env/linux \
  -I$(TOP)/services/server/env/linux/$(PVR_ARCH) -I$(TOP)/services/server/env/linux \
- -I$(TOP)/hwdefs/$(PVR_ARCH)/km
- #-I$(TOP)/kernel/drivers/staging/imgtec
+ -I$(TOP)/kernel/drivers/staging/imgtec
 
 # System dir
 ifneq ($(wildcard $(TOP)/services/system/$(PVR_ARCH)/$(PVR_SYSTEM)/Kbuild.mk),)
@@ -171,11 +164,12 @@ endif
 
 ifeq ($(SUPPORT_RGX),1)
 $(PVRSRV_MODNAME)-y += \
+ services/server/devices/rgx_bridge_init.o \
  services/server/env/linux/pvr_gputrace.o \
  services/server/devices/rgxfwdbg.o \
  services/server/devices/rgxtimerquery.o \
  services/server/devices/rgxccb.o \
- services/server/devices/$(PVR_ARCH)/rgxdebug.o \
+ services/server/devices/$(PVR_ARCH_DEFS)/rgxdebug.o \
  services/server/devices/rgxfwtrace_strings.o \
  services/server/devices/$(PVR_ARCH)/rgxfwutils.o \
  services/server/devices/$(PVR_ARCH)/rgxinit.o \
@@ -195,7 +189,6 @@ $(PVRSRV_MODNAME)-y += \
  services/server/devices/$(PVR_ARCH)/rgxstartstop.o \
  services/server/devices/rgxtimecorr.o \
  services/server/devices/$(PVR_ARCH)/rgxcompute.o \
- services/server/devices/rgxsignals.o \
  services/server/devices/$(PVR_ARCH)/rgxmulticore.o \
  services/server/devices/rgxshader.o
 
@@ -226,6 +219,17 @@ ifeq ($(SUPPORT_WORKLOAD_ESTIMATION),1)
  services/server/devices/rgxworkest.o
 endif
 
+ifeq ($(SUPPORT_VALIDATION),1)
+ifeq ($(PVR_TESTING_UTILS),1)
+ $(PVRSRV_MODNAME)-y += \
+ services/server/devices/rgxgpumap.o
+endif
+endif
+
+ifeq ($(SUPPORT_VALIDATION),1)
+ $(PVRSRV_MODNAME)-y += \
+ services/server/devices/rgxsoctimer.o
+endif
 endif
 
 ifeq ($(SUPPORT_DISPLAY_CLASS),1)
@@ -284,6 +288,12 @@ $(PVRSRV_MODNAME)-y += \
 endif
 
 ifeq ($(SUPPORT_NATIVE_FENCE_SYNC),1)
+$(PVRSRV_MODNAME)-y += services/server/env/linux/pvr_sync_ioctl_common.o
+ifeq ($(USE_PVRSYNC_DEVNODE),1)
+$(PVRSRV_MODNAME)-y += services/server/env/linux/pvr_sync_ioctl_dev.o
+else
+$(PVRSRV_MODNAME)-y += services/server/env/linux/pvr_sync_ioctl_drm.o
+endif
 ifeq ($(SUPPORT_DMA_FENCE),1)
 $(PVRSRV_MODNAME)-y += \
  services/server/env/linux/pvr_sync_file.o \
@@ -318,11 +328,20 @@ $(PVRSRV_MODNAME)-$(CONFIG_METAG) += services/server/env/linux/osfunc_metag.o
 $(PVRSRV_MODNAME)-$(CONFIG_MIPS) += services/server/env/linux/osfunc_mips.o
 $(PVRSRV_MODNAME)-$(CONFIG_RISCV) += services/server/env/linux/osfunc_riscv.o
 
-ifeq ($(CONFIG_DEBUG_FS),y)
-$(PVRSRV_MODNAME)-$(CONFIG_DEBUG_FS) += services/server/env/linux/pvr_debugfs.o
-else ifeq ($(CONFIG_PROC_FS),y)
-$(PVRSRV_MODNAME)-$(CONFIG_PROC_FS) += services/server/env/linux/pvr_procfs.o
+ifeq ($(SUPPORT_ANDROID_PLATFORM),1)
+ ifeq ($(CONFIG_PROC_FS),y)
+ $(PVRSRV_MODNAME)-$(CONFIG_PROC_FS) += services/server/env/linux/pvr_procfs.o
+ else ifeq ($(CONFIG_DEBUG_FS),y)
+ $(PVRSRV_MODNAME)-$(CONFIG_DEBUG_FS) += services/server/env/linux/pvr_debugfs.o
+ endif
+else
+ ifeq ($(CONFIG_DEBUG_FS),y)
+ $(PVRSRV_MODNAME)-$(CONFIG_DEBUG_FS) += services/server/env/linux/pvr_debugfs.o
+ else ifeq ($(CONFIG_PROC_FS),y)
+ $(PVRSRV_MODNAME)-$(CONFIG_PROC_FS) += services/server/env/linux/pvr_procfs.o
+ endif
 endif
+
 ifeq ($(SUPPORT_DI_BRG_IMPL),1)
 $(PVRSRV_MODNAME)-y += services/server/common/di_impl_brg.o
 endif
@@ -338,12 +357,24 @@ $(PVRSRV_MODNAME)-y += \
  services/server/devices/rgxfwimageutils.o
 ifeq ($(PVR_ARCH),rogue)
 $(PVRSRV_MODNAME)-y += \
- services/shared/devices/$(PVR_ARCH)/rgx_hwperf_table.o
+ services/shared/devices/$(PVR_ARCH_DEFS)/rgx_hwperf_table.o
 endif
 endif
 
+$(PVRSRV_MODNAME)-y += \
+ services/system/$(PVR_ARCH)/common/env/linux/dma_support.o \
+ services/system/common/env/linux/interrupt_support.o
+
+$(PVRSRV_MODNAME)-$(CONFIG_PCI) += \
+ services/system/common/env/linux/pci_support.o
+
+ccflags-y += \
+ -I$(HWDEFS_DIR)/km
+ifeq ($(PVR_ARCH),rogue)
+ccflags-y += \
+ -I$(TOP)/include/$(PVR_ARCH_DEFS)
+endif
 ccflags-y += \
- -I$(HWDEFS_DIR)/km \
  -I$(TOP)/include/$(PVR_ARCH) -I$(TOP)/include \
  -I$(TOP)/include/$(PVR_ARCH)/public -I$(TOP)/include/public \
  -I$(TOP)/services/include/$(PVR_ARCH) -I$(TOP)/services/include \
@@ -384,15 +415,13 @@ endif
 
 ifeq ($(SUPPORT_RGX),1)
 ccflags-y += \
- -I$(bridge_base)/rgxtq2_bridge \
  -I$(bridge_base)/rgxta3d_bridge \
  -I$(bridge_base)/rgxhwperf_bridge \
  -I$(bridge_base)/rgxkicksync_bridge \
  -I$(bridge_base)/rgxcmp_bridge \
  -I$(bridge_base)/rgxregconfig_bridge \
  -I$(bridge_base)/rgxtimerquery_bridge \
- -I$(bridge_base)/rgxfwdbg_bridge \
- -I$(bridge_base)/rgxsignals_bridge
+ -I$(bridge_base)/rgxfwdbg_bridge
 ifeq ($(PVR_ARCH),volcanic)
 ccflags-y += \
  -I$(bridge_base)/rgxray_bridge
@@ -401,6 +430,11 @@ ifeq ($(PVR_ARCH),rogue)
 ccflags-y += \
  -I$(bridge_base)/rgxtq_bridge
 endif
+# Oceanic does not support TDM
+ifneq ($(PVR_ARCH_DEFS),oceanic)
+ccflags-y += \
+ -I$(bridge_base)/rgxtq2_bridge
+endif
 ifeq ($(SUPPORT_USC_BREAKPOINT),1)
 ccflags-y += \
  -I$(bridge_base)/rgxbreakpoint_bridge
@@ -424,15 +458,13 @@ endif
 
 ifeq ($(SUPPORT_RGX),1)
 $(PVRSRV_MODNAME)-y += \
- generated/$(PVR_ARCH)/rgxtq2_bridge/server_rgxtq2_bridge.o \
  generated/$(PVR_ARCH)/rgxta3d_bridge/server_rgxta3d_bridge.o \
  generated/$(PVR_ARCH)/rgxhwperf_bridge/server_rgxhwperf_bridge.o \
  generated/$(PVR_ARCH)/rgxkicksync_bridge/server_rgxkicksync_bridge.o \
  generated/$(PVR_ARCH)/rgxcmp_bridge/server_rgxcmp_bridge.o \
  generated/$(PVR_ARCH)/rgxregconfig_bridge/server_rgxregconfig_bridge.o \
  generated/$(PVR_ARCH)/rgxtimerquery_bridge/server_rgxtimerquery_bridge.o \
- generated/$(PVR_ARCH)/rgxfwdbg_bridge/server_rgxfwdbg_bridge.o \
- generated/$(PVR_ARCH)/rgxsignals_bridge/server_rgxsignals_bridge.o
+ generated/$(PVR_ARCH)/rgxfwdbg_bridge/server_rgxfwdbg_bridge.o
 ifeq ($(PVR_ARCH),volcanic)
 $(PVRSRV_MODNAME)-y += \
  generated/$(PVR_ARCH)/rgxray_bridge/server_rgxray_bridge.o
@@ -441,6 +473,11 @@ ifeq ($(PVR_ARCH),rogue)
 $(PVRSRV_MODNAME)-y += \
  generated/$(PVR_ARCH)/rgxtq_bridge/server_rgxtq_bridge.o
 endif
+# Oceanic does not support TDM
+ifneq ($(PVR_ARCH_DEFS),oceanic)
+$(PVRSRV_MODNAME)-y += \
+ generated/$(PVR_ARCH)/rgxtq2_bridge/server_rgxtq2_bridge.o
+endif
 ifeq ($(SUPPORT_USC_BREAKPOINT),1)
 $(PVRSRV_MODNAME)-y += \
  generated/$(PVR_ARCH)/rgxbreakpoint_bridge/server_rgxbreakpoint_bridge.o
index 3b81559..5d7c85d 100644 (file)
@@ -54,19 +54,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 #include "osfunc.h"
 
-/*
- * DEBUG_MEMSTATS_ALLOC_RECORD_VALUES needs to be different from
- * DEBUG_MEMSTATS_VALUES defined in process_stats.h.
- * The reason for this is that the file and line where the allocation happens
- * are tracked from the OSAllocMem params. If DEBUG_MEMSTATS_VALUES were to be
- * used, all OSAllocMem allocation statistics would point to allocmem.c, which
- * is not expected behaviour.
- */
-#if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON)
-#define DEBUG_MEMSTATS_ALLOC_RECORD_VALUES ,pvAllocFromFile, ui32AllocFromLine
-#else
-#define DEBUG_MEMSTATS_ALLOC_RECORD_VALUES
-#endif
 
 /*
  * When memory statistics are disabled, memory records are used instead.
@@ -167,7 +154,7 @@ static inline void _pvr_alloc_stats_add(void *pvAddr, IMG_UINT32 ui32Size DEBUG_
                                                                          ksize(pvAddr),
                                                                          NULL,
                                                                          OSGetCurrentClientProcessIDKM()
-                                                                         DEBUG_MEMSTATS_ALLOC_RECORD_VALUES);
+                                                                         DEBUG_MEMSTATS_ARGS);
 #else
                {
                        /* Store the PID in the final additional 4 bytes allocated */
@@ -189,7 +176,7 @@ static inline void _pvr_alloc_stats_add(void *pvAddr, IMG_UINT32 ui32Size DEBUG_
                                                                          ((ui32Size + PAGE_SIZE-1) & ~(PAGE_SIZE-1)),
                                                                          NULL,
                                                                          OSGetCurrentClientProcessIDKM()
-                                                                         DEBUG_MEMSTATS_ALLOC_RECORD_VALUES);
+                                                                         DEBUG_MEMSTATS_ARGS);
 #else
                PVRSRVStatsIncrMemAllocStatAndTrack(PVRSRV_MEM_ALLOC_TYPE_VMALLOC,
                                                    ((ui32Size + PAGE_SIZE-1) & ~(PAGE_SIZE-1)),
@@ -256,7 +243,7 @@ void *(OSAllocMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
 
        if (pvRet != NULL)
        {
-               _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ALLOC_RECORD_VALUES);
+               _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ARGS);
        }
 
        return pvRet;
@@ -286,7 +273,7 @@ void *(OSAllocZMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
 
        if (pvRet != NULL)
        {
-               _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ALLOC_RECORD_VALUES);
+               _pvr_alloc_stats_add(pvRet, ui32Size DEBUG_MEMSTATS_ARGS);
        }
 
        return pvRet;
index 986190a..2a6c7d0 100644 (file)
@@ -60,7 +60,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 typedef struct _ENV_CONNECTION_PRIVATE_DATA_
 {
-       struct file *psFile;
        PVRSRV_DEVICE_NODE *psDevNode;
 } ENV_CONNECTION_PRIVATE_DATA;
 
@@ -79,9 +78,12 @@ typedef struct _ENV_CONNECTION_DATA_
 {
        pid_t owner;
 
-       struct file *psFile;
        PVRSRV_DEVICE_NODE *psDevNode;
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+       void *pvPvrSyncPrivateData;
+#endif
+
 #if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
        ENV_ION_CONNECTION_DATA *psIonData;
 #endif
index b2c286a..35e52af 100644 (file)
@@ -182,19 +182,16 @@ OSLoadFirmware(PVRSRV_DEVICE_NODE *psDeviceNode, const IMG_CHAR *pszBVNCString,
        res = request_firmware(&psFW, pszBVNCString, psDeviceNode->psDevConfig->pvOSDevice);
        if (res != 0)
        {
-               PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') failed (%d)",
-                                               __func__, pszBVNCString, res));
-
                release_firmware(psFW);
                if (res == -ENOENT)
                {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: request_firmware('%s') failed (%d) (ERROR_NOT_FOUND)",
+                       PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') not found (%d)",
                                                        __func__, pszBVNCString, res));
                        eError = PVRSRV_ERROR_NOT_FOUND;
                }
                else
                {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: request_firmware('%s') failed (%d) (ERROR_NOT_READY)",
+                       PVR_DPF((PVR_DBG_WARNING, "%s: request_firmware('%s') not ready (%d)",
                                                        __func__, pszBVNCString, res));
                        eError = PVRSRV_ERROR_NOT_READY;
                }
index 9b62b5e..9246179 100644 (file)
@@ -86,6 +86,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define APPHINT_DEVICES_MAX 16
 
+/* Apphint Debug output level */
+#define APPHINT_DPF_LEVEL PVR_DBG_VERBOSE
+
 /*
 *******************************************************************************
  * AppHint mnemonic data type helper tables
@@ -296,9 +299,9 @@ static struct apphint_state
        DI_GROUP *buildvar_rootdir;
        DI_ENTRY *buildvar_entry[APPHINT_BUILDVAR_ID_MAX];
 
-       unsigned num_devices;
+       unsigned int num_devices;
        PVRSRV_DEVICE_NODE *devices[APPHINT_DEVICES_MAX];
-       unsigned initialized;
+       unsigned int initialized;
 
        /* Array contains value space for 1 copy of all apphint values defined
         * (for device 1) and N copies of device specific apphint values for
@@ -340,9 +343,11 @@ get_apphint_id_from_action_addr(const struct apphint_action * const addr,
 
 static inline void
 get_value_offset_from_device(const PVRSRV_DEVICE_NODE * const device,
-                             int * const offset)
+                             int * const offset,
+                             APPHINT_ID id)
 {
        int i;
+       IMG_BOOL bFound = IMG_FALSE;
 
        /* No device offset if not a device specific apphint */
        if (APPHINT_OF_DRIVER_NO_DEVICE == device) {
@@ -350,6 +355,24 @@ get_value_offset_from_device(const PVRSRV_DEVICE_NODE * const device,
                return;
        }
 
+       /* Check that the specified ID is a device-specific one. If not we
+        * set the offset to 0 for the global MODPARAM / BUILDVAR etc. AppHint
+        */
+       for (i = 0; i < ARRAY_SIZE(init_data_debuginfo_device); i++)
+       {
+               const struct apphint_init_data *device_init = &init_data_debuginfo_device[i];
+
+               if ((IMG_UINT32)id == device_init->id) {
+                       bFound = IMG_TRUE;
+                       break;
+               }
+       }
+
+       if (!bFound) {
+               *offset = 0;
+               return;
+       }
+
        for (i = 0; device && i < APPHINT_DEVICES_MAX; i++) {
                if (apphint.devices[i] == device)
                        break;
@@ -413,7 +436,8 @@ static void apphint_action_worker(struct work_struct *work)
                                 __func__, param_lookup[id].data_type, id));
                }
 
-               if (PVRSRV_OK != result) {
+               /* Do not log errors if running in GUEST mode */
+               if ((PVRSRV_OK != result) && !PVRSRV_VZ_MODE_IS(GUEST)) {
                        PVR_DPF((PVR_DBG_ERROR,
                                 "%s: failed (%s)",
                                 __func__, PVRSRVGetErrorString(result)));
@@ -616,41 +640,72 @@ err_exit:
 }
 
 static PVRSRV_ERROR get_apphint_value_from_action(const struct apphint_action * const action,
-                                                                                                 union apphint_value * const value)
+                                                  union apphint_value * const value,
+                                                  const PVRSRV_DEVICE_NODE * const psDevNode)
 {
        APPHINT_ID id;
        APPHINT_DATA_TYPE data_type;
        PVRSRV_ERROR result = PVRSRV_OK;
+       const PVRSRV_DEVICE_NODE *psDevice;
 
        get_apphint_id_from_action_addr(action, &id);
        data_type = param_lookup[id].data_type;
 
+       /* If we've got an entry that is APPHINT_OF_DRIVER_NO_DEVICE we should use
+        * the higher-level psDevNode value instead. This is the device-node that is
+        * associated with the original debug_dump request.
+        * Note: if we're called with psDevNode == APPHINT_OF_DRIVER_NO_DEVICE
+        * we attempt to use the first registered apphint.devices[0] (if any
+        * devices have been presented). If we have no devices hooked into the
+        * apphint mechanism we just return the default value for the AppHint.
+        */
+       if (psDevNode == APPHINT_OF_DRIVER_NO_DEVICE) {
+               if (action->device == APPHINT_OF_DRIVER_NO_DEVICE) {
+                       if (apphint.num_devices > 0) {
+                               psDevice = apphint.devices[0];
+                       } else {
+                               PVR_DPF((PVR_DBG_ERROR,
+                                       "Uninitialised AppHint device for AppHint index (%d)",
+                                       id));
+                               return PVRSRV_ERROR_RETRY;
+                       }
+               } else {
+                       psDevice = action->device;
+               }
+       } else {
+               if (action->device == APPHINT_OF_DRIVER_NO_DEVICE) {
+                       psDevice = psDevNode;
+               } else {
+                       psDevice = action->device;
+               }
+       }
+
        if (action->query.UINT64) {
                switch (data_type) {
                case APPHINT_DATA_TYPE_UINT64:
-                       result = action->query.UINT64(action->device,
-                                                                                 action->private_data,
-                                                                                 &value->UINT64);
+                       result = action->query.UINT64(psDevice,
+                                                     action->private_data,
+                                                     &value->UINT64);
                        break;
 
                case APPHINT_DATA_TYPE_UINT32:
                case APPHINT_DATA_TYPE_UINT32Bitfield:
                case APPHINT_DATA_TYPE_UINT32List:
-                       result = action->query.UINT32(action->device,
-                                                                                 action->private_data,
-                                                                                 &value->UINT32);
+                       result = action->query.UINT32(psDevice,
+                                                     action->private_data,
+                                                     &value->UINT32);
                        break;
 
                case APPHINT_DATA_TYPE_BOOL:
-                       result = action->query.BOOL(action->device,
-                                                                               action->private_data,
-                                                                               &value->BOOL);
+                       result = action->query.BOOL(psDevice,
+                                                   action->private_data,
+                                                   &value->BOOL);
                        break;
 
                case APPHINT_DATA_TYPE_STRING:
-                       result = action->query.STRING(action->device,
-                                                                                 action->private_data,
-                                                                                 &value->STRING);
+                       result = action->query.STRING(psDevice,
+                                                     action->private_data,
+                                                     &value->STRING);
                        break;
                default:
                        PVR_DPF((PVR_DBG_ERROR,
@@ -684,7 +739,7 @@ static int apphint_write(char *buffer, const size_t size,
        get_apphint_id_from_action_addr(a, &id);
        hint = &param_lookup[id];
 
-       result = get_apphint_value_from_action(a, &value);
+       result = get_apphint_value_from_action(a, &value, a->device);
 
        switch (hint->data_type) {
        case APPHINT_DATA_TYPE_UINT64:
@@ -941,20 +996,20 @@ err_exit:
  * apphint_debuginfo_init - Create the specified debuginfo entries
  */
 static int apphint_debuginfo_init(const char *sub_dir,
-               unsigned device_num,
-               unsigned init_data_size,
+               unsigned int device_num,
+               unsigned int init_data_size,
                const struct apphint_init_data *init_data,
                DI_GROUP *parentdir,
                DI_GROUP **rootdir,
                DI_ENTRY *entry[])
 {
        PVRSRV_ERROR result;
-       unsigned i;
-       unsigned device_value_offset = device_num * APPHINT_DEBUGINFO_DEVICE_ID_MAX;
+       unsigned int i;
+       unsigned int device_value_offset = device_num * APPHINT_DEBUGINFO_DEVICE_ID_MAX;
        const DI_ITERATOR_CB iterator = {
                .pfnStart = apphint_di_start, .pfnStop = apphint_di_stop,
                .pfnNext  = apphint_di_next,  .pfnShow = apphint_di_show,
-               .pfnWrite = apphint_set
+               .pfnWrite = apphint_set,      .ui32WriteLenMax = APPHINT_BUFFER_SIZE
        };
 
        if (*rootdir) {
@@ -997,11 +1052,11 @@ err_exit:
 /**
  * apphint_debuginfo_deinit- destroy the debuginfo entries
  */
-static void apphint_debuginfo_deinit(unsigned num_entries,
+static void apphint_debuginfo_deinit(unsigned int num_entries,
                DI_GROUP **rootdir,
                DI_ENTRY *entry[])
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < num_entries; i++) {
                if (entry[i]) {
@@ -1020,17 +1075,19 @@ static void apphint_debuginfo_deinit(unsigned num_entries,
  AppHint status dump implementation
 ******************************************************************************/
 #if defined(PDUMP)
-static void apphint_pdump_values(void *flags, const IMG_CHAR *format, ...)
+static void apphint_pdump_values(void *pvDeviceNode,
+                                 const IMG_CHAR *format, ...)
 {
        char km_buffer[APPHINT_BUFFER_SIZE];
-       IMG_UINT32 ui32Flags = *(IMG_UINT32 *)flags;
+       IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
        va_list ap;
 
        va_start(ap, format);
        (void)vsnprintf(km_buffer, APPHINT_BUFFER_SIZE, format, ap);
        va_end(ap);
 
-       PDumpCommentKM(km_buffer, ui32Flags);
+       /* ui32CommentSize set to 0 here as function does not make use of the value. */
+       PDumpCommentKM(NULL, (PVRSRV_DEVICE_NODE*)pvDeviceNode, 0, km_buffer, ui32Flags);
 }
 #endif
 
@@ -1061,7 +1118,8 @@ static void apphint_dump_values(const char *group_name,
                        int group_size,
                        DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                        void *pvDumpDebugFile,
-                       bool list_all)
+                       bool list_all,
+                       PVRSRV_DEVICE_NODE *psDevNode)
 {
        int i, result;
        int device_value_offset = device_num * APPHINT_DEBUGINFO_DEVICE_ID_MAX;
@@ -1076,7 +1134,7 @@ static void apphint_dump_values(const char *group_name,
                const struct apphint_action *action = &apphint.val[id + device_value_offset];
                union apphint_value value;
 
-               result = get_apphint_value_from_action(action, &value);
+               result = get_apphint_value_from_action(action, &value, psDevNode);
 
                if (PVRSRV_OK != result) {
                        continue;
@@ -1122,15 +1180,15 @@ static void apphint_dump_state(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
 
                apphint_dump_values("Build Vars", 0,
                        init_data_buildvar, ARRAY_SIZE(init_data_buildvar),
-                       pfnDumpDebugPrintf, pvDumpDebugFile, true);
+                       pfnDumpDebugPrintf, pvDumpDebugFile, true, device);
 
                apphint_dump_values("Module Params", 0,
                        init_data_modparam, ARRAY_SIZE(init_data_modparam),
-                       pfnDumpDebugPrintf, pvDumpDebugFile, false);
+                       pfnDumpDebugPrintf, pvDumpDebugFile, false, device);
 
                apphint_dump_values("Debug Info Params", 0,
                        init_data_debuginfo, ARRAY_SIZE(init_data_debuginfo),
-                       pfnDumpDebugPrintf, pvDumpDebugFile, false);
+                       pfnDumpDebugPrintf, pvDumpDebugFile, false, device);
 
                for (i = 0; i < APPHINT_DEVICES_MAX; i++) {
                        if (!apphint.devices[i]
@@ -1149,7 +1207,7 @@ static void apphint_dump_state(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
                                            ARRAY_SIZE(init_data_debuginfo_device),
                                            pfnDumpDebugPrintf,
                                            pvDumpDebugFile,
-                                               false);
+                                               false, device);
                }
        }
 }
@@ -1203,14 +1261,14 @@ int pvr_apphint_device_register(PVRSRV_DEVICE_NODE *device)
 {
        int result, i;
        char device_num[APPHINT_BUFFER_SIZE];
-       unsigned device_value_offset;
+       unsigned int device_value_offset;
 
        if (!apphint.initialized) {
                result = -EAGAIN;
                goto err_out;
        }
 
-       if (apphint.num_devices+1 >= APPHINT_DEVICES_MAX) {
+       if (apphint.num_devices+1 > APPHINT_DEVICES_MAX) {
                result = -EMFILE;
                goto err_out;
        }
@@ -1334,131 +1392,193 @@ void pvr_apphint_deinit(void)
        apphint.initialized = 0;
 }
 
-void pvr_apphint_dump_state(void)
+void pvr_apphint_dump_state(PVRSRV_DEVICE_NODE *device)
 {
 #if defined(PDUMP)
-       IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
-
-       apphint_dump_state(NULL, DEBUG_REQUEST_VERBOSITY_HIGH,
-                          apphint_pdump_values, (void *)&ui32Flags);
+       /* NB. apphint_pdump_values() is the pfnDumpDebugPrintf
+        * function used when PDUMP is defined.
+        * apphintpdump_values() calls PDumpCommentKM(), which
+        * requires the device but as it is only called as a
+        * DUMPDEBUG_PRINTF_FUNC it is only passed pvDumpDebugFile
+        * (which happens to be the 4th parameter in the call to
+        * apphint_dump_state() below).
+        * Hence, we also need to pass device in the 4th parameter.
+        */
+       apphint_dump_state(device, DEBUG_REQUEST_VERBOSITY_HIGH,
+                          apphint_pdump_values, device);
 #endif
-       apphint_dump_state(NULL, DEBUG_REQUEST_VERBOSITY_HIGH,
+       apphint_dump_state(device, DEBUG_REQUEST_VERBOSITY_HIGH,
                           NULL, NULL);
 }
 
-int pvr_apphint_get_uint64(APPHINT_ID ue, IMG_UINT64 *pVal)
+
+int pvr_apphint_get_uint64(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT64 *pVal)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if (ue < APPHINT_ID_MAX) {
-               *pVal = apphint.val[ue].stored.UINT64;
-               error = 0;
+               if ((int)ue > APPHINT_DEBUGINFO_DEVICE_ID_OFFSET) // From this point, we're in the device apphints
+               {
+                       *pVal = apphint.val[ue + device_offset].stored.UINT64;
+                       error = 0;
+               }
+               else
+               {
+                       *pVal = apphint.val[ue].stored.UINT64;
+                       error = 0;
+               }
        }
        return error;
 }
 
-int pvr_apphint_get_uint32(APPHINT_ID ue, IMG_UINT32 *pVal)
+int pvr_apphint_get_uint32(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT32 *pVal)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if (ue < APPHINT_ID_MAX) {
-               *pVal = apphint.val[ue].stored.UINT32;
-               error = 0;
+               if ((int)ue > APPHINT_DEBUGINFO_DEVICE_ID_OFFSET) // From this point, we're in the device apphints
+               {
+                       *pVal = apphint.val[ue + device_offset].stored.UINT32;
+                       error = 0;
+               }
+               else
+               {
+                       *pVal = apphint.val[ue].stored.UINT32;
+                       error = 0;
+               }
        }
        return error;
 }
 
-int pvr_apphint_get_bool(APPHINT_ID ue, IMG_BOOL *pVal)
+int pvr_apphint_get_bool(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_BOOL *pVal)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if (ue < APPHINT_ID_MAX) {
-               error = 0;
-               *pVal = apphint.val[ue].stored.BOOL;
+               if ((int)ue > APPHINT_DEBUGINFO_DEVICE_ID_OFFSET) // From this point, we're in the device apphints
+               {
+                       *pVal = apphint.val[ue + device_offset].stored.BOOL;
+                       error = 0;
+               }
+               else
+               {
+                       *pVal = apphint.val[ue].stored.BOOL;
+                       error = 0;
+               }
        }
        return error;
 }
 
-int pvr_apphint_get_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size)
+int pvr_apphint_get_string(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
+
        if (ue < APPHINT_ID_MAX && apphint.val[ue].stored.STRING) {
-               if (OSStringLCopy(pBuffer, apphint.val[ue].stored.STRING, size) < size) {
-                       error = 0;
+               if ((int)ue > APPHINT_DEBUGINFO_DEVICE_ID_OFFSET) // From this point, we're in the device apphints
+               {
+                       if (OSStringLCopy(pBuffer, apphint.val[ue + device_offset].stored.STRING, size) < size) {
+                               error = 0;
+                       }
+               }
+               else
+               {
+                       if (OSStringLCopy(pBuffer, apphint.val[ue].stored.STRING, size) < size) {
+                               error = 0;
+                       }
                }
        }
        return error;
 }
 
-int pvr_apphint_set_uint64(APPHINT_ID ue, IMG_UINT64 Val)
+int pvr_apphint_set_uint64(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT64 Val)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if ((ue < APPHINT_ID_MAX) &&
                (param_lookup[ue].data_type == APPHINT_DATA_TYPE_UINT64)) {
 
-               if (apphint.val[ue].set.UINT64) {
-                       apphint.val[ue].set.UINT64(apphint.val[ue].device, apphint.val[ue].private_data, Val);
+               if (apphint.val[ue + device_offset].set.UINT64) {
+                       apphint.val[ue + device_offset].set.UINT64(apphint.val[ue + device_offset].device,
+                                                                                                        apphint.val[ue + device_offset].private_data,
+                                                                                                        Val);
                } else {
-                       apphint.val[ue].stored.UINT64 = Val;
+                       apphint.val[ue + device_offset].stored.UINT64 = Val;
                }
+               apphint.val[ue].device = device;
                error = 0;
        }
 
        return error;
 }
 
-int pvr_apphint_set_uint32(APPHINT_ID ue, IMG_UINT32 Val)
+int pvr_apphint_set_uint32(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT32 Val)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if ((ue < APPHINT_ID_MAX) &&
                (param_lookup[ue].data_type == APPHINT_DATA_TYPE_UINT32)) {
 
-               if (apphint.val[ue].set.UINT32) {
-                       apphint.val[ue].set.UINT32(apphint.val[ue].device, apphint.val[ue].private_data, Val);
+               if (apphint.val[ue + device_offset].set.UINT32) {
+                       apphint.val[ue + device_offset].set.UINT32(apphint.val[ue + device_offset].device,
+                                                                                                        apphint.val[ue + device_offset].private_data,
+                                                                                                        Val);
                } else {
-                       apphint.val[ue].stored.UINT32 = Val;
+                       apphint.val[ue + device_offset].stored.UINT32 = Val;
                }
+               apphint.val[ue].device = device;
                error = 0;
        }
 
        return error;
 }
 
-int pvr_apphint_set_bool(APPHINT_ID ue, IMG_BOOL Val)
+int pvr_apphint_set_bool(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_BOOL Val)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if ((ue < APPHINT_ID_MAX) &&
                (param_lookup[ue].data_type == APPHINT_DATA_TYPE_BOOL)) {
 
                error = 0;
-               if (apphint.val[ue].set.BOOL) {
-                       apphint.val[ue].set.BOOL(apphint.val[ue].device, apphint.val[ue].private_data, Val);
+               if (apphint.val[ue + device_offset].set.BOOL) {
+                       apphint.val[ue + device_offset].set.BOOL(apphint.val[ue + device_offset].device,
+                                                                                                apphint.val[ue + device_offset].private_data,
+                                                                                                Val);
                } else {
-                       apphint.val[ue].stored.BOOL = Val;
+                       apphint.val[ue + device_offset].stored.BOOL = Val;
                }
+               apphint.val[ue].device = device;
        }
 
        return error;
 }
 
-int pvr_apphint_set_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size)
+int pvr_apphint_set_string(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size)
 {
        int error = -ERANGE;
+       int device_offset = (device != NULL) ? device->sDevId.ui32InternalID * APPHINT_DEBUGINFO_DEVICE_ID_MAX : 0;
 
        if ((ue < APPHINT_ID_MAX) &&
                ((param_lookup[ue].data_type == APPHINT_DATA_TYPE_STRING) &&
-               apphint.val[ue].stored.STRING)) {
+               apphint.val[ue + device_offset].stored.STRING)) {
 
-               if (apphint.val[ue].set.STRING) {
-                       error = apphint.val[ue].set.STRING(apphint.val[ue].device, apphint.val[ue].private_data, pBuffer);
+               if (apphint.val[ue + device_offset].set.STRING) {
+                       error = apphint.val[ue + device_offset].set.STRING(apphint.val[ue + device_offset].device,
+                                                                                                                        apphint.val[ue + device_offset].private_data,
+                                                                                                                        pBuffer);
                } else {
-                       if (strlcpy(apphint.val[ue].stored.STRING, pBuffer, size) < size) {
+                       if (strlcpy(apphint.val[ue + device_offset].stored.STRING, pBuffer, size) < size) {
                                error = 0;
                        }
                }
+               apphint.val[ue].device = device;
        }
 
        return error;
@@ -1472,6 +1592,9 @@ void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
 {
        int device_value_offset;
 
+       PVR_DPF((APPHINT_DPF_LEVEL, "%s(%d, %p, %p, %p, %p)",
+                __func__, id, query, set, device, private_data));
+
        if (id >= APPHINT_ID_MAX) {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: AppHint ID (%d) is out of range, max (%d)",
@@ -1479,7 +1602,7 @@ void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
                return;
        }
 
-       get_value_offset_from_device(device, &device_value_offset);
+       get_value_offset_from_device(device, &device_value_offset, id);
 
        switch (param_lookup[id].data_type) {
        case APPHINT_DATA_TYPE_UINT64:
@@ -1508,6 +1631,9 @@ void pvr_apphint_register_handlers_uint32(APPHINT_ID id,
 {
        int device_value_offset;
 
+       PVR_DPF((APPHINT_DPF_LEVEL, "%s(%d, %p, %p, %p, %p)",
+                __func__, id, query, set, device, private_data));
+
        if (id >= APPHINT_ID_MAX) {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: AppHint ID (%d) is out of range, max (%d)",
@@ -1515,7 +1641,7 @@ void pvr_apphint_register_handlers_uint32(APPHINT_ID id,
                return;
        }
 
-       get_value_offset_from_device(device, &device_value_offset);
+       get_value_offset_from_device(device, &device_value_offset, id);
 
        switch (param_lookup[id].data_type) {
        case APPHINT_DATA_TYPE_UINT32:
@@ -1547,6 +1673,9 @@ void pvr_apphint_register_handlers_bool(APPHINT_ID id,
 {
        int device_value_offset;
 
+       PVR_DPF((APPHINT_DPF_LEVEL, "%s(%d, %p, %p, %p, %p)",
+                __func__, id, query, set, device, private_data));
+
        if (id >= APPHINT_ID_MAX) {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: AppHint ID (%d) is out of range, max (%d)",
@@ -1554,7 +1683,7 @@ void pvr_apphint_register_handlers_bool(APPHINT_ID id,
                return;
        }
 
-       get_value_offset_from_device(device, &device_value_offset);
+       get_value_offset_from_device(device, &device_value_offset, id);
 
        switch (param_lookup[id].data_type) {
        case APPHINT_DATA_TYPE_BOOL:
@@ -1584,6 +1713,9 @@ void pvr_apphint_register_handlers_string(APPHINT_ID id,
 {
        int device_value_offset;
 
+       PVR_DPF((APPHINT_DPF_LEVEL, "%s(%d, %p, %p, %p, %p)",
+                __func__, id, query, set, device, private_data));
+
        if (id >= APPHINT_ID_MAX) {
                PVR_DPF((PVR_DBG_ERROR,
                         "%s: AppHint ID (%d) is out of range, max (%d)",
@@ -1591,7 +1723,7 @@ void pvr_apphint_register_handlers_string(APPHINT_ID id,
                return;
        }
 
-       get_value_offset_from_device(device, &device_value_offset);
+       get_value_offset_from_device(device, &device_value_offset, id);
 
        switch (param_lookup[id].data_type) {
        case APPHINT_DATA_TYPE_STRING:
index 9b267d7..71e2ce9 100644 (file)
@@ -56,17 +56,17 @@ int pvr_apphint_init(void);
 void pvr_apphint_deinit(void);
 int pvr_apphint_device_register(PVRSRV_DEVICE_NODE *device);
 void pvr_apphint_device_unregister(PVRSRV_DEVICE_NODE *device);
-void pvr_apphint_dump_state(void);
+void pvr_apphint_dump_state(PVRSRV_DEVICE_NODE *device);
 
-int pvr_apphint_get_uint64(APPHINT_ID ue, IMG_UINT64 *pVal);
-int pvr_apphint_get_uint32(APPHINT_ID ue, IMG_UINT32 *pVal);
-int pvr_apphint_get_bool(APPHINT_ID ue, IMG_BOOL *pVal);
-int pvr_apphint_get_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size);
+int pvr_apphint_get_uint64(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT64 *pVal);
+int pvr_apphint_get_uint32(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT32 *pVal);
+int pvr_apphint_get_bool(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_BOOL *pVal);
+int pvr_apphint_get_string(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size);
 
-int pvr_apphint_set_uint64(APPHINT_ID ue, IMG_UINT64 Val);
-int pvr_apphint_set_uint32(APPHINT_ID ue, IMG_UINT32 Val);
-int pvr_apphint_set_bool(APPHINT_ID ue, IMG_BOOL Val);
-int pvr_apphint_set_string(APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size);
+int pvr_apphint_set_uint64(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT64 Val);
+int pvr_apphint_set_uint32(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_UINT32 Val);
+int pvr_apphint_set_bool(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_BOOL Val);
+int pvr_apphint_set_string(PVRSRV_DEVICE_NODE *device, APPHINT_ID ue, IMG_CHAR *pBuffer, size_t size);
 
 void pvr_apphint_register_handlers_uint64(APPHINT_ID id,
        PVRSRV_ERROR (*query)(const PVRSRV_DEVICE_NODE *device, const void *private_data, IMG_UINT64 *value),
index 712e9b1..62aa58e 100644 (file)
@@ -68,6 +68,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
 #include "pvr_sync.h"
+#if !defined(USE_PVRSYNC_DEVNODE)
+#include "pvr_sync_ioctl_drm.h"
+#endif
 #endif
 
 #include "ospvr_gputrace.h"
@@ -105,6 +108,7 @@ EXPORT_SYMBOL(PVRSRVCheckStatus);
 
 #include "pvr_debug.h"
 EXPORT_SYMBOL(PVRSRVGetErrorString);
+EXPORT_SYMBOL(PVRSRVGetDeviceInstance);
 #endif /* defined(SUPPORT_DISPLAY_CLASS) */
 
 #if defined(SUPPORT_RGX)
@@ -115,10 +119,10 @@ EXPORT_SYMBOL(RGXInitSLC);
 EXPORT_SYMBOL(RGXHWPerfConnect);
 EXPORT_SYMBOL(RGXHWPerfDisconnect);
 EXPORT_SYMBOL(RGXHWPerfControl);
-#if defined(HWPERF_PACKET_V2C_SIG)
+#if defined(RGX_FEATURE_HWPERF_VOLCANIC)
 EXPORT_SYMBOL(RGXHWPerfConfigureCounters);
 #else
-EXPORT_SYMBOL(RGXHWPerfConfigureAndEnableCounters);
+EXPORT_SYMBOL(RGXHWPerfConfigMuxCounters);
 EXPORT_SYMBOL(RGXHWPerfConfigureAndEnableCustomCounters);
 #endif
 EXPORT_SYMBOL(RGXHWPerfDisableCounters);
@@ -133,26 +137,37 @@ EXPORT_SYMBOL(OSRemoveTimer);
 #endif
 #endif
 
-CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile)
+static int PVRSRVDeviceSyncOpen(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+                                struct drm_file *psDRMFile);
+
+CONNECTION_DATA *LinuxServicesConnectionFromFile(struct file *pFile)
 {
        if (pFile)
        {
                struct drm_file *psDRMFile = pFile->private_data;
+               PVRSRV_CONNECTION_PRIV *psConnectionPriv = (PVRSRV_CONNECTION_PRIV*)psDRMFile->driver_priv;
 
-               return psDRMFile->driver_priv;
+               return (CONNECTION_DATA*)psConnectionPriv->pvConnectionData;
        }
 
        return NULL;
 }
 
-struct file *LinuxFileFromConnection(CONNECTION_DATA *psConnection)
+CONNECTION_DATA *LinuxSyncConnectionFromFile(struct file *pFile)
 {
-       ENV_CONNECTION_DATA *psEnvConnection;
+       if (pFile)
+       {
+               struct drm_file *psDRMFile = pFile->private_data;
+               PVRSRV_CONNECTION_PRIV *psConnectionPriv = (PVRSRV_CONNECTION_PRIV*)psDRMFile->driver_priv;
 
-       psEnvConnection = PVRSRVConnectionPrivateData(psConnection);
-       PVR_ASSERT(psEnvConnection != NULL);
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+               return (CONNECTION_DATA*)psConnectionPriv->pvConnectionData;
+#else
+               return (CONNECTION_DATA*)psConnectionPriv->pvSyncConnectionData;
+#endif
+       }
 
-       return psEnvConnection->psFile;
+       return NULL;
 }
 
 /**************************************************************************/ /*!
@@ -171,6 +186,12 @@ int PVRSRVDriverInit(void)
                return -ENOMEM;
        }
 
+       error = PVRSRVCommonDriverInit();
+       if (error != PVRSRV_OK)
+       {
+               return -ENODEV;
+       }
+
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
        error = pvr_sync_register_functions();
        if (error != PVRSRV_OK)
@@ -185,12 +206,6 @@ int PVRSRVDriverInit(void)
        }
 #endif
 
-       error = PVRSRVCommonDriverInit();
-       if (error != PVRSRV_OK)
-       {
-               return -ENODEV;
-       }
-
        os_err = pvr_apphint_init();
        if (os_err != 0)
        {
@@ -206,6 +221,21 @@ int PVRSRVDriverInit(void)
        }
 #endif
 
+#if defined(ANDROID)
+#if defined(CONFIG_PROC_FS)
+       error = PVRProcFsRegister();
+       if (error != PVRSRV_OK)
+       {
+               return -ENOMEM;
+       }
+#elif defined(CONFIG_DEBUG_FS)
+       error = PVRDebugFsRegister();
+       if (error != PVRSRV_OK)
+       {
+               return -ENOMEM;
+       }
+#endif /* defined(CONFIG_PROC_FS) || defined(CONFIG_DEBUG_FS) */
+#else
 #if defined(CONFIG_DEBUG_FS)
        error = PVRDebugFsRegister();
        if (error != PVRSRV_OK)
@@ -219,6 +249,7 @@ int PVRSRVDriverInit(void)
                return -ENOMEM;
        }
 #endif /* defined(CONFIG_DEBUG_FS) || defined(CONFIG_PROC_FS) */
+#endif /* defined(ANDROID) */
 
        error = PVRSRVIonStatsInitialise();
        if (error != PVRSRV_OK)
@@ -233,7 +264,6 @@ int PVRSRVDriverInit(void)
         * need it */
        PVRGpuTraceInitAppHintCallbacks(NULL);
 #endif
-
        return 0;
 }
 
@@ -248,16 +278,16 @@ void PVRSRVDriverDeinit(void)
 
        PVRSRVIonStatsDestroy();
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+       pvr_sync_deinit();
+#endif
+
        PVRSRVCommonDriverDeInit();
 
 #if defined(SUPPORT_RGX)
        PVRGpuTraceSupportDeInit();
 #endif
 
-#if defined(SUPPORT_NATIVE_FENCE_SYNC)
-       pvr_sync_deinit();
-#endif
-
        PVROSFuncDeInit();
 }
 
@@ -270,8 +300,6 @@ void PVRSRVDriverDeinit(void)
 */ /***************************************************************************/
 int PVRSRVDeviceInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       int error = 0;
-
 #if defined(SUPPORT_NATIVE_FENCE_SYNC)
        {
                PVRSRV_ERROR eError = pvr_sync_device_init(psDeviceNode->psDevConfig->pvOSDevice);
@@ -285,26 +313,17 @@ int PVRSRVDeviceInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 #endif
 
 #if defined(SUPPORT_RGX)
-       error = PVRGpuTraceInitDevice(psDeviceNode);
-       if (error != 0)
        {
-               PVR_DPF((PVR_DBG_WARNING,
-                        "%s: failed to initialise PVR GPU Tracing on device%d (%d)",
-                        __func__, psDeviceNode->sDevId.i32OsDeviceID, error));
+               int error = PVRGpuTraceInitDevice(psDeviceNode);
+               if (error != 0)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                "%s: failed to initialise PVR GPU Tracing on device%d (%d)",
+                                __func__, psDeviceNode->sDevId.i32OsDeviceID, error));
+               }
        }
 #endif
 
-       /* register the AppHint device control before device initialisation
-        * so individual AppHints can be configured during the init phase
-        */
-       error = pvr_apphint_device_register(psDeviceNode);
-       if (error != 0)
-       {
-               PVR_DPF((PVR_DBG_WARNING,
-                        "%s: failed to initialise device AppHints (%d)",
-                        __func__, error));
-       }
-
        return 0;
 }
 
@@ -317,8 +336,6 @@ int PVRSRVDeviceInit(PVRSRV_DEVICE_NODE *psDeviceNode)
 */ /***************************************************************************/
 void PVRSRVDeviceDeinit(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
-       pvr_apphint_device_unregister(psDeviceNode);
-
 #if defined(SUPPORT_RGX)
        PVRGpuTraceDeInitDevice(psDeviceNode);
 #endif
@@ -361,7 +378,8 @@ void PVRSRVDeviceShutdown(PVRSRV_DEVICE_NODE *psDeviceNode)
        }
 
        (void) PVRSRVSetDeviceSystemPowerState(psDeviceNode,
-                                                                                  PVRSRV_SYS_POWER_STATE_OFF);
+                                              PVRSRV_SYS_POWER_STATE_OFF,
+                                              PVRSRV_POWER_FLAGS_NONE);
 }
 
 /**************************************************************************/ /*!
@@ -378,7 +396,6 @@ int PVRSRVDeviceSuspend(PVRSRV_DEVICE_NODE *psDeviceNode)
         * while it's suspended (this is needed for Android). Acquire the bridge
         * lock first to ensure the driver isn't currently in use.
         */
-
        LinuxBridgeBlockClientsAccess(IMG_FALSE);
 
 #if defined(SUPPORT_AUTOVZ)
@@ -388,7 +405,8 @@ int PVRSRVDeviceSuspend(PVRSRV_DEVICE_NODE *psDeviceNode)
 #endif
 
        if (PVRSRVSetDeviceSystemPowerState(psDeviceNode,
-                                                                               PVRSRV_SYS_POWER_STATE_OFF) != PVRSRV_OK)
+                                                                               PVRSRV_SYS_POWER_STATE_OFF,
+                                                                               PVRSRV_POWER_FLAGS_SUSPEND) != PVRSRV_OK)
        {
                LinuxBridgeUnblockClientsAccess();
                return -EINVAL;
@@ -407,7 +425,8 @@ int PVRSRVDeviceSuspend(PVRSRV_DEVICE_NODE *psDeviceNode)
 int PVRSRVDeviceResume(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        if (PVRSRVSetDeviceSystemPowerState(psDeviceNode,
-                                                                               PVRSRV_SYS_POWER_STATE_ON) != PVRSRV_OK)
+                                                                               PVRSRV_SYS_POWER_STATE_ON,
+                                                                               PVRSRV_POWER_FLAGS_SUSPEND) != PVRSRV_OK)
        {
                return -EINVAL;
        }
@@ -427,21 +446,21 @@ int PVRSRVDeviceResume(PVRSRV_DEVICE_NODE *psDeviceNode)
 }
 
 /**************************************************************************/ /*!
-@Function     PVRSRVDeviceOpen
-@Description  Common device open.
+@Function     PVRSRVDeviceServicesOpen
+@Description  Services device open.
 @Input        psDeviceNode  The device node representing the device being
                             opened by a user mode process
 @Input        psDRMFile     The DRM file data that backs the file handle
                             returned to the user mode process
 @Return       int           0 on success and a Linux error code otherwise
 */ /***************************************************************************/
-int PVRSRVDeviceOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                                  struct drm_file *psDRMFile)
+int PVRSRVDeviceServicesOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             struct drm_file *psDRMFile)
 {
        static DEFINE_MUTEX(sDeviceInitMutex);
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        ENV_CONNECTION_PRIVATE_DATA sPrivData;
-       void *pvConnectionData;
+       PVRSRV_CONNECTION_PRIV *psConnectionPriv;
        PVRSRV_ERROR eError;
        int iErr = 0;
 
@@ -466,6 +485,23 @@ int PVRSRVDeviceOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
                goto out;
        }
 
+       if (psDRMFile->driver_priv == NULL)
+       {
+               /* Allocate psConnectionPriv (stores private data and release pfn under driver_priv) */
+               psConnectionPriv = kzalloc(sizeof(*psConnectionPriv), GFP_KERNEL);
+               if (!psConnectionPriv)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: No memory to allocate driver_priv data", __func__));
+                       iErr = -ENOMEM;
+                       mutex_unlock(&sDeviceInitMutex);
+                       goto fail_alloc_connection_priv;
+               }
+       }
+       else
+       {
+               psConnectionPriv = (PVRSRV_CONNECTION_PRIV*)psDRMFile->driver_priv;
+       }
+
        if (psDeviceNode->eDevState == PVRSRV_DEVICE_STATE_INIT)
        {
                eError = PVRSRVCommonDeviceInitialise(psDeviceNode);
@@ -475,7 +511,7 @@ int PVRSRVDeviceOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
                                         __func__, PVRSRVGetErrorString(eError)));
                        iErr = -ENODEV;
                        mutex_unlock(&sDeviceInitMutex);
-                       goto out;
+                       goto fail_device_init;
                }
 
 #if defined(SUPPORT_RGX)
@@ -485,22 +521,131 @@ int PVRSRVDeviceOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
        mutex_unlock(&sDeviceInitMutex);
 
        sPrivData.psDevNode = psDeviceNode;
-       sPrivData.psFile = psDRMFile->filp;
 
        /*
         * Here we pass the file pointer which will passed through to our
         * OSConnectionPrivateDataInit function where we can save it so
         * we can back reference the file structure from its connection
         */
-       eError = PVRSRVCommonConnectionConnect(&pvConnectionData, (void *) &sPrivData);
+       eError = PVRSRVCommonConnectionConnect(&psConnectionPriv->pvConnectionData,
+                                              (void *)&sPrivData);
        if (eError != PVRSRV_OK)
        {
                iErr = -ENOMEM;
+               goto fail_connect;
+       }
+
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       psConnectionPriv->pfDeviceRelease = PVRSRVCommonConnectionDisconnect;
+#endif
+       psDRMFile->driver_priv = (void*)psConnectionPriv;
+       goto out;
+
+fail_connect:
+fail_device_init:
+       kfree(psConnectionPriv);
+fail_alloc_connection_priv:
+out:
+       return iErr;
+}
+
+/**************************************************************************/ /*!
+@Function     PVRSRVDeviceSyncOpen
+@Description  Sync device open.
+@Input        psDeviceNode  The device node representing the device being
+                            opened by a user mode process
+@Input        psDRMFile     The DRM file data that backs the file handle
+                            returned to the user mode process
+@Return       int           0 on success and a Linux error code otherwise
+*/ /***************************************************************************/
+static int PVRSRVDeviceSyncOpen(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                struct drm_file *psDRMFile)
+{
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+       CONNECTION_DATA *psConnection = NULL;
+       ENV_CONNECTION_PRIVATE_DATA sPrivData;
+       PVRSRV_CONNECTION_PRIV *psConnectionPriv;
+       PVRSRV_ERROR eError;
+       int iErr = 0;
+
+       if (!psPVRSRVData)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: No device data", __func__));
+               iErr = -ENODEV;
                goto out;
        }
 
-       psDRMFile->driver_priv = pvConnectionData;
+       if (psDRMFile->driver_priv == NULL)
+       {
+               /* Allocate psConnectionPriv (stores private data and release pfn under driver_priv) */
+               psConnectionPriv = kzalloc(sizeof(*psConnectionPriv), GFP_KERNEL);
+               if (!psConnectionPriv)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: No memory to allocate driver_priv data", __func__));
+                       iErr = -ENOMEM;
+                       goto out;
+               }
+       }
+       else
+       {
+               psConnectionPriv = (PVRSRV_CONNECTION_PRIV*)psDRMFile->driver_priv;
+       }
+
+       /* Allocate connection data area, no stats since process not registered yet */
+       psConnection = kzalloc(sizeof(*psConnection), GFP_KERNEL);
+       if (!psConnection)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: No memory to allocate connection data", __func__));
+               iErr = -ENOMEM;
+               goto fail_alloc_connection;
+       }
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       psConnectionPriv->pvConnectionData = (void*)psConnection;
+#else
+       psConnectionPriv->pvSyncConnectionData = (void*)psConnection;
+#endif
+
+       sPrivData.psDevNode = psDeviceNode;
+
+       /* Call environment specific connection data init function */
+       eError = OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, &sPrivData);
+       if (eError != PVRSRV_OK)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: OSConnectionPrivateDataInit() failed (%s)",
+                       __func__, PVRSRVGetErrorString(eError)));
+               goto fail_private_data_init;
+       }
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       iErr = pvr_sync_open(psConnectionPriv->pvConnectionData, psDRMFile);
+#else
+       iErr = pvr_sync_open(psConnectionPriv->pvSyncConnectionData, psDRMFile);
+#endif
+       if (iErr)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: pvr_sync_open() failed(%d)",
+                               __func__, iErr));
+               goto fail_pvr_sync_open;
+       }
+#endif
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       psConnectionPriv->pfDeviceRelease = pvr_sync_close;
+#endif
+#endif
+       psDRMFile->driver_priv = psConnectionPriv;
+       goto out;
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE)
+fail_pvr_sync_open:
+       OSConnectionPrivateDataDeInit(psConnection->hOsPrivateData);
+#endif
+fail_private_data_init:
+       kfree(psConnection);
+fail_alloc_connection:
+       kfree(psConnectionPriv);
 out:
        return iErr;
 }
@@ -514,15 +659,63 @@ out:
 @Return       void
 */ /***************************************************************************/
 void PVRSRVDeviceRelease(PVRSRV_DEVICE_NODE *psDeviceNode,
-                                                          struct drm_file *psDRMFile)
+                         struct drm_file *psDRMFile)
 {
-       void *pvConnectionData = psDRMFile->driver_priv;
-
        PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 
-       psDRMFile->driver_priv = NULL;
-       if (pvConnectionData)
+       if (psDRMFile->driver_priv)
+       {
+               PVRSRV_CONNECTION_PRIV *psConnectionPriv = (PVRSRV_CONNECTION_PRIV*)psDRMFile->driver_priv;
+
+               if (psConnectionPriv->pvConnectionData)
+               {
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+                       if (psConnectionPriv->pfDeviceRelease)
+                       {
+                               psConnectionPriv->pfDeviceRelease(psConnectionPriv->pvConnectionData);
+                       }
+#else
+                       if (psConnectionPriv->pvConnectionData)
+                               PVRSRVCommonConnectionDisconnect(psConnectionPriv->pvConnectionData);
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE)
+                       if (psConnectionPriv->pvSyncConnectionData)
+                               pvr_sync_close(psConnectionPriv->pvSyncConnectionData);
+#endif
+#endif
+               }
+
+               kfree(psDRMFile->driver_priv);
+               psDRMFile->driver_priv = NULL;
+       }
+}
+
+int
+drm_pvr_srvkm_init(struct drm_device *dev, void *arg, struct drm_file *psDRMFile)
+{
+       struct drm_pvr_srvkm_init_data *data = arg;
+       struct pvr_drm_private *priv = dev->dev_private;
+       int iErr = 0;
+
+       switch (data->init_module)
        {
-               PVRSRVCommonConnectionDisconnect(pvConnectionData);
+               case PVR_SRVKM_SYNC_INIT:
+               {
+                       iErr = PVRSRVDeviceSyncOpen(priv->dev_node, psDRMFile);
+                       break;
+               }
+               case PVR_SRVKM_SERVICES_INIT:
+               {
+                       iErr = PVRSRVDeviceServicesOpen(priv->dev_node, psDRMFile);
+                       break;
+               }
+               default:
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: invalid init_module (%d)",
+                               __func__, data->init_module));
+                       iErr = -EINVAL;
+               }
        }
+
+       return iErr;
 }
index 1b2ffe1..7317a0a 100644 (file)
@@ -43,11 +43,43 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef MODULE_COMMON_H
 #define MODULE_COMMON_H
 
+#include "pvr_drm.h"
+
 /* DRVNAME is the name we use to register our driver. */
 #define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
 
 struct _PVRSRV_DEVICE_NODE_;
 struct drm_file;
+struct drm_device;
+
+/* psDRMFile->driver_priv will point to a PVRSV_CONNECTION_PRIV
+ * struct, which will contain a ptr to the CONNECTION_DATA and
+ * a pfn to the release function (which will differ depending
+ * on whether the connection is to Sync or Services).
+ */
+typedef void (*PFN_PVRSRV_DEV_RELEASE)(void *pvData);
+typedef struct
+{
+       /* pvConnectionData is used to hold Services connection data
+        * for all PVRSRV_DEVICE_INIT_MODE options.
+        */
+       void *pvConnectionData;
+
+       /* pfDeviceRelease is used to indicate the release function
+        * to be called when PVRSRV_DEVICE_INIT_MODE is PVRSRV_LINUX_DEV_INIT_ON_CONNECT,
+        * as we can then have one connections made (either for Services or Sync) per
+        * psDRMFile, and need to know which type of connection is being released
+        * (as the ioctl release call is common for both).
+        */
+       PFN_PVRSRV_DEV_RELEASE pfDeviceRelease;
+
+       /* pvSyncConnectionData is used to hold Sync connection data
+        * when PVRSRV_DEVICE_INIT_MODE is not PVRSRV_LINUX_DEV_INIT_ON_CONNECT,
+        * as we can then have two connections made (for Services and Sync) to
+        * the same psDRMFile.
+        */
+       void *pvSyncConnectionData;
+} PVRSRV_CONNECTION_PRIV;
 
 int PVRSRVDriverInit(void);
 void PVRSRVDriverDeinit(void);
@@ -59,9 +91,11 @@ void PVRSRVDeviceShutdown(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 int PVRSRVDeviceSuspend(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 int PVRSRVDeviceResume(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 
-int PVRSRVDeviceOpen(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
-                                                  struct drm_file *psDRMFile);
+int PVRSRVDeviceServicesOpen(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
+                             struct drm_file *psDRMFile);
 void PVRSRVDeviceRelease(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
-                                                          struct drm_file *psDRMFile);
+                         struct drm_file *psDRMFile);
+int drm_pvr_srvkm_init(struct drm_device *dev,
+                       void *arg, struct drm_file *psDRMFile);
 
 #endif /* MODULE_COMMON_H */
index 8b0ab4a..0c3bc2d 100644 (file)
@@ -83,10 +83,12 @@ PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, void *pvOS
 
        psEnvConnection->owner = current->tgid;
 
-       /* Save the pointer to our struct file */
-       psEnvConnection->psFile = psPrivData->psFile;
        psEnvConnection->psDevNode = psPrivData->psDevNode;
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+       psEnvConnection->pvPvrSyncPrivateData = NULL;
+#endif
+
 #if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
        psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocZMem(sizeof(ENV_ION_CONNECTION_DATA));
        if (psIonConnection == NULL)
index 386d79e..4534643 100644 (file)
@@ -98,7 +98,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "dma_support.h"
 #include "kernel_compatibility.h"
 
-#include "dma_km.h"
 #include "pvrsrv_sync_server.h"
 
 
@@ -173,10 +172,11 @@ void OSThreadDumpInfo(DUMPDEBUG_PRINTF_FUNC* pfnDumpDebugPrintf,
        }
 }
 
-PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
+PVRSRV_ERROR OSPhyContigPagesAlloc(PHYS_HEAP *psPhysHeap, size_t uiSize,
                                                        PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
                                                        IMG_PID uiPid)
 {
+       PVRSRV_DEVICE_NODE *psDevNode = PhysHeapDeviceNode(psPhysHeap);
        struct device *psDev = psDevNode->psDevConfig->pvOSDevice;
        IMG_CPU_PHYADDR sCpuPAddr;
        struct page *psPage;
@@ -227,7 +227,7 @@ PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
         * Even when more pages are allocated as base MMU object we still need one single physical address because
         * they are physically contiguous.
         */
-       PhysHeapCpuPAddrToDevPAddr(psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_CPU_LOCAL], 1, psDevPAddr, &sCpuPAddr);
+       PhysHeapCpuPAddrToDevPAddr(psPhysHeap, 1, psDevPAddr, &sCpuPAddr);
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
@@ -251,11 +251,13 @@ PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
        return PVRSRV_OK;
 }
 
-void OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
+void OSPhyContigPagesFree(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle)
 {
        struct page *psPage = (struct page*) psMemHandle->u.pvHandle;
        IMG_UINT32      uiSize, uiPageCount=0, ui32Order;
 
+       PVR_UNREFERENCED_PARAMETER(psPhysHeap);
+
        ui32Order = psMemHandle->uiOrder;
        uiPageCount = (1 << ui32Order);
        uiSize = (uiPageCount * PAGE_SIZE);
@@ -275,7 +277,7 @@ void OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
        psMemHandle->uiOrder = 0;
 }
 
-PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
+PVRSRV_ERROR OSPhyContigPagesMap(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle,
                                                size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
                                                void **pvPtr)
 {
@@ -286,7 +288,7 @@ PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMem
 
        PVR_UNREFERENCED_PARAMETER(actualSize); /* If we don't take an #ifdef path */
        PVR_UNREFERENCED_PARAMETER(uiSize);
-       PVR_UNREFERENCED_PARAMETER(psDevNode);
+       PVR_UNREFERENCED_PARAMETER(psPhysHeap);
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
@@ -310,7 +312,7 @@ PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMem
        return PVRSRV_OK;
 }
 
-void OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle, void *pvPtr)
+void OSPhyContigPagesUnmap(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle, void *pvPtr)
 {
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if !defined(PVRSRV_ENABLE_MEMORY_STATS)
@@ -325,17 +327,18 @@ void OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle
 #endif
 #endif
 
-       PVR_UNREFERENCED_PARAMETER(psDevNode);
+       PVR_UNREFERENCED_PARAMETER(psPhysHeap);
        PVR_UNREFERENCED_PARAMETER(pvPtr);
 
        kunmap((struct page*) psMemHandle->u.pvHandle);
 }
 
-PVRSRV_ERROR OSPhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+PVRSRV_ERROR OSPhyContigPagesClean(PHYS_HEAP *psPhysHeap,
                                    PG_HANDLE *psMemHandle,
                                    IMG_UINT32 uiOffset,
                                    IMG_UINT32 uiLength)
 {
+       PVRSRV_DEVICE_NODE *psDevNode = PhysHeapDeviceNode(psPhysHeap);
        PVRSRV_ERROR eError = PVRSRV_OK;
        struct page* psPage = (struct page*) psMemHandle->u.pvHandle;
 
@@ -473,7 +476,47 @@ size_t OSStringNLength(const IMG_CHAR *pStr, size_t uiCount)
 IMG_INT32 OSStringNCompare(const IMG_CHAR *pStr1, const IMG_CHAR *pStr2,
                           size_t uiSize)
 {
+#if defined(DEBUG)
+       /* Double-check that we are not passing NULL parameters in. If we are we
+        * return -1 (for arg1 == NULL, arg2 != NULL)
+        * 0 (for arg1 == NULL, arg2 == NULL
+        * +1 (for arg1 != NULL, arg2 == NULL)
+        * strncmp(arg1, arg2, size) otherwise
+        */
+       if (pStr1 == NULL)
+       {
+               if (pStr2 == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s(%p, %p, %d): Both args NULL",
+                                __func__, pStr1, pStr2, (int)uiSize));
+                       OSDumpStack();
+                       return 0;       /* Both NULL */
+               }
+               else
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s(%p, %p, %d): arg1 NULL",
+                                __func__, pStr1, pStr2, (int)uiSize));
+                       OSDumpStack();
+                       return -1;      /* NULL < non-NULL */
+               }
+       }
+       else
+       {
+               if (pStr2 == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s(%p, %p, %d): arg2 NULL",
+                                __func__, pStr1, pStr2, (int)uiSize));
+                       OSDumpStack();
+                       return +1;      /* non-NULL > NULL */
+               }
+               else
+               {
+                       return strncmp(pStr1, pStr2, uiSize);
+               }
+       }
+#else
        return strncmp(pStr1, pStr2, uiSize);
+#endif
 }
 
 PVRSRV_ERROR OSStringToUINT32(const IMG_CHAR *pStr, IMG_UINT32 ui32Base,
@@ -513,29 +556,96 @@ IMG_UINT32 OSStringUINT32ToStr(IMG_CHAR *pszBuf, size_t uSize,
        return ui32Len;
 }
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) || defined(SUPPORT_BUFFER_SYNC)
+static struct workqueue_struct *gpFenceStatusWq;
+
+static PVRSRV_ERROR _NativeSyncInit(void)
+{
+       gpFenceStatusWq = create_freezable_workqueue("pvr_fence_status");
+       if (!gpFenceStatusWq)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create foreign fence status workqueue",
+                                __func__));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+
+       return PVRSRV_OK;
+}
+
+static void _NativeSyncDeinit(void)
+{
+       destroy_workqueue(gpFenceStatusWq);
+}
+
+struct workqueue_struct *NativeSyncGetFenceStatusWq(void)
+{
+       if (!gpFenceStatusWq)
+       {
+#if defined(DEBUG)
+               PVR_ASSERT(gpFenceStatusWq);
+#endif
+               return NULL;
+       }
+
+       return gpFenceStatusWq;
+}
+#endif
+
 PVRSRV_ERROR OSInitEnvData(void)
 {
+       PVRSRV_ERROR eError = PVRSRV_OK;
 
        LinuxInitPhysmem();
 
        _OSInitThreadList();
 
-       return PVRSRV_OK;
-}
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) || defined(SUPPORT_BUFFER_SYNC)
+       eError = _NativeSyncInit();
+#endif
 
+       return eError;
+}
 
 void OSDeInitEnvData(void)
 {
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) || defined(SUPPORT_BUFFER_SYNC)
+       _NativeSyncDeinit();
+#endif
 
        LinuxDeinitPhysmem();
 }
 
-
 void OSReleaseThreadQuanta(void)
 {
        schedule();
 }
 
+void OSMemoryBarrier(volatile void *hReadback)
+{
+       mb();
+
+       if (hReadback)
+       {
+               /* Force a read-back to memory to avoid posted writes on certain buses
+                * e.g. PCI(E)
+                */
+               (void) OSReadDeviceMem32(hReadback);
+       }
+}
+
+void OSWriteMemoryBarrier(volatile void *hReadback)
+{
+       wmb();
+
+       if (hReadback)
+       {
+               /* Force a read-back to memory to avoid posted writes on certain buses
+                * e.g. PCI(E)
+                */
+               (void) OSReadDeviceMem32(hReadback);
+       }
+}
+
 /* Not matching/aligning this API to the Clockus() API above to avoid necessary
  * multiplication/division operations in calling code.
  */
@@ -863,7 +973,7 @@ PVRSRV_ERROR OSScheduleMISR(IMG_HANDLE hMISRData)
 #else
        {
                bool rc = queue_work(psMISRData->psWorkQueue, &psMISRData->sMISRWork);
-               return (rc ? PVRSRV_OK : PVRSRV_ERROR_ALREADY_EXISTS);
+               return rc ? PVRSRV_OK : PVRSRV_ERROR_ALREADY_EXISTS;
        }
 #endif
 }
@@ -903,7 +1013,7 @@ static int OSThreadRun(void *data)
        /* Wait for OSThreadDestroy() to call kthread_stop() */
        while (!kthread_freezable_should_stop(NULL))
        {
-                schedule();
+               schedule();
        }
 
        LinuxBridgeNumActiveKernelThreadsDecrement();
@@ -1902,8 +2012,6 @@ static void dma_callback(void *pvOSCleanup)
        }
 
        spin_unlock_irqrestore(&psOSCleanup->spinlock, flags);
-
-       return;
 }
 
 #if defined(SUPPORT_VALIDATION) && defined(PVRSRV_DEBUG_DMA)
@@ -2123,7 +2231,7 @@ PVRSRV_ERROR OSDmaPrepareTransfer(PVRSRV_DEVICE_NODE *psDevNode,
        struct dma_async_tx_descriptor *psDesc;
 
        unsigned long offset = (unsigned long)puiAddress & ((1 << PAGE_SHIFT) - 1);
-       unsigned num_pages = (uiSize + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       unsigned int num_pages = (uiSize + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        int num_pinned_pages = 0;
        unsigned int gup_flags = 0;
 
@@ -2133,7 +2241,7 @@ PVRSRV_ERROR OSDmaPrepareTransfer(PVRSRV_DEVICE_NODE *psDevNode,
        psOSCleanupData->pages[psOSCleanupData->uiCount] = OSAllocZMem(num_pages * sizeof(struct page *));
        PVR_LOG_GOTO_IF_NOMEM(psOSCleanupData->pages[psOSCleanupData->uiCount], eError, e1);
 
-       gup_flags |= bMemToDev ? 0 : (FOLL_WRITE | FOLL_POPULATE);
+       gup_flags |= bMemToDev ? 0 : FOLL_WRITE;
 
        num_pinned_pages = get_user_pages_fast(
                        (unsigned long)puiAddress,
@@ -2183,9 +2291,9 @@ PVRSRV_ERROR OSDmaPrepareTransfer(PVRSRV_DEVICE_NODE *psDevNode,
                goto e4;
        }
 
-       dma_sync_sg_for_device(psDevConfig->pvOSDevice, psSg->sgl,(unsigned)iRet, sConfig.direction);
+       dma_sync_sg_for_device(psDevConfig->pvOSDevice, psSg->sgl,(unsigned int)iRet, sConfig.direction);
 
-       psDesc = dmaengine_prep_slave_sg(pvChan, psSg->sgl, (unsigned)iRet, sConfig.direction, 0);
+       psDesc = dmaengine_prep_slave_sg(pvChan, psSg->sgl, (unsigned int)iRet, sConfig.direction, 0);
        if (!psDesc)
        {
                PVR_DPF((PVR_DBG_ERROR, "%s: dmaengine_prep_slave_sg failed", __func__));
@@ -2276,9 +2384,9 @@ PVRSRV_ERROR OSDmaPrepareTransferSparse(PVRSRV_DEVICE_NODE *psDevNode,
        struct dma_async_tx_descriptor *psDesc;
 
        unsigned long offset = (unsigned long)puiAddress & ((1 << PAGE_SHIFT) - 1);
-       unsigned num_pages = (uiSize + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       unsigned int num_pages = (uiSize + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        unsigned int num_valid_pages = CalculateValidPages(pbValid, ui32SizeInPages);
-       unsigned num_pinned_pages = 0;
+       unsigned int num_pinned_pages = 0;
        unsigned int gup_flags = 0;
        unsigned int valid_idx;
        size_t transfer_size;
@@ -2305,7 +2413,7 @@ PVRSRV_ERROR OSDmaPrepareTransferSparse(PVRSRV_DEVICE_NODE *psDevNode,
        psOSCleanupData->ppsDescriptorsSparse[psOSCleanupData->uiCount] = OSAllocZMem(num_valid_pages * sizeof(struct dma_async_tx_descriptor *));
        PVR_LOG_GOTO_IF_NOMEM(psOSCleanupData->ppsDescriptorsSparse[psOSCleanupData->uiCount], eError, e11);
 
-       gup_flags |= bMemToDev ? 0 : (FOLL_WRITE | FOLL_POPULATE);
+       gup_flags |= bMemToDev ? 0 : FOLL_WRITE;
 
        for (ui32Idx = 0, valid_idx = 0; ui32Idx < ui32SizeInPages; ui32Idx++)
        {
@@ -2345,7 +2453,7 @@ PVRSRV_ERROR OSDmaPrepareTransferSparse(PVRSRV_DEVICE_NODE *psDevNode,
                        }
                }
 
-               if ((unsigned long long)pvNextAddress + transfer_size > PAGE_ALIGN((unsigned long long)pvNextAddress))
+               if (((unsigned long long)pvNextAddress & (ui32PageSize - 1)) + transfer_size > ui32PageSize)
                {
                        num_pages = 2;
                }
@@ -2410,9 +2518,9 @@ PVRSRV_ERROR OSDmaPrepareTransferSparse(PVRSRV_DEVICE_NODE *psDevNode,
                        eError = PVRSRV_ERROR_INVALID_PARAMS;
                        goto e5;
                }
-               dma_sync_sg_for_device(psDevConfig->pvOSDevice, psSg->sgl,(unsigned)iRet, sConfig.direction);
+               dma_sync_sg_for_device(psDevConfig->pvOSDevice, psSg->sgl,(unsigned int)iRet, sConfig.direction);
 
-               psDesc = dmaengine_prep_slave_sg(pvChan, psSg->sgl, (unsigned)iRet, sConfig.direction, 0);
+               psDesc = dmaengine_prep_slave_sg(pvChan, psSg->sgl, (unsigned int)iRet, sConfig.direction, 0);
                if (!psDesc)
                {
                        PVR_DPF((PVR_DBG_ERROR, "%s: dmaengine_prep_slave_sg failed", __func__));
index d2a8329..68d1285 100644 (file)
@@ -52,6 +52,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "osfunc.h"
 #include "pvr_debug.h"
 
+#include "kernel_compatibility.h"
+
 #if defined(CONFIG_OUTER_CACHE)
   /* If you encounter a 64-bit ARM system with an outer cache, you'll need
    * to add the necessary code to manage that cache. See osfunc_arm.c
@@ -63,14 +65,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 static inline void begin_user_mode_access(void)
 {
 #if defined(CONFIG_ARM64) && defined(CONFIG_ARM64_SW_TTBR0_PAN)
-       uaccess_enable();
+       uaccess_enable_privileged();
 #endif
 }
 
 static inline void end_user_mode_access(void)
 {
 #if defined(CONFIG_ARM64) && defined(CONFIG_ARM64_SW_TTBR0_PAN)
-       uaccess_disable();
+       uaccess_disable_privileged();
 #endif
 }
 
index a0cd2a7..0de3bf4 100644 (file)
@@ -185,7 +185,7 @@ OS_CACHE_OP_ADDR_TYPE OSCPUCacheOpAddressType(void)
         * Return BOTH for now on.
         *
         */
-       return OS_CACHE_OP_ADDR_TYPE_PHYSICAL;
+       return OS_CACHE_OP_ADDR_TYPE_PHYSICAL;//OS_CACHE_OP_ADDR_TYPE_BOTH;
 }
 
 void OSUserModeAccessToPerfCountersEn(void)
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/env/linux/ossecure_export.c b/drivers/gpu/drm/img/img-rogue/services/server/env/linux/ossecure_export.c
new file mode 100644 (file)
index 0000000..1070067
--- /dev/null
@@ -0,0 +1,155 @@
+/*************************************************************************/ /*!
+@File
+@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.
+*/ /**************************************************************************/
+
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/cred.h>
+
+#include "img_types.h"
+#include "img_defs.h"
+#include "ossecure_export.h"
+#include "private_data.h"
+#include "pvr_debug.h"
+
+#include "kernel_compatibility.h"
+
+typedef struct
+{
+       PVRSRV_ERROR (*pfnReleaseFunc)(void *);
+       void *pvData;
+} OSSecureFileData;
+
+static IMG_INT _OSSecureFileReleaseFunc(struct inode *psInode,
+                                        struct file *psFile)
+{
+       OSSecureFileData *psSecureFileData = (OSSecureFileData *)psFile->private_data;
+       psSecureFileData->pfnReleaseFunc(psSecureFileData->pvData);
+
+       OSFreeMem(psSecureFileData);
+       PVR_UNREFERENCED_PARAMETER(psInode);
+
+       return 0;
+}
+
+static struct file_operations secure_file_fops = {
+       .release        = _OSSecureFileReleaseFunc,
+};
+
+PVRSRV_ERROR OSSecureExport(const IMG_CHAR *pszName,
+                            PVRSRV_ERROR (*pfnReleaseFunc)(void *),
+                            void *pvData,
+                            IMG_SECURE_TYPE *phSecure)
+{
+       struct file *secure_file;
+       int secure_fd;
+       PVRSRV_ERROR eError;
+       OSSecureFileData *psSecureFileData;
+
+       PVR_ASSERT(pfnReleaseFunc != NULL || pvData != NULL);
+
+       psSecureFileData = OSAllocMem(sizeof(*psSecureFileData));
+       if (psSecureFileData == NULL)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto e0;
+       }
+
+       psSecureFileData->pvData = pvData;
+       psSecureFileData->pfnReleaseFunc = pfnReleaseFunc;
+
+       /* Allocate a fd number */
+       secure_fd = get_unused_fd();
+       if (secure_fd < 0)
+       {
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto e0;
+       }
+
+       /* Create a file with provided name, fops and flags,
+        * also store the private data in the file */
+       secure_file = anon_inode_getfile(pszName, &secure_file_fops, psSecureFileData, 0);
+       if (IS_ERR(secure_file))
+       {
+               put_unused_fd(secure_fd);
+               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+               goto e0;
+       }
+
+       /* Bind our struct file with it's fd number */
+       fd_install(secure_fd, secure_file);
+
+       *phSecure = secure_fd;
+       return PVRSRV_OK;
+
+e0:
+       OSFreeMem(psSecureFileData);
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
+
+PVRSRV_ERROR OSSecureImport(IMG_SECURE_TYPE hSecure, void **ppvData)
+{
+       struct file *secure_file;
+       PVRSRV_ERROR eError;
+       OSSecureFileData *psSecureFileData;
+
+       secure_file = fget(hSecure);
+       if (!secure_file)
+       {
+               eError = PVRSRV_ERROR_INVALID_PARAMS;
+               goto err_out;
+       }
+
+       psSecureFileData = (OSSecureFileData *)secure_file->private_data;
+       *ppvData = psSecureFileData->pvData;
+
+       fput(secure_file);
+       return PVRSRV_OK;
+
+err_out:
+       PVR_ASSERT(eError != PVRSRV_OK);
+       return eError;
+}
index 9acfe00..ac157b5 100644 (file)
@@ -105,7 +105,6 @@ static struct sg_table *PVRDmaBufOpsMap(struct dma_buf_attachment *psAttachment,
                                         enum dma_data_direction eDirection)
 {
        /* Attach hasn't been called yet */
-       dump_stack();
        return ERR_PTR(-EINVAL);
 }
 
@@ -131,7 +130,6 @@ static void *PVRDmaBufOpsKMap(struct dma_buf *psDmaBuf, unsigned long uiPageNum)
 
 static int PVRDmaBufOpsMMap(struct dma_buf *psDmaBuf, struct vm_area_struct *psVMA)
 {
-       dump_stack();
        return -ENOSYS;
 }
 
@@ -191,6 +189,80 @@ static IMG_UINT32 g_ui32HashRefCount;
 #define pvr_sg_length(sg) sg_dma_len(sg)
 #endif
 
+static int
+DmaBufSetValue(struct dma_buf *psDmaBuf, int iValue, const char *szFunc)
+{
+       struct dma_buf_map sMap;
+       int err, err_end_access;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0))
+       int i;
+#endif
+
+       err = dma_buf_begin_cpu_access(psDmaBuf, DMA_FROM_DEVICE);
+       if (err)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to begin cpu access (err=%d)",
+                                       szFunc, err));
+               goto err_out;
+       }
+
+       err = dma_buf_vmap(psDmaBuf, &sMap);
+       if (err)
+       {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map page (err=%d)",
+                                       szFunc, err));
+               goto exit_end_access;
+#else
+               for (i = 0; i < psDmaBuf->size / PAGE_SIZE; i++)
+               {
+                       void *pvKernAddr;
+
+                       pvKernAddr = dma_buf_kmap(psDmaBuf, i);
+                       if (IS_ERR_OR_NULL(pvKernAddr))
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map page (err=%ld)",
+                                                       szFunc,
+                                                       pvKernAddr ? PTR_ERR(pvKernAddr) : -ENOMEM));
+                               err = !pvKernAddr ? -ENOMEM : -EINVAL;
+
+                               goto exit_end_access;
+                       }
+
+                       memset(pvKernAddr, iValue, PAGE_SIZE);
+
+                       dma_buf_kunmap(psDmaBuf, i, pvKernAddr);
+               }
+#endif
+       }
+       else
+       {
+               memset(sMap.vaddr, iValue, psDmaBuf->size);
+
+               dma_buf_vunmap(psDmaBuf, &sMap);
+       }
+
+       err = 0;
+
+exit_end_access:
+       do {
+               err_end_access = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
+       } while (err_end_access == -EAGAIN || err_end_access == -EINTR);
+
+       if (err_end_access)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to end cpu access (err=%d)",
+                                       szFunc, err_end_access));
+               if (!err)
+               {
+                       err = err_end_access;
+               }
+       }
+
+err_out:
+       return err;
+}
+
 /*****************************************************************************
  *                          PMR callback functions                           *
  *****************************************************************************/
@@ -259,63 +331,16 @@ static PVRSRV_ERROR PMRFinalizeDmaBuf(PMR_IMPL_PRIVDATA pvPriv)
        if (psPrivData->bPoisonOnFree)
        {
                int err;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0))
-               int i;
-               void *pvKernAddr;
-#else
-               struct dma_buf_map sMap;
-#endif
 
-               err = dma_buf_begin_cpu_access(psDmaBuf, DMA_FROM_DEVICE);
+               err = DmaBufSetValue(psDmaBuf, PVRSRV_POISON_ON_FREE_VALUE, __func__);
                if (err)
                {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: Failed to begin cpu access for free poisoning (err=%d)",
-                                        __func__, err));
-                       PVR_ASSERT(IMG_FALSE);
-                       goto exit;
-               }
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
-               err = dma_buf_vmap(psDmaBuf, &sMap);
-               if (err != 0 || sMap.vaddr == NULL)
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: Failed to poison allocation before free",
-                                        __func__));
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to poison allocation before "
+                                               "free", __func__));
                        PVR_ASSERT(IMG_FALSE);
-                       goto exit_end_access;
                }
-
-               memset(sMap.vaddr, PVRSRV_POISON_ON_FREE_VALUE, psDmaBuf->size);
-
-               dma_buf_vunmap(psDmaBuf, &sMap);
-#else
-               for (i = 0; i < psDmaBuf->size / PAGE_SIZE; i++)
-               {
-                       pvKernAddr = dma_buf_kmap(psDmaBuf, i);
-                       if (IS_ERR_OR_NULL(pvKernAddr))
-                       {
-                               PVR_DPF((PVR_DBG_ERROR,
-                                                "%s: Failed to poison allocation before free (err=%ld)",
-                                                __func__, pvKernAddr ? PTR_ERR(pvKernAddr) : -ENOMEM));
-                               PVR_ASSERT(IMG_FALSE);
-                               goto exit_end_access;
-                       }
-
-                       memset(pvKernAddr, PVRSRV_POISON_ON_FREE_VALUE, PAGE_SIZE);
-
-                       dma_buf_kunmap(psDmaBuf, i, pvKernAddr);
-               }
-#endif
-
-exit_end_access:
-               do {
-                       err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
-               } while (err == -EAGAIN || err == -EINTR);
        }
 
-exit:
        if (psPrivData->pfnDestroy)
        {
                eError = psPrivData->pfnDestroy(psPrivData->psPhysHeap, psPrivData->psAttachment);
@@ -378,8 +403,9 @@ static PVRSRV_ERROR PMRDevPhysAddrDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
                        ui32PageIndex = puiOffset[idx] >> PAGE_SHIFT;
                        ui32InPageOffset = puiOffset[idx] - ((IMG_DEVMEM_OFFSET_T)ui32PageIndex << PAGE_SHIFT);
 
+                       PVR_LOG_RETURN_IF_FALSE(ui32PageIndex < psPrivData->ui32VirtPageCount,
+                                               "puiOffset out of range", PVRSRV_ERROR_OUT_OF_RANGE);
 
-                       PVR_ASSERT(ui32PageIndex < psPrivData->ui32VirtPageCount);
                        PVR_ASSERT(ui32InPageOffset < PAGE_SIZE);
                        psDevPAddr[idx].uiAddr = psPrivData->pasDevPhysAddr[ui32PageIndex].uiAddr + ui32InPageOffset;
                }
@@ -387,32 +413,18 @@ static PVRSRV_ERROR PMRDevPhysAddrDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
        return PVRSRV_OK;
 }
 
-#ifdef CACHE_TEST
 static PVRSRV_ERROR
 PMRAcquireKernelMappingDataDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
                                  size_t uiOffset,
                                  size_t uiSize,
-                                 size_t uilogicSize,
                                  void **ppvKernelAddressOut,
                                  IMG_HANDLE *phHandleOut,
                                  PMR_FLAGS_T ulFlags)
-#else
-static PVRSRV_ERROR
-PMRAcquireKernelMappingDataDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
-                                 size_t uiOffset,
-                                 size_t uiSize,
-                                 void **ppvKernelAddressOut,
-                                 IMG_HANDLE *phHandleOut,
-                                 PMR_FLAGS_T ulFlags)
-#endif
 {
        PMR_DMA_BUF_DATA *psPrivData = pvPriv;
        struct dma_buf *psDmaBuf = psPrivData->psAttachment->dmabuf;
        PVRSRV_ERROR eError;
        int err;
-#ifdef CACHE_TEST    
-       PVR_UNREFERENCED_PARAMETER(uilogicSize);
-#endif
 
        if (psPrivData->ui32PhysPageCount != psPrivData->ui32VirtPageCount)
        {
@@ -452,14 +464,12 @@ fail:
 }
 
 static void PMRReleaseKernelMappingDataDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
-                                             IMG_HANDLE hHandle, PMR *psPMR)
+                                             IMG_HANDLE hHandle)
 {
        PMR_DMA_BUF_DATA *psPrivData = pvPriv;
        struct dma_buf *psDmaBuf = psPrivData->psAttachment->dmabuf;
        int err;
 
-       PVR_UNREFERENCED_PARAMETER(psPMR);
-
        dma_buf_vunmap(psDmaBuf, &psPrivData->sMap);
 
        do {
@@ -484,7 +494,6 @@ static PVRSRV_ERROR PMRMMapDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
                return PVRSRV_ERROR_NOT_IMPLEMENTED;
        }
 
-       //dump_stack();  //arrive here...
        err = dma_buf_mmap(psDmaBuf, psVma, 0);
        if (err)
        {
@@ -492,7 +501,6 @@ static PVRSRV_ERROR PMRMMapDmaBuf(PMR_IMPL_PRIVDATA pvPriv,
        }
 
 #if defined(PVRSRV_ENABLE_LINUX_MMAP_STATS)
-sdaj;lll
        MMapStatsAddOrUpdatePMR(psPMR, psVma->vm_end - psVma->vm_start);
 #endif
 
@@ -546,8 +554,11 @@ PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap,
 
        bZeroOnAlloc = PVRSRV_CHECK_ZERO_ON_ALLOC(uiFlags);
        bPoisonOnAlloc = PVRSRV_CHECK_POISON_ON_ALLOC(uiFlags);
+#if defined(DEBUG)
        bPoisonOnFree = PVRSRV_CHECK_POISON_ON_FREE(uiFlags);
-
+#else
+       bPoisonOnFree = IMG_FALSE;
+#endif
        if (bZeroOnAlloc && bPoisonOnFree)
        {
                /* Zero on Alloc and Poison on Alloc are mutually exclusive */
@@ -583,82 +594,19 @@ PhysmemCreateNewDmaBufBackedPMR(PHYS_HEAP *psHeap,
 
        if (bZeroOnAlloc || bPoisonOnAlloc)
        {
+               int iValue = bZeroOnAlloc ? 0 : PVRSRV_POISON_ON_ALLOC_VALUE;
                int err;
-#if (LINUX_VERSION_CODE <KERNEL_VERSION(5, 6, 0))
-               int i;
-               void *pvKernAddr;
-#else
-               struct dma_buf_map sMap;
-#endif
 
-               err = dma_buf_begin_cpu_access(psDmaBuf, DMA_FROM_DEVICE);
+               err = DmaBufSetValue(psDmaBuf, iValue, __func__);
                if (err)
                {
-                       eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
-                       goto errFreePhysAddr;
-               }
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map buffer for %s",
+                                               __func__,
+                                               bZeroOnAlloc ? "zeroing" : "poisoning"));
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
-               err = dma_buf_vmap(psDmaBuf, &sMap);
-               if (err != 0 || sMap.vaddr == NULL)
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: Failed to map buffer for %s)",
-                                        __func__, bZeroOnAlloc ? "zeroing" : "poisoning"));
                        eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
-
-                       do {
-                               err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
-                       } while (err == -EAGAIN || err == -EINTR);
-
                        goto errFreePhysAddr;
                }
-
-               if (bZeroOnAlloc)
-               {
-                       memset(sMap.vaddr, 0, psDmaBuf->size);
-               }
-               else
-               {
-                       memset(sMap.vaddr, PVRSRV_POISON_ON_ALLOC_VALUE, psDmaBuf->size);
-               }
-
-               dma_buf_vunmap(psDmaBuf, &sMap);
-#else
-               for (i = 0; i < psDmaBuf->size / PAGE_SIZE; i++)
-               {
-                       pvKernAddr = dma_buf_kmap(psDmaBuf, i);
-                       if (IS_ERR_OR_NULL(pvKernAddr))
-                       {
-                               PVR_DPF((PVR_DBG_ERROR,
-                                                "%s: Failed to map page for %s (err=%ld)",
-                                                __func__, bZeroOnAlloc ? "zeroing" : "poisoning",
-                                                pvKernAddr ? PTR_ERR(pvKernAddr) : -ENOMEM));
-                               eError = PVRSRV_ERROR_PMR_NO_KERNEL_MAPPING;
-
-                               do {
-                                       err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
-                               } while (err == -EAGAIN || err == -EINTR);
-
-                               goto errFreePhysAddr;
-                       }
-
-                       if (bZeroOnAlloc)
-                       {
-                               memset(pvKernAddr, 0, PAGE_SIZE);
-                       }
-                       else
-                       {
-                               memset(pvKernAddr, PVRSRV_POISON_ON_ALLOC_VALUE, PAGE_SIZE);
-                       }
-
-                       dma_buf_kunmap(psDmaBuf, i, pvKernAddr);
-               }
-#endif
-
-               do {
-                       err = dma_buf_end_cpu_access(psDmaBuf, DMA_TO_DEVICE);
-               } while (err == -EAGAIN || err == -EINTR);
        }
 
        table = dma_buf_map_attachment(psAttachment, DMA_BIDIRECTIONAL);
@@ -830,11 +778,7 @@ PhysmemExportDmaBuf(CONNECTION_DATA *psConnection,
 
        PMRRefPMR(psPMR);
 
-       eError = PMR_LogicalSize(psPMR, &uiPMRSize);
-       if (eError != PVRSRV_OK)
-       {
-               goto fail_pmr_ref;
-       }
+       PMR_LogicalSize(psPMR, &uiPMRSize);
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
        {
@@ -941,6 +885,46 @@ PhysmemImportDmaBuf(CONNECTION_DATA *psConnection,
 }
 
 PVRSRV_ERROR
+PhysmemImportDmaBufLocked(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_INT fd,
+                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                          IMG_UINT32 ui32NameSize,
+                          const IMG_CHAR pszName[DEVMEM_ANNOTATION_MAX_LEN],
+                          PMR **ppsPMRPtr,
+                          IMG_DEVMEM_SIZE_T *puiSize,
+                          IMG_DEVMEM_ALIGN_T *puiAlign)
+{
+       PMR *psPMRPtr;
+       PVRSRV_ERROR eError;
+
+       eError = PhysmemImportDmaBuf(psConnection,
+                                    psDevNode,
+                                    fd,
+                                    uiFlags,
+                                    ui32NameSize,
+                                    pszName,
+                                    &psPMRPtr,
+                                    puiSize,
+                                    puiAlign);
+
+       if (eError == PVRSRV_OK)
+       {
+               eError = PMRLockSysPhysAddresses(psPMRPtr);
+               if (eError == PVRSRV_OK)
+               {
+                       *ppsPMRPtr = psPMRPtr;
+               }
+               else
+               {
+                       PMRUnrefPMR(psPMRPtr);
+               }
+       }
+
+       return eError;
+}
+
+PVRSRV_ERROR
 PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection,
                           PVRSRV_DEVICE_NODE *psDevNode,
                           IMG_INT fd,
index 3ab26ec..abd628e 100644 (file)
@@ -80,6 +80,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "cache_km.h"
 #include "devicemem_server_utils.h"
 #include "pvr_vmap.h"
+#include "physheap.h"
 
 /* ourselves */
 #include "physmem_osmem.h"
@@ -130,6 +131,8 @@ static IMG_UINT32 g_uiMaxOrder;
 #define DMA_GET_ADDR(x)                                        (((dma_addr_t)x) & ((dma_addr_t)~0xfff))
 #define DMA_VADDR_NOT_IN_USE                   0xCAFEF00DDEADBEEFULL
 
+#define PVRSRV_ZERO_VALUE 0
+
 typedef struct _PMR_OSPAGEARRAY_DATA_ {
        /* Device for which this allocation has been made */
        PVRSRV_DEVICE_NODE *psDevNode;
@@ -268,82 +271,6 @@ typedef struct
 } LinuxUnpinEntry;
 
 
-
-
-
-struct pmrx
-{
-       PHYS_HEAP *psPhysHeap;
-
-       ATOMIC_T iRefCount;
-
-       ATOMIC_T iLockCount;
-
-       /* Lock for this structure */
-       POS_LOCK hLock;
-
-       /* Incrementing serial number to each allocation. */
-       IMG_UINT64 uiSerialNum;
-
-       /* For security, we only allow a PMR to be mapped if the caller knows
-        * its key. We can pseudo-randomly generate keys
-        */
-       PMR_PASSWORD_T uiKey;
-
-       /* Callbacks for per-flavour functions */
-       const PMR_IMPL_FUNCTAB *psFuncTab;
-
-       /* Data associated with the "subtype" */
-       PMR_IMPL_PRIVDATA pvFlavourData;
-
-       /* What kind of PMR do we have? */
-       PMR_IMPL_TYPE eFlavour;
-
-       /* And for pdump */
-       const IMG_CHAR *pszPDumpDefaultMemspaceName;
-
-       /* Allocation annotation */
-       IMG_CHAR szAnnotation[DEVMEM_ANNOTATION_MAX_LEN];
-
-#if defined(PDUMP)
-       IMG_HANDLE hPDumpAllocHandle;
-       IMG_UINT32 uiNumPDumpBlocks;
-#endif
-
-       PMR_SIZE_T uiLogicalSize;
-
-       PMR_MAPPING_TABLE *psMappingTable;
-
-       IMG_BOOL bSparseAlloc;
-
-       IMG_BOOL bIsUnpinned;
-
-       IMG_BOOL bNoLayoutChange;
-
-       PMR_LOG2ALIGN_T uiLog2ContiguityGuarantee;
-
-       PMR_FLAGS_T uiFlags;
-
-       struct _PMR_CTX_ *psContext;
-
-#if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
-       /* Stored handle to PMR RI entry */
-       void            *hRIHandle;
-#endif
-};
-
-
-
-
-extern void *riscv_vmap(struct page **pages, unsigned int count,
-          unsigned long flags, pgprot_t prot);
-
-extern unsigned long va2pa(const void *vaddr_in);
-
-
-
-
-
 /* Caches to hold page pool and page array structures */
 static struct kmem_cache *g_psLinuxPagePoolCache;
 static struct kmem_cache *g_psLinuxPageArray;
@@ -1029,9 +956,10 @@ _GetPagesFromPoolLocked(PVRSRV_DEVICE_NODE *psDevNode,
 
 /* Takes a page array and maps it into the kernel to write zeros */
 static PVRSRV_ERROR
-_ZeroPageArray(IMG_UINT32 uiNumToClean,
-               struct page **ppsCleanArray,
-               pgprot_t pgprot)
+_MemsetPageArray(IMG_UINT32 uiNumToClean,
+                 struct page **ppsCleanArray,
+                 pgprot_t pgprot,
+                 IMG_UINT8 ui8Pattern)
 {
        IMG_CPU_VIRTADDR pvAddr;
        IMG_UINT32 uiMaxPagesToMap = MIN(PVR_LINUX_PHYSMEM_MAX_KMAP_PAGES,
@@ -1044,13 +972,15 @@ _ZeroPageArray(IMG_UINT32 uiNumToClean,
        {
                IMG_UINT32 uiToClean = MIN(uiNumToClean, uiMaxPagesToMap);
 
-               pvAddr = riscv_vmap(ppsCleanArray, uiToClean, VM_WRITE, pgprot);
+               pvAddr = pvr_vmap(ppsCleanArray, uiToClean, VM_WRITE, pgprot);
                if (!pvAddr)
                {
                        if (uiMaxPagesToMap <= 1)
                        {
-                               PVR_DPF((PVR_DBG_ERROR, "%s: Out of vmalloc memory, "
-                                       "unable to map pages for zeroing.", __func__));
+                               PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Out of vmalloc memory, unable to map pages for %s.",
+                                       __func__,
+                                       ui8Pattern == PVRSRV_ZERO_VALUE ? "zeroing" : "poisoning"));
                                return PVRSRV_ERROR_OUT_OF_MEMORY;
                        }
                        else
@@ -1065,18 +995,17 @@ _ZeroPageArray(IMG_UINT32 uiNumToClean,
                {
                        /* this is most likely unnecessary as all pages must be 8-bytes
                         * aligned so there unaligned access is impossible */
-                       OSDeviceMemSet(pvAddr, 0, PAGE_SIZE * uiToClean);
+                       OSDeviceMemSet(pvAddr, ui8Pattern, PAGE_SIZE * uiToClean);
                }
                else if (pgprot_val(pgprot) == pgprot_val(pgprot_writecombine(PAGE_KERNEL)))
                {
-                       OSCachedMemSet(pvAddr, 0, PAGE_SIZE * uiToClean);
-                       OSWriteMemoryBarrier();
+                       OSCachedMemSetWMB(pvAddr, ui8Pattern, PAGE_SIZE * uiToClean);
                }
                else
                {
-                       OSCachedMemSet(pvAddr, 0, PAGE_SIZE * uiToClean);
+                       OSCachedMemSet(pvAddr, ui8Pattern, PAGE_SIZE * uiToClean);
                }
-               vunmap(pvAddr);
+               pvr_vunmap(pvAddr, uiToClean, pgprot);
                ppsCleanArray = &(ppsCleanArray[uiToClean]);
                uiNumToClean -= uiToClean;
        }
@@ -1126,9 +1055,9 @@ _CleanupThread_CleanPages(void *pvData)
        /* Map and fill the pages with zeros.
         * For large page arrays do it PVR_LINUX_PHYSMEM_MAX_KMAP_SIZE
         * at a time. */
-       eError = _ZeroPageArray(psPagePoolEntry->uiItemsRemaining,
-                               psPagePoolEntry->ppsPageArray,
-                               pgprot);
+       eError = _MemsetPageArray(psPagePoolEntry->uiItemsRemaining,
+                                 psPagePoolEntry->ppsPageArray,
+                                 pgprot, PVRSRV_ZERO_VALUE);
        if (eError != PVRSRV_OK)
        {
                goto eExit;
@@ -1144,6 +1073,13 @@ _CleanupThread_CleanPages(void *pvData)
        list_add_tail(&psPagePoolEntry->sPagePoolItem, psPoolHead);
 
        _DumpPoolStructure();
+
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
+       /* Calling PVRSRVStatsIncrMemAllocPoolStat and PVRSRVStatsDecrMemAllocPoolStat
+        * inside page pool lock ensures that the stat reflects the state of the pool. */
+       PVRSRVStatsIncrMemAllocPoolStat(PAGE_SIZE * psPagePoolEntry->uiItemsRemaining);
+#endif
+
        _PagePoolUnlock();
 
        OSFreeMem(pvData);
@@ -1168,16 +1104,6 @@ eExit:
 
        *puiCounter -= psPagePoolEntry->uiItemsRemaining;
 
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-       /* MemStats usually relies on having the bridge lock held, however
-        * the page pool code may call PVRSRVStatsIncrMemAllocPoolStat and
-        * PVRSRVStatsDecrMemAllocPoolStat without the bridge lock held, so
-        * the page pool lock is used to ensure these calls are mutually
-        * exclusive
-        */
-       PVRSRVStatsDecrMemAllocPoolStat(PAGE_SIZE * psCleanupData->psPoolEntry->uiItemsRemaining);
-#endif
-
        _PagePoolUnlock();
 
        for (i = 0; i < psCleanupData->psPoolEntry->uiItemsRemaining; i++)
@@ -1284,16 +1210,6 @@ _PutPagesToPoolLocked(IMG_UINT32 ui32CPUCacheFlags,
                                CLEANUP_THREAD_SET_RETRY_COUNT(psCleanupThreadFn,
                                                               CLEANUP_THREAD_RETRY_COUNT_DEFAULT);
 
-       #if defined(PVRSRV_ENABLE_PROCESS_STATS)
-                               /* MemStats usually relies on having the bridge lock held, however
-                                * the page pool code may call PVRSRVStatsIncrMemAllocPoolStat and
-                                * PVRSRVStatsDecrMemAllocPoolStat without the bridge lock held, so
-                                * the page pool lock is used to ensure these calls are mutually
-                                * exclusive
-                                */
-                               PVRSRVStatsIncrMemAllocPoolStat(PAGE_SIZE * uiNumPages);
-       #endif
-
                                /* We must not hold the pool lock when calling AddWork because it might call us back to
                                 * free pooled pages directly when unloading the driver  */
                                _PagePoolUnlock();
@@ -1648,7 +1564,6 @@ _ApplyOSPagesAttribute(PVRSRV_DEVICE_NODE *psDevNode,
                        /* On x86 if we already have a mapping (e.g. low memory) we need to change the mode of
                                current mapping before we map it ourselves      */
                        int ret = IMG_FALSE;
-                       PVR_UNREFERENCED_PARAMETER(bFlush);
 
                        switch (PVRSRV_CPU_CACHE_MODE(ui32CPUCacheFlags))
                        {
@@ -1951,8 +1866,8 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
        IMG_BOOL bIncreaseMaxOrder = IMG_TRUE;
 
        IMG_UINT32 ui32NumPageReq;
-       IMG_UINT32 uiPagesToAlloc;
-       IMG_UINT32 uiPagesFromPool = 0;
+       IMG_UINT32 uiOSPagesToAlloc;
+       IMG_UINT32 uiDevPagesFromPool = 0;
 
        gfp_t gfp_flags = _GetGFPFlags(ui32MinOrder ? BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO) : IMG_FALSE, /* Zero all pages later as batch */
                                              psPageArrayData->psDevNode);
@@ -1962,22 +1877,22 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
        struct page **ppsPageArray = psPageArrayData->pagearray;
        struct page **ppsPageAttributeArray = NULL;
 
-       uiPagesToAlloc = psPageArrayData->uiTotalNumOSPages;
+       uiOSPagesToAlloc = psPageArrayData->uiTotalNumOSPages;
 
        /* Try to get pages from the pool since it is faster;
           the page pool currently only supports zero-order pages
           thus currently excludes all DMA/CMA allocated memory */
        _GetPagesFromPoolLocked(psPageArrayData->psDevNode,
                                                        psPageArrayData->ui32CPUCacheFlags,
-                                                       uiPagesToAlloc,
+                                                       uiOSPagesToAlloc,
                                                        ui32MinOrder,
                                                        BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO),
                                                        ppsPageArray,
-                                                       &uiPagesFromPool);
+                                                       &uiDevPagesFromPool);
 
-       uiArrayIndex = uiPagesFromPool;
+       uiArrayIndex = uiDevPagesFromPool;
 
-       if ((uiPagesToAlloc - uiPagesFromPool) < PVR_LINUX_HIGHORDER_ALLOCATION_THRESHOLD)
+       if ((uiOSPagesToAlloc - uiDevPagesFromPool) < PVR_LINUX_HIGHORDER_ALLOCATION_THRESHOLD)
        {       /* Small allocations: ask for one device page at a time */
                ui32Order = ui32MinOrder;
                bIncreaseMaxOrder = IMG_FALSE;
@@ -2010,9 +1925,9 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
        ui32GfpFlags = (ui32Order > ui32MinOrder) ? ui32HighOrderGfpFlags : gfp_flags;
        ui32NumPageReq = (1 << ui32Order);
 
-       while (uiArrayIndex < uiPagesToAlloc)
+       while (uiArrayIndex < uiOSPagesToAlloc)
        {
-               IMG_UINT32 ui32PageRemain = uiPagesToAlloc - uiArrayIndex;
+               IMG_UINT32 ui32PageRemain = uiOSPagesToAlloc - uiArrayIndex;
 
                while (ui32NumPageReq > ui32PageRemain)
                {
@@ -2081,7 +1996,7 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
                                                                __func__,
                                                                BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA) ? "dma_alloc_coherent" : "alloc_pages",
                                                                uiArrayIndex,
-                                                               uiPagesToAlloc,
+                                                               uiOSPagesToAlloc,
                                                                ui32GfpFlags,
                                                                ui32Order,
                                                                PVRSRVGetErrorString(eError)));
@@ -2097,25 +2012,20 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
        }
 
        /* Construct table of page pointers to apply attributes */
-       ppsPageAttributeArray = &ppsPageArray[uiPagesFromPool];
+       ppsPageAttributeArray = &ppsPageArray[uiDevPagesFromPool];
        if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA))
        {
                IMG_UINT32 uiIdx, uiIdy, uiIdz;
 
-               ppsPageAttributeArray = OSAllocMem(sizeof(struct page *) * uiPagesToAlloc);
-               if (ppsPageAttributeArray == NULL)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "Failed OSAllocMem() for page attributes table"));
-                       eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-                       goto e_free_pages;
-               }
+               ppsPageAttributeArray = OSAllocMem(sizeof(struct page *) * uiOSPagesToAlloc);
+               PVR_LOG_GOTO_IF_NOMEM(ppsPageAttributeArray, eError, e_free_pages);
 
-               for (uiIdx = 0; uiIdx < uiPagesToAlloc; uiIdx += ui32NumPageReq)
+               for (uiIdx = 0; uiIdx < uiOSPagesToAlloc; uiIdx += ui32NumPageReq)
                {
                        uiIdy = uiIdx >> ui32Order;
                        for (uiIdz = 0; uiIdz < ui32NumPageReq; uiIdz++)
                        {
-                               ppsPageAttributeArray[uiIdx+uiIdz] = psPageArrayData->pagearray[uiIdy];
+                               ppsPageAttributeArray[uiIdx+uiIdz] = ppsPageArray[uiIdy];
                                ppsPageAttributeArray[uiIdx+uiIdz] += uiIdz;
                        }
                }
@@ -2123,22 +2033,46 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
 
        if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO) && ui32MinOrder == 0)
        {
-               eError = _ZeroPageArray(uiPagesToAlloc - uiPagesFromPool,
-                                          ppsPageAttributeArray,
-                                          PAGE_KERNEL);
+               eError = _MemsetPageArray(uiOSPagesToAlloc - uiDevPagesFromPool,
+                                         ppsPageAttributeArray, PAGE_KERNEL,
+                                         PVRSRV_ZERO_VALUE);
                if (eError != PVRSRV_OK)
                {
                        PVR_DPF((PVR_DBG_ERROR, "Failed to zero pages (fast)"));
                        goto e_free_pages;
                }
        }
+       else if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_POISON_ON_ALLOC))
+       {
+               /* need to call twice because ppsPageArray and ppsPageAttributeArray
+                * can point to different allocations: first for pages obtained from
+                * the pool and then the remaining pages */
+               eError = _MemsetPageArray(uiDevPagesFromPool, ppsPageArray, PAGE_KERNEL,
+                                         PVRSRV_POISON_ON_ALLOC_VALUE);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Failed to poison pages (fast)"));
+               }
+               eError = _MemsetPageArray(uiOSPagesToAlloc - uiDevPagesFromPool,
+                                         ppsPageAttributeArray, PAGE_KERNEL,
+                                         PVRSRV_POISON_ON_ALLOC_VALUE);
+               if (eError != PVRSRV_OK)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "Failed to poison pages (fast)"));
+               }
 
+               /* for poisoning need to also flush the pool pages as the 0s have
+                * been overwritten */
+               _ApplyCacheMaintenance(psPageArrayData->psDevNode, ppsPageArray,
+                                      uiDevPagesFromPool);
+       }
 
        /* Do the cache management as required */
        eError = _ApplyOSPagesAttribute(psPageArrayData->psDevNode,
                                                                        ppsPageAttributeArray,
-                                                                       uiPagesToAlloc - uiPagesFromPool,
-                                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO),
+                                                                       uiOSPagesToAlloc - uiDevPagesFromPool,
+                                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO) ||
+                                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_POISON_ON_ALLOC),
                                                                        psPageArrayData->ui32CPUCacheFlags);
        if (eError != PVRSRV_OK)
        {
@@ -2156,13 +2090,13 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
        /* Update metadata */
        psPageArrayData->iNumOSPagesAllocated = psPageArrayData->uiTotalNumOSPages;
 
+#if defined(PVRSRV_ENABLE_PROCESS_STATS)
        {
+#if defined(PVRSRV_ENABLE_MEMORY_STATS)
                IMG_UINT32 ui32NumPages =
                        psPageArrayData->iNumOSPagesAllocated >> ui32MinOrder;
                IMG_UINT32 i;
 
-#if defined(PVRSRV_ENABLE_PROCESS_STATS)
-#if defined(PVRSRV_ENABLE_MEMORY_STATS)
                for (i = 0; i < ui32NumPages; i++)
                {
                        if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA))
@@ -2175,23 +2109,11 @@ _AllocOSPages_Fast(PMR_OSPAGEARRAY_DATA *psPageArrayData)
                        }
                }
 #else /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
-               _IncrMemAllocStat_UmaPages(((uiPagesToAlloc * PAGE_SIZE)+(psPageArrayData->ui32CMAAdjustedPageCount)),
+               _IncrMemAllocStat_UmaPages(((uiOSPagesToAlloc * PAGE_SIZE)+(psPageArrayData->ui32CMAAdjustedPageCount)),
                                           psPageArrayData->uiPid);
 #endif /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
-#endif /* defined(PVRSRV_ENABLE_PROCESS_STATS) */
-
-               if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_POISON_ON_ALLOC))
-               {
-                       for (i = 0; i < ui32NumPages; i++)
-                       {
-                               _PoisonDevicePage(psPageArrayData->psDevNode,
-                                                 ppsPageArray[i],
-                                                 ui32MinOrder,
-                                                 psPageArrayData->ui32CPUCacheFlags,
-                                                 PVRSRV_POISON_ON_ALLOC_VALUE);
-                       }
-               }
        }
+#endif /* defined(PVRSRV_ENABLE_PROCESS_STATS) */
 
        return PVRSRV_OK;
 
@@ -2227,7 +2149,7 @@ e_free_pages:
                else
                {
                        /* Free the pages we got from the pool */
-                       for (ui32PageToFree = 0; ui32PageToFree < uiPagesFromPool; ui32PageToFree++)
+                       for (ui32PageToFree = 0; ui32PageToFree < uiDevPagesFromPool; ui32PageToFree++)
                        {
                                _FreeOSPage(ui32MinOrder,
                                                        BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_UNSET_MEMORY_TYPE),
@@ -2235,7 +2157,7 @@ e_free_pages:
                                ppsPageArray[ui32PageToFree] = NULL;
                        }
 
-                       for (ui32PageToFree = uiPagesFromPool; ui32PageToFree < uiArrayIndex; ui32PageToFree++)
+                       for (ui32PageToFree = uiDevPagesFromPool; ui32PageToFree < uiArrayIndex; ui32PageToFree++)
                        {
                                _FreeOSPage(ui32MinOrder, IMG_FALSE, ppsPageArray[ui32PageToFree]);
                                ppsPageArray[ui32PageToFree] = NULL;
@@ -2246,6 +2168,33 @@ e_free_pages:
        }
 }
 
+static INLINE PVRSRV_ERROR
+_CheckIfIndexInRange(IMG_UINT32 ui32Index, IMG_UINT32 *pui32Indices, IMG_UINT32 ui32Limit)
+{
+       if (pui32Indices[ui32Index] >= ui32Limit)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Given alloc index %u at %u is larger than page array %u.",
+                       __func__, pui32Indices[ui32Index], ui32Index, ui32Limit));
+               return PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
+       }
+
+       return PVRSRV_OK;
+}
+
+static INLINE PVRSRV_ERROR
+_CheckIfPageNotAllocated(IMG_UINT32 ui32Index, IMG_UINT32 *pui32Indices, struct page **ppsPageArray)
+{
+       if (ppsPageArray[pui32Indices[ui32Index]] != NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Mapping number %u at page array index %u already exists. "
+                       "Page struct %p", __func__, pui32Indices[ui32Index], ui32Index,
+                       ppsPageArray[pui32Indices[ui32Index]]));
+               return PVRSRV_ERROR_PMR_MAPPING_ALREADY_EXISTS;
+       }
+
+       return PVRSRV_OK;
+}
+
 /* Allocation of OS pages: This function is used for sparse allocations.
  *
  * Sparse allocations provide only a proportion of sparse physical backing within the total
@@ -2253,183 +2202,186 @@ e_free_pages:
 static PVRSRV_ERROR
 _AllocOSPages_Sparse(PMR_OSPAGEARRAY_DATA *psPageArrayData,
                                         IMG_UINT32 *puiAllocIndices,
-                                        IMG_UINT32 uiPagesToAlloc)
+                                        IMG_UINT32 uiDevPagesToAlloc)
 {
        PVRSRV_ERROR eError;
        IMG_UINT32 i;
        struct page **ppsPageArray = psPageArrayData->pagearray;
        IMG_UINT32 uiOrder = psPageArrayData->uiLog2AllocPageSize - PAGE_SHIFT;
-       IMG_UINT32 uiPagesFromPool = 0;
-       IMG_UINT32 uiNumOSPagesToAlloc = uiPagesToAlloc * (1 << uiOrder);
-       IMG_UINT32 uiTotalNumAllocPages = psPageArrayData->uiTotalNumOSPages >> uiOrder;
-       gfp_t ui32GfpFlags = _GetGFPFlags(uiOrder ? BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO):
+       IMG_UINT32 uiDevPagesFromPool = 0;
+       IMG_UINT32 uiOSPagesToAlloc = uiDevPagesToAlloc * (1 << uiOrder);
+       IMG_UINT32 uiDevPagesAllocated = psPageArrayData->uiTotalNumOSPages >> uiOrder;
+       const IMG_UINT32 ui32AllocFlags = psPageArrayData->ui32AllocFlags;
+       gfp_t ui32GfpFlags = _GetGFPFlags(uiOrder ? BIT_ISSET(ui32AllocFlags, FLAG_ZERO):
                                                                          IMG_FALSE, /* Zero pages later as batch */
                                                                          psPageArrayData->psDevNode);
 
-        /* We use this page array to receive pages from the pool and then reuse it afterwards to
-         * store pages that need their cache attribute changed on x86*/
+       /* We use this page array to receive pages from the pool and then reuse it afterwards to
+        * store pages that need their cache attribute changed on x86 */
        struct page **ppsTempPageArray;
        IMG_UINT32 uiTempPageArrayIndex = 0;
 
        /* Allocate the temporary page array that we need here to receive pages
         * from the pool and to store pages that need their caching attributes changed.
         * Allocate number of OS pages to be able to use the attribute function later. */
-       ppsTempPageArray = OSAllocMem(sizeof(struct page*) * uiNumOSPagesToAlloc);
-       if (ppsTempPageArray == NULL)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed metadata allocation", __func__));
-               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto e_exit;
-       }
+       ppsTempPageArray = OSAllocMem(sizeof(struct page*) * uiOSPagesToAlloc);
+       PVR_LOG_GOTO_IF_NOMEM(ppsTempPageArray, eError, e_exit);
 
        /* Check the requested number of pages if they fit in the page array */
-       if (uiTotalNumAllocPages <
-                       ((psPageArrayData->iNumOSPagesAllocated >> uiOrder) + uiPagesToAlloc) )
+       if (uiDevPagesAllocated <
+               ((psPageArrayData->iNumOSPagesAllocated >> uiOrder) + uiDevPagesToAlloc))
        {
                PVR_DPF((PVR_DBG_ERROR,
                                 "%s: Trying to allocate more pages (Order %u) than this buffer can handle, "
                                 "Request + Allocated < Max! Request %u, Allocated %u, Max %u.",
                                 __func__,
                                 uiOrder,
-                                uiPagesToAlloc,
+                                uiDevPagesToAlloc,
                                 psPageArrayData->iNumOSPagesAllocated >> uiOrder,
-                                uiTotalNumAllocPages));
+                                uiDevPagesAllocated));
                eError = PVRSRV_ERROR_PMR_BAD_MAPPINGTABLE_SIZE;
                goto e_free_temp_array;
        }
 
-       /* Try to get pages from the pool since it is faster */
+       /* Try to get pages from the pool since it is faster. The pages from pool are going to be
+        * allocated only if:
+        * - PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES == 1 && uiOrder == 0
+        * - PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES == 0 && uiOrder == 0 &&
+        *   !BIT_ISSET(ui32AllocFlags, FLAG_ZERO) */
        _GetPagesFromPoolLocked(psPageArrayData->psDevNode,
                                                        psPageArrayData->ui32CPUCacheFlags,
-                                                       uiPagesToAlloc,
+                                                       uiDevPagesToAlloc,
                                                        uiOrder,
-                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO),
+                                                       BIT_ISSET(ui32AllocFlags, FLAG_ZERO),
                                                        ppsTempPageArray,
-                                                       &uiPagesFromPool);
+                                                       &uiDevPagesFromPool);
+
+       /* In general device pages can have higher order than 0 but page pool always provides only 0
+        * order pages so they can be assigned to the OS pages values (in other words if we're
+        * allocating non-4k pages uiDevPagesFromPool will always be 0) */
+       uiTempPageArrayIndex = uiDevPagesFromPool;
 
-       /* Allocate pages from the OS or move the pages that we got from the pool
-        * to the page array */
-       for (i = 0; i < uiPagesToAlloc; i++)
+       /* Move pages we got from the pool to the array. */
+       for (i = 0; i < uiDevPagesFromPool; i++)
        {
-               /* Check if the indices we are allocating are in range */
-               if (puiAllocIndices[i] >= uiTotalNumAllocPages)
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: Given alloc index %u at %u is larger than page array %u.",
-                                        __func__,
-                                        i,
-                                        puiAllocIndices[i],
-                                        uiTotalNumAllocPages));
-                       eError = PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE;
-                       goto e_free_pages;
-               }
+               eError = _CheckIfIndexInRange(i, puiAllocIndices, uiDevPagesAllocated);
+               PVR_GOTO_IF_ERROR(eError, e_free_pool_pages);
+               eError = _CheckIfPageNotAllocated(i, puiAllocIndices, ppsPageArray);
+               PVR_GOTO_IF_ERROR(eError, e_free_pool_pages);
 
-               /* Check if there is not already a page allocated at this position */
-               if (NULL != ppsPageArray[puiAllocIndices[i]])
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                        "%s: Mapping number %u at page array index %u already exists. "
-                                        "Page struct %p",
-                                        __func__,
-                                        i,
-                                        puiAllocIndices[i],
-                                        ppsPageArray[puiAllocIndices[i]]));
-                       eError = PVRSRV_ERROR_PMR_MAPPING_ALREADY_EXISTS;
-                       goto e_free_pages;
-               }
+               ppsPageArray[puiAllocIndices[i]] = ppsTempPageArray[i];
+       }
 
-               /* Finally assign a page to the array.
-                * Either from the pool or allocate a new one. */
-               if (uiPagesFromPool != 0)
+       /* Allocate pages from the OS */
+       for (i = uiDevPagesFromPool; i < uiDevPagesToAlloc; i++)
+       {
+               eError = _CheckIfIndexInRange(i, puiAllocIndices, uiDevPagesAllocated);
+               PVR_GOTO_IF_ERROR(eError, e_free_pages);
+               eError = _CheckIfPageNotAllocated(i, puiAllocIndices, ppsPageArray);
+               PVR_GOTO_IF_ERROR(eError, e_free_pages);
+
+               /* Allocated pages and assign them the array. */
+               if (BIT_ISSET(ui32AllocFlags, FLAG_IS_CMA))
                {
-                       uiPagesFromPool--;
-                       ppsPageArray[puiAllocIndices[i]] = ppsTempPageArray[uiPagesFromPool];
+                       /* As the DMA/CMA framework rounds-up request to the
+                          next power-of-two, we request multiple uiMinOrder
+                          pages to satisfy allocation request in order to
+                          minimise wasting memory */
+                       eError = _AllocOSPage_CMA(psPageArrayData,
+                                                                         ui32GfpFlags,
+                                                                         uiOrder,
+                                                                         uiOrder,
+                                                                         puiAllocIndices[i]);
+                       if (eError != PVRSRV_OK)
+                       {
+                               PVR_DPF((PVR_DBG_ERROR, "Failed to alloc CMA pages"));
+                               goto e_free_pages;
+                       }
                }
                else
                {
-                       if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA))
-                       {
+                       DisableOOMKiller();
+                       ppsPageArray[puiAllocIndices[i]] = alloc_pages(ui32GfpFlags, uiOrder);
+                       EnableOOMKiller();
+               }
 
-                               /* As the DMA/CMA framework rounds-up request to the
-                                  next power-of-two, we request multiple uiMinOrder
-                                  pages to satisfy allocation request in order to
-                                  minimise wasting memory */
-                               eError = _AllocOSPage_CMA(psPageArrayData,
-                                                                                 ui32GfpFlags,
-                                                                                 uiOrder,
-                                                                                 uiOrder,
-                                                                                 puiAllocIndices[i]);
-                               if (eError != PVRSRV_OK)
-                               {
-                                       PVR_DPF((PVR_DBG_ERROR, "Failed to alloc CMA pages"));
-                                       goto e_free_pages;
-                               }
-                       }
-                       else
-                       {
-                               DisableOOMKiller();
-                               ppsPageArray[puiAllocIndices[i]] = alloc_pages(ui32GfpFlags, uiOrder);
-                               EnableOOMKiller();
-                       }
+               if (ppsPageArray[puiAllocIndices[i]] != NULL)
+               {
+                       /* Append pages to the temporary array so it's easier to process
+                        * them later on. */
 
-                       if (ppsPageArray[puiAllocIndices[i]] != NULL)
+                       if (BIT_ISSET(ui32AllocFlags, FLAG_IS_CMA))
                        {
-                               /* Reusing the temp page array if it has no pool pages anymore */
-
-                               if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA))
-                               {
-                                       IMG_UINT32 idx;
-                                       struct page* psPageAddr;
+                               IMG_UINT32 idx;
+                               struct page *psPageAddr;
 
-                                       psPageAddr = ppsPageArray[puiAllocIndices[i]];
+                               psPageAddr = ppsPageArray[puiAllocIndices[i]];
 
-                                       for (idx = 0; idx < (1 << uiOrder); idx++)
-                                       {
-                                               ppsTempPageArray[uiTempPageArrayIndex + idx] = psPageAddr;
-                                               psPageAddr++;
-                                       }
-                                       uiTempPageArrayIndex += (1 << uiOrder);
-                               }
-                               else
+                               /* "divide" CMA pages into OS pages if they have higher order */
+                               for (idx = 0; idx < (1 << uiOrder); idx++)
                                {
-                                       ppsTempPageArray[uiTempPageArrayIndex] = ppsPageArray[puiAllocIndices[i]];
-                                       uiTempPageArrayIndex++;
+                                       ppsTempPageArray[uiTempPageArrayIndex + idx] = psPageAddr;
+                                       psPageAddr++;
                                }
+                               uiTempPageArrayIndex += (1 << uiOrder);
                        }
                        else
                        {
-                               /* Failed to alloc pages at required contiguity. Failed allocation */
-                               PVR_DPF((PVR_DBG_ERROR,
-                                                "%s: alloc_pages failed to honour request at %u of %u, flags = %x, order = %u",
-                                                __func__,
-                                                i,
-                                                uiPagesToAlloc,
-                                                ui32GfpFlags,
-                                                uiOrder));
-                               eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
-                               goto e_free_pages;
+                               ppsTempPageArray[uiTempPageArrayIndex] = ppsPageArray[puiAllocIndices[i]];
+                               uiTempPageArrayIndex++;
                        }
                }
-       }
-
-       if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO) && uiOrder == 0)
-       {
-               eError = _ZeroPageArray(uiTempPageArrayIndex,
-                                       ppsTempPageArray,
-                                       PAGE_KERNEL);
-               if (eError != PVRSRV_OK)
+               else
                {
-                       PVR_DPF((PVR_DBG_ERROR, "Failed to zero pages (sparse)"));
+                       /* Failed to alloc pages at required contiguity. Failed allocation */
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: alloc_pages failed to honour request at %u of %u, flags = %x, order = %u",
+                               __func__, i, uiDevPagesToAlloc, ui32GfpFlags, uiOrder));
+                       eError = PVRSRV_ERROR_PMR_FAILED_TO_ALLOC_PAGES;
                        goto e_free_pages;
                }
        }
 
+       if (BIT_ISSET(ui32AllocFlags, FLAG_ZERO) && uiOrder == 0)
+       {
+               /* At this point this array contains pages allocated from the page pool at its start
+                * and pages allocated from the OS after that.
+                * If there are pages from the pool here they must be zeroed already hence we don't have
+                * to do it again. This is because if PVR_LINUX_PHYSMEM_ZERO_ALL_PAGES is enabled pool pages
+                * are zeroed in the cleanup thread. If it's disabled they aren't, and in that case we never
+                * allocate pages with FLAG_ZERO from the pool. This is why those pages need to be zeroed
+                * here.
+                * All of the above is true for the 0 order pages. For higher order we never allocated from
+                * the pool and those pages are allocated already zeroed from the OS.
+                * Long story short we can always skip pages allocated from the pool because they are either
+                * zeroed or we didn't allocate any of them. */
+               eError = _MemsetPageArray(uiTempPageArrayIndex - uiDevPagesFromPool,
+                                         &ppsTempPageArray[uiDevPagesFromPool],
+                                         PAGE_KERNEL, PVRSRV_ZERO_VALUE);
+               PVR_LOG_GOTO_IF_FALSE(eError == PVRSRV_OK, "failed to zero pages (sparse)", e_free_pages);
+       }
+       else if (BIT_ISSET(ui32AllocFlags, FLAG_POISON_ON_ALLOC))
+       {
+               /* Here we need to poison all of the pages regardless if they were
+                * allocated from the pool or from the system. */
+               eError = _MemsetPageArray(uiTempPageArrayIndex, ppsTempPageArray,
+                                         PAGE_KERNEL, PVRSRV_POISON_ON_ALLOC_VALUE);
+               PVR_LOG_IF_FALSE(eError == PVRSRV_OK, "failed to poison pages (sparse)");
+
+               /* We need to flush the cache for the poisoned pool pages here. The flush for the pages
+                * allocated from the system is done below because we also need to add appropriate cache
+                * attributes to them. Pages allocated from the pool already come with correct caching
+                * mode. */
+               _ApplyCacheMaintenance(psPageArrayData->psDevNode, ppsTempPageArray, uiDevPagesFromPool);
+       }
+
        /* Do the cache management as required */
        eError = _ApplyOSPagesAttribute(psPageArrayData->psDevNode,
-                                                                       ppsTempPageArray,
-                                                                       uiTempPageArrayIndex,
-                                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_ZERO),
-                                                                       psPageArrayData->ui32CPUCacheFlags);
+                                       &ppsTempPageArray[uiDevPagesFromPool],
+                                       uiTempPageArrayIndex - uiDevPagesFromPool,
+                                       BIT_ISSET(ui32AllocFlags, FLAG_ZERO) ||
+                                       BIT_ISSET(ui32AllocFlags, FLAG_POISON_ON_ALLOC),
+                                       psPageArrayData->ui32CPUCacheFlags);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR, "Failed to set page attributes"));
@@ -2437,83 +2389,66 @@ _AllocOSPages_Sparse(PMR_OSPAGEARRAY_DATA *psPageArrayData,
        }
 
        /* Update metadata */
-       psPageArrayData->iNumOSPagesAllocated += uiNumOSPagesToAlloc;
+       psPageArrayData->iNumOSPagesAllocated += uiOSPagesToAlloc;
 
        /* Free temporary page array */
        OSFreeMem(ppsTempPageArray);
 
 #if defined(PVRSRV_ENABLE_PROCESS_STATS)
 #if defined(PVRSRV_ENABLE_MEMORY_STATS)
-       for (i = 0; i < uiPagesToAlloc; i++)
+       for (i = 0; i < uiDevPagesToAlloc; i++)
        {
                _AddMemAllocRecord_UmaPages(psPageArrayData,
                                            ppsPageArray[puiAllocIndices[i]]);
        }
 #else
-       _IncrMemAllocStat_UmaPages(((uiNumOSPagesToAlloc * PAGE_SIZE)+(psPageArrayData->ui32CMAAdjustedPageCount)),
+       _IncrMemAllocStat_UmaPages(((uiOSPagesToAlloc * PAGE_SIZE)+(psPageArrayData->ui32CMAAdjustedPageCount)),
                                   psPageArrayData->uiPid);
 #endif
 #endif
 
-       if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_POISON_ON_ALLOC))
-       {
-               for (i = 0; i < uiPagesToAlloc; i++)
-               {
-                       _PoisonDevicePage(psPageArrayData->psDevNode,
-                                         ppsPageArray[puiAllocIndices[i]],
-                                         uiOrder,
-                                         psPageArrayData->ui32CPUCacheFlags,
-                                         PVRSRV_POISON_ON_ALLOC_VALUE);
-               }
-       }
-
        return PVRSRV_OK;
 
-/* Error path */
 e_free_pages:
+       if (BIT_ISSET(ui32AllocFlags, FLAG_IS_CMA))
        {
-               IMG_UINT32 ui32PageToFree;
+               IMG_UINT32 uiDevPageSize = PAGE_SIZE << uiOrder;
 
-               if (BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_IS_CMA))
+               /* Free the pages we just allocated from the CMA */
+               for (; i > uiDevPagesFromPool; i--)
                {
-                       IMG_UINT32 uiDevPageSize = PAGE_SIZE << uiOrder;
-
-                       for (ui32PageToFree = 0; ui32PageToFree < i; ui32PageToFree++)
-                       {
-                               _FreeOSPage_CMA(psPageArrayData->psDevNode->psDevConfig->pvOSDevice,
-                                                               uiDevPageSize,
-                                                               uiOrder,
-                                                               psPageArrayData->dmavirtarray[puiAllocIndices[ui32PageToFree]],
-                                                               psPageArrayData->dmaphysarray[puiAllocIndices[ui32PageToFree]],
-                                                               ppsPageArray[puiAllocIndices[ui32PageToFree]]);
-                               psPageArrayData->dmaphysarray[puiAllocIndices[ui32PageToFree]]= (dma_addr_t)0;
-                               psPageArrayData->dmavirtarray[puiAllocIndices[ui32PageToFree]] = NULL;
-                               ppsPageArray[puiAllocIndices[ui32PageToFree]] = NULL;
-                       }
+                       _FreeOSPage_CMA(psPageArrayData->psDevNode->psDevConfig->pvOSDevice,
+                                       uiDevPageSize,
+                                       uiOrder,
+                                       psPageArrayData->dmavirtarray[puiAllocIndices[i-1]],
+                                       psPageArrayData->dmaphysarray[puiAllocIndices[i-1]],
+                                       ppsPageArray[puiAllocIndices[i-1]]);
+                       psPageArrayData->dmaphysarray[puiAllocIndices[i-1]]= (dma_addr_t) 0;
+                       psPageArrayData->dmavirtarray[puiAllocIndices[i-1]] = NULL;
+                       ppsPageArray[puiAllocIndices[i-1]] = NULL;
                }
-               else
+       }
+       else
+       {
+               /* Free the pages we just allocated from the OS */
+               for (; i > uiDevPagesFromPool; i--)
                {
-                       /* Free the pages we got from the pool */
-                       for (ui32PageToFree = 0; ui32PageToFree < uiPagesFromPool; ui32PageToFree++)
-                       {
-                               _FreeOSPage(0,
-                                                       BIT_ISSET(psPageArrayData->ui32AllocFlags, FLAG_UNSET_MEMORY_TYPE),
-                                                       ppsTempPageArray[ui32PageToFree]);
-                       }
+                       _FreeOSPage(0, IMG_FALSE, ppsPageArray[puiAllocIndices[i-1]]);
+                       ppsPageArray[puiAllocIndices[i-1]] = NULL;
+               }
+       }
 
-                       /* Free the pages we just allocated from the OS */
-                       for (ui32PageToFree = uiPagesFromPool; ui32PageToFree < i; ui32PageToFree++)
-                       {
-                               _FreeOSPage(0,
-                                                       IMG_FALSE,
-                                                       ppsPageArray[puiAllocIndices[ui32PageToFree]]);
-                       }
+e_free_pool_pages:
+       /* And now free all of the pages we allocated from the pool. */
+       for (i = 0; i < uiDevPagesFromPool; i++)
+       {
+               _FreeOSPage(0, BIT_ISSET(ui32AllocFlags, FLAG_UNSET_MEMORY_TYPE),
+                           ppsTempPageArray[i]);
 
-                       /* Reset all page array entries that have been set so far*/
-                       for (ui32PageToFree = 0; ui32PageToFree < i; ui32PageToFree++)
-                       {
-                               ppsPageArray[puiAllocIndices[ui32PageToFree]] = NULL;
-                       }
+               /* not using _CheckIfIndexInRange() to not print error message */
+               if (puiAllocIndices[i] < uiDevPagesAllocated)
+               {
+                       ppsPageArray[puiAllocIndices[i]] = NULL;
                }
        }
 
@@ -3078,6 +3013,13 @@ PMRUnlockSysPhysAddressesOSMem(PMR_IMPL_PRIVDATA pvPriv)
        return eError;
 }
 
+static INLINE IMG_BOOL IsOffsetValid(const PMR_OSPAGEARRAY_DATA *psOSPageArrayData,
+                                     IMG_UINT32 ui32Offset)
+{
+       return (ui32Offset >> psOSPageArrayData->uiLog2AllocPageSize) <
+           psOSPageArrayData->uiTotalNumOSPages;
+}
+
 /* Determine PA for specified offset into page array. */
 static IMG_DEV_PHYADDR GetOffsetPA(const PMR_OSPAGEARRAY_DATA *psOSPageArrayData,
                                    IMG_UINT32 ui32Offset)
@@ -3087,7 +3029,6 @@ static IMG_DEV_PHYADDR GetOffsetPA(const PMR_OSPAGEARRAY_DATA *psOSPageArrayData
        IMG_UINT32 ui32InPageOffset = ui32Offset - (ui32PageIndex << ui32Log2AllocPageSize);
        IMG_DEV_PHYADDR sPA;
 
-       PVR_ASSERT(ui32PageIndex < psOSPageArrayData->uiTotalNumOSPages);
        PVR_ASSERT(ui32InPageOffset < (1U << ui32Log2AllocPageSize));
 
        sPA.uiAddr = page_to_phys(psOSPageArrayData->pagearray[ui32PageIndex]);
@@ -3122,6 +3063,9 @@ PMRSysPhysAddrOSMem(PMR_IMPL_PRIVDATA pvPriv,
        {
                if (pbValid[uiIdx])
                {
+                       PVR_LOG_RETURN_IF_FALSE(IsOffsetValid(psOSPageArrayData, puiOffset[uiIdx]),
+                                               "puiOffset out of range", PVRSRV_ERROR_OUT_OF_RANGE);
+
                        psDevPAddr[uiIdx] = GetOffsetPA(psOSPageArrayData, puiOffset[uiIdx]);
 
 #if !defined(PVR_LINUX_PHYSMEM_USE_HIGHMEM_ONLY)
@@ -3152,25 +3096,13 @@ typedef struct _PMR_OSPAGEARRAY_KERNMAP_DATA_ {
        pgprot_t PageProps;
 } PMR_OSPAGEARRAY_KERNMAP_DATA;
 
-
-#ifdef CACHE_TEST
 static PVRSRV_ERROR
 PMRAcquireKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
                                                                 size_t uiOffset,
                                                                 size_t uiSize,
-                                                                size_t uilogicSize,
                                                                 void **ppvKernelAddressOut,
                                                                 IMG_HANDLE *phHandleOut,
                                                                 PMR_FLAGS_T ulFlags)
-#else
-static PVRSRV_ERROR
-PMRAcquireKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                                                                size_t uiOffset,
-                                                                size_t uiSize,                                                          
-                                                                void **ppvKernelAddressOut,
-                                                                IMG_HANDLE *phHandleOut,
-                                                                PMR_FLAGS_T ulFlags)
-#endif
 {
        PVRSRV_ERROR eError;
        PMR_OSPAGEARRAY_DATA *psOSPageArrayData = pvPriv;
@@ -3291,30 +3223,7 @@ PMRAcquireKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
                goto e1;
        }
 
-#ifdef CACHE_TEST
-       if(PVRSRV_CHECK_CPU_UNCACHED(ulFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(ulFlags) )
-       {
-               pvAddress = riscv_vmap(pagearray, ui32PageCount, VM_READ | VM_WRITE, prot);     
-       }
-       else
-#endif
-       {
-#ifdef CACHE_TEST      
-               if(uilogicSize <= 4096 )
-               {
-                       pvAddress = riscv_vmap(pagearray, ui32PageCount, VM_READ | VM_WRITE, prot);     
-               }
-               else
-#endif                 
-               {
-                       pvAddress = pvr_vmap(pagearray, ui32PageCount, VM_READ | VM_WRITE, prot);
-               }
-       }
-
-#ifdef CACHE_TEST      
-       //printk("## %s..L%d flag:%llx VA:%llx, PA:%llx, size:%ld\n", __func__, __LINE__, (unsigned long long)ulFlags, (unsigned long long)pvAddress, (unsigned long long)va2pa(pvAddress), uilogicSize);
-#endif
-
+       pvAddress = pvr_vmap(pagearray, ui32PageCount, VM_READ | VM_WRITE, prot);
        if (pvAddress == NULL)
        {
                eError = PVRSRV_ERROR_OUT_OF_MEMORY;
@@ -3349,37 +3258,13 @@ e0:
        return eError;
 }
 
-
 static void PMRReleaseKernelMappingDataOSMem(PMR_IMPL_PRIVDATA pvPriv,
-                                                                                        IMG_HANDLE hHandle, struct _PMR_ *psPMR)
+                                                                                        IMG_HANDLE hHandle)
 {
        PMR_OSPAGEARRAY_KERNMAP_DATA *psData = hHandle;
-#ifdef CACHE_TEST      
-       struct pmrx *pr = (struct pmrx *)psPMR;
-#endif
        PVR_UNREFERENCED_PARAMETER(pvPriv);
 
-#ifdef CACHE_TEST
-       if(PVRSRV_CHECK_CPU_UNCACHED(pr->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pr->uiFlags) )
-       {
-               vunmap(psData->pvBase);
-       }
-       else
-#endif         
-       {
-#ifdef CACHE_TEST
-        if(pr->uiLogicalSize <= 4096)
-        {
-            vunmap(psData->pvBase);    
-        }
-        else
-#endif
-        {
-                   pvr_vunmap(psData->pvBase, psData->ui32PageCount, psData->PageProps);
-        }
-       }
-
-       //pvr_vunmap(psData->pvBase, psData->ui32PageCount, psData->PageProps);
+       pvr_vunmap(psData->pvBase, psData->ui32PageCount, psData->PageProps);
        OSFreeMem(psData);
 }
 
@@ -3540,7 +3425,7 @@ PMRChangeSparseMemOSMem(PMR_IMPL_PRIVDATA pPriv,
                ui32CommonRequestCount = (ui32AllocPageCount > ui32FreePageCount) ?
                                ui32FreePageCount : ui32AllocPageCount;
 
-               PDUMP_PANIC(SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
+               PDUMP_PANIC(PMR_DeviceNode(psPMR), SPARSEMEM_SWAP, "Request to swap alloc & free pages not supported");
        }
 
        if (SPARSE_RESIZE_ALLOC == (uiFlags & SPARSE_RESIZE_ALLOC))
@@ -3869,11 +3754,13 @@ static void _EncodeAllocationFlags(IMG_UINT32 uiLog2AllocPageSize,
                BIT_SET(*ui32AllocFlags, FLAG_POISON_ON_ALLOC);
        }
 
+#if defined(DEBUG)
        /* Poison on free? */
        if (PVRSRV_CHECK_POISON_ON_FREE(uiFlags))
        {
                BIT_SET(*ui32AllocFlags, FLAG_POISON_ON_FREE);
        }
+#endif
 
        /* Indicate whether this is an allocation with default caching attribute (i.e cached) or not */
        if (PVRSRV_CHECK_CPU_UNCACHED(uiFlags) ||
@@ -3884,6 +3771,20 @@ static void _EncodeAllocationFlags(IMG_UINT32 uiLog2AllocPageSize,
 
 }
 
+void PhysmemGetOSRamMemStats(PHEAP_IMPL_DATA pvImplData,
+                                          IMG_UINT64 *pui64TotalSize,
+                                          IMG_UINT64 *pui64FreeSize)
+{
+       struct sysinfo sMeminfo;
+       si_meminfo(&sMeminfo);
+
+       PVR_UNREFERENCED_PARAMETER(pvImplData);
+
+       *pui64TotalSize = sMeminfo.totalram * sMeminfo.mem_unit;
+       *pui64FreeSize = sMeminfo.freeram * sMeminfo.mem_unit;
+
+}
+
 PVRSRV_ERROR
 PhysmemNewOSRamBackedPMR(PHYS_HEAP *psPhysHeap,
                                                 CONNECTION_DATA *psConnection,
@@ -4003,7 +3904,7 @@ PhysmemNewOSRamBackedPMR(PHYS_HEAP *psPhysHeap,
 
        if (BIT_ISSET(ui32AllocFlags, FLAG_ONDEMAND))
        {
-               PDUMPCOMMENT("Deferred Allocation PMR (UMA)");
+               PDUMPCOMMENT(PhysHeapDeviceNode(psPhysHeap), "Deferred Allocation PMR (UMA)");
        }
 
        eError = PMRCreatePMR(psPhysHeap,
index 2030fc6..3874594 100644 (file)
@@ -159,8 +159,6 @@ PhysMemTestInit(PVRSRV_DEVICE_NODE **ppsDeviceNode, PVRSRV_DEVICE_CONFIG *psDevC
        eError = PVRSRVPhysMemHeapsInit(psDeviceNode, psDevConfig);
        PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVPhysMemHeapsInit", ErrorSysDevDeInit);
 
-       psDeviceNode->sDevMMUPxSetup.uiMMUPxLog2AllocGran = OSGetPageShift();
-
        *ppsDeviceNode = psDeviceNode;
 
        return PVRSRV_OK;
@@ -227,11 +225,11 @@ PMRValidationTest(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_MEMALLOCFLAGS_T uiFla
                pui32MappingTable[i++] = ui32Index;
        }
 
-       /* Allocate Sparse PMR with SPARSE | READ | WRITE | UNCACHED attributes */
+       /* Allocate Sparse PMR with SPARSE | READ | WRITE | UNCACHED_WC attributes */
        uiFlags |= PVRSRV_MEMALLOCFLAG_SPARSE_NO_DUMMY_BACKING | \
                                PVRSRV_MEMALLOCFLAG_CPU_READABLE | \
                                PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE | \
-                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED;
+                               PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC;
 
        /* Allocate a sparse PMR from given physical heap - CPU/GPU/FW */
        eError = PhysmemNewRamBackedPMR(NULL,
@@ -247,7 +245,8 @@ PMRValidationTest(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_MEMALLOCFLAGS_T uiFla
                                                                        "PMR ValidationTest",
                                                                        OSGetCurrentClientProcessIDKM(),
                                                                        &psPMR,
-                                                                       PDUMP_NONE);
+                                                                       PDUMP_NONE,
+                                                                       NULL);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR, "Failed to allocate a PMR"));
@@ -299,7 +298,7 @@ PMRValidationTest(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_MEMALLOCFLAGS_T uiFla
                                PVR_DPF((PVR_DBG_ERROR, "Failed to Acquire Kernel Mapping of PMR"));
                                goto ErrorUnlockPhysAddresses;
                        }
-                       OSDeviceMemCopy(pvKernAddr, pcWriteBuffer, OSGetPageSize());
+                       OSCachedMemCopyWMB(pvKernAddr, pcWriteBuffer, OSGetPageSize());
 
                        eError = PMRReleaseKernelMappingData(psPMR, hPrivData);
                        PVR_LOG_IF_ERROR(eError, "PMRReleaseKernelMappingData");
@@ -320,7 +319,7 @@ PMRValidationTest(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_MEMALLOCFLAGS_T uiFla
                                goto ErrorUnlockPhysAddresses;
                        }
                        OSCachedMemSet(pcReadBuffer, 0x0, uiPageSize);
-                       OSDeviceMemCopy(pcReadBuffer, pvKernAddr, uiMappedSize);
+                       OSCachedMemCopy(pcReadBuffer, pvKernAddr, uiMappedSize);
 
                        eError = PMRReleaseKernelMappingData(psPMR, hPrivData);
                        PVR_LOG_IF_ERROR(eError, "PMRReleaseKernelMappingData");
@@ -575,7 +574,8 @@ MemTestPatterns(PVRSRV_DEVICE_NODE *psDeviceNode, PVRSRV_MEMALLOCFLAGS_T uiFlags
                                                                        "PMR PhysMemTest",
                                                                        OSGetCurrentClientProcessIDKM(),
                                                                        &psPMR,
-                                                                       PDUMP_NONE);
+                                                                       PDUMP_NONE,
+                                                                       NULL);
        PVR_LOG_RETURN_IF_ERROR(eError, "PhysmemNewRamBackedPMR");
 
        /* Check whether allocated PMR can be locked and obtain physical
index bfd21aa..20de047 100644 (file)
@@ -203,14 +203,10 @@ static const struct vm_operations_struct gsMMapOps =
 static INLINE int _OSMMapPMR(PVRSRV_DEVICE_NODE *psDevNode,
                                                        struct vm_area_struct *ps_vma,
                                                        IMG_DEVMEM_OFFSET_T uiOffset,
-#ifdef CACHE_TEST                                                      
-                                                       size_t   uiLogicalSize,
-#endif
                                                        IMG_CPU_PHYADDR *psCpuPAddr,
                                                        IMG_UINT32 uiLog2PageSize,
                                                        IMG_BOOL bUseVMInsertPage,
-                                                       IMG_BOOL bUseMixedMap,
-                                                       PMR_FLAGS_T ulFlags)
+                                                       IMG_BOOL bUseMixedMap)
 {
        IMG_INT32 iStatus;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
@@ -220,30 +216,7 @@ static INLINE int _OSMMapPMR(PVRSRV_DEVICE_NODE *psDevNode,
 #endif
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
-#ifdef CACHE_TEST
-       if(PVRSRV_CHECK_CPU_UNCACHED(ulFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(ulFlags) )
-       {
-               sPFN = phys_to_pfn_t(psCpuPAddr->uiAddr + SYSPORT_MEM_OFFSET, 0);
-       }
-       else
-       {       
-               if(uiLogicalSize <= 4096 )
-               {
-                       sPFN = phys_to_pfn_t(psCpuPAddr->uiAddr + SYSPORT_MEM_OFFSET, 0);
-               }
-               else
-               {
-                   //printk("mmap size > 120K from %pS\n", __builtin_return_address(0));
-                       sPFN = phys_to_pfn_t(psCpuPAddr->uiAddr, 0);
-               }
-       }
-       //printk("## the flag:%llx,PA:%llx, PFN:%llx, uiLogicalSize:%ld\n", (unsigned long long)ulFlags, (unsigned long long )psCpuPAddr->uiAddr,(unsigned long long )sPFN.val, uiLogicalSize);
-
-#else
-
        sPFN = phys_to_pfn_t(psCpuPAddr->uiAddr + SYSPORT_MEM_OFFSET, 0);
-
-#endif
 #else
        uiPFN = psCpuPAddr->uiAddr >> PAGE_SHIFT;
        PVR_ASSERT(((IMG_UINT64)uiPFN << PAGE_SHIFT) == psCpuPAddr->uiAddr);
@@ -544,14 +517,10 @@ OSMMapPMRGeneric(PMR *psPMR, PMR_MMAP_DATA pOSMMapData)
                        iStatus = _OSMMapPMR(psDevNode,
                                                                 ps_vma,
                                                                 uiOffset,
-#ifdef CACHE_TEST                                                               
-                                                                pmr_size(psPMR),
-#endif                                                          
                                                                 &psCpuPAddr[uiOffsetIdx],
                                                                 uiLog2PageSize,
                                                                 bUseVMInsertPage,
-                                                                bUseMixedMap,
-                                                                PMR_Flags(psPMR));
+                                                                bUseMixedMap);
                        if (iStatus)
                        {
                                /* Failure error code doesn't get propagated */
index b6a18ec..60a1fac 100644 (file)
@@ -46,8 +46,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <linux/fs.h>
 
 #include "connection_server.h"
+#include "pvr_drm.h"
 
-CONNECTION_DATA *LinuxConnectionFromFile(struct file *pFile);
-struct file *LinuxFileFromConnection(CONNECTION_DATA *psConnection);
+#define PVR_SRVKM_PRIV_DATA_IDX 0
+#define PVR_SYNC_PRIV_DATA_IDX  1
+
+#define PVR_NUM_PRIV_DATA_IDXS  2
+
+CONNECTION_DATA *LinuxServicesConnectionFromFile(struct file *pFile);
+CONNECTION_DATA *LinuxSyncConnectionFromFile(struct file *pFile);
 
 #endif /* !defined(INCLUDED_PRIVATE_DATA_H) */
index 796177c..7211ef0 100644 (file)
@@ -81,7 +81,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "common_srvcore_bridge.h"
 
 PVRSRV_ERROR InitDMABUFBridge(void);
-PVRSRV_ERROR DeinitDMABUFBridge(void);
+void DeinitDMABUFBridge(void);
 
 #if defined(MODULE_TEST)
 /************************************************************************/
@@ -113,8 +113,6 @@ static void *BridgeStatsDIStart(OSDI_IMPL_ENTRY *psEntry, IMG_UINT64 *pui64Pos)
 {
        PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psDispatchTable = DIGetPrivData(psEntry);
 
-       BridgeGlobalStatsLock();
-
        if (psDispatchTable == NULL || *pui64Pos > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)
        {
                return NULL;
@@ -132,8 +130,6 @@ static void BridgeStatsDIStop(OSDI_IMPL_ENTRY *psEntry, void *pvData)
 {
        PVR_UNREFERENCED_PARAMETER(psEntry);
        PVR_UNREFERENCED_PARAMETER(pvData);
-
-       BridgeGlobalStatsUnlock();
 }
 
 static void *BridgeStatsDINext(OSDI_IMPL_ENTRY *psEntry, void *pvData,
@@ -257,7 +253,10 @@ PVRSRV_ERROR OSPlatformBridgeInit(void)
                        .pfnStop = BridgeStatsDIStop,
                        .pfnNext = BridgeStatsDINext,
                        .pfnShow = BridgeStatsDIShow,
-                       .pfnWrite = BridgeStatsWrite
+                       .pfnWrite = BridgeStatsWrite,
+
+                       //Expects '0' + Null terminator
+                       .ui32WriteLenMax = ((1U)+1U)
                };
 
                eError = DICreateEntry("bridge_stats", NULL, &sIter,
@@ -279,10 +278,8 @@ error_:
        return eError;
 }
 
-PVRSRV_ERROR OSPlatformBridgeDeInit(void)
+void OSPlatformBridgeDeInit(void)
 {
-       PVRSRV_ERROR eError;
-
 #if defined(DEBUG_BRIDGE_KM)
        if (gpsDIBridgeStatsEntry != NULL)
        {
@@ -290,15 +287,12 @@ PVRSRV_ERROR OSPlatformBridgeDeInit(void)
        }
 #endif
 
-       eError = DeinitDMABUFBridge();
-       PVR_LOG_RETURN_IF_ERROR(eError, "DeinitDMABUFBridge");
+       DeinitDMABUFBridge();
 
        if (g_hDriverThreadEventObject != NULL) {
                OSEventObjectDestroy(g_hDriverThreadEventObject);
                g_hDriverThreadEventObject = NULL;
        }
-
-       return eError;
 }
 
 PVRSRV_ERROR LinuxBridgeBlockClientsAccess(IMG_BOOL bShutdown)
@@ -489,12 +483,12 @@ PVRSRV_BridgeDispatchKM(struct drm_device __maybe_unused *dev, void *arg, struct
 {
        struct drm_pvr_srvkm_cmd *psSrvkmCmd = (struct drm_pvr_srvkm_cmd *) arg;
        PVRSRV_BRIDGE_PACKAGE sBridgePackageKM = { 0 };
-       CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pDRMFile->filp);
+       CONNECTION_DATA *psConnection = LinuxServicesConnectionFromFile(pDRMFile->filp);
        PVRSRV_ERROR error;
 
        if (psConnection == NULL)
        {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Connection is closed", __func__));
+               PVR_DPF((PVR_DBG_ERROR, "Invalid connection data"));
                return -EFAULT;
        }
 
@@ -528,7 +522,7 @@ e0:
 int
 PVRSRV_MMap(struct file *pFile, struct vm_area_struct *ps_vma)
 {
-       CONNECTION_DATA *psConnection = LinuxConnectionFromFile(pFile);
+       CONNECTION_DATA *psConnection = LinuxServicesConnectionFromFile(pFile);
        IMG_HANDLE hSecurePMRHandle = (IMG_HANDLE)((uintptr_t)ps_vma->vm_pgoff);
        PMR *psPMR;
        PVRSRV_ERROR eError;
index c5f0344..b5426d4 100644 (file)
@@ -50,7 +50,6 @@
 #include "pvr_drv.h"
 #include "pvr_fence.h"
 
-
 struct pvr_buffer_sync_context {
        struct mutex ctx_lock;
        struct pvr_fence_context *fence_ctx;
@@ -75,7 +74,6 @@ struct pvr_buffer_sync_append_data {
        struct pvr_buffer_sync_check_data *check_data;
 };
 
-
 static struct dma_resv *
 pmr_reservation_object_get(struct _PMR_ *pmr)
 {
@@ -192,8 +190,8 @@ pvr_buffer_sync_pmrs_fence_count(u32 nr_pmrs, struct _PMR_ **pmrs,
                if (WARN_ON_ONCE(!resv))
                        continue;
 
-               resv_list = dma_resv_get_list(resv);
-               fence = dma_resv_get_excl(resv);
+               resv_list = dma_resv_shared_list(resv);
+               fence = dma_resv_excl_fence(resv);
 
                if (fence &&
                    (!exclusive || !resv_list || !resv_list->shared_count))
@@ -251,8 +249,8 @@ pvr_buffer_sync_check_fences_create(struct pvr_fence_context *fence_ctx,
                                goto err_destroy_fences;
                }
 
-               resv_list = dma_resv_get_list(resv);
-               fence = dma_resv_get_excl(resv);
+               resv_list = dma_resv_shared_list(resv);
+               fence = dma_resv_excl_fence(resv);
 
                if (fence &&
                    (!exclusive || !resv_list || !resv_list->shared_count)) {
@@ -330,7 +328,7 @@ pvr_buffer_sync_context_create(struct device *dev, const char *name)
        }
 
        ctx->fence_ctx = pvr_fence_context_create(priv->dev_node,
-                                                 priv->fence_status_wq,
+                                                 NativeSyncGetFenceStatusWq(),
                                                  name);
        if (!ctx->fence_ctx) {
                err = -ENOMEM;
index f371f6d..3fa8903 100644 (file)
@@ -131,12 +131,11 @@ pvr_counting_fence_timeline_debug_request(void *data, u32 verbosity,
 }
 
 struct pvr_counting_fence_timeline *pvr_counting_fence_timeline_create(
-       void *dev_cookie,
        const char *name)
 {
        PVRSRV_ERROR srv_err;
        struct pvr_counting_fence_timeline *timeline =
-               kmalloc(sizeof(*timeline), GFP_KERNEL);
+               kzalloc(sizeof(*timeline), GFP_KERNEL);
 
        if (!timeline)
                goto err_out;
@@ -146,14 +145,14 @@ struct pvr_counting_fence_timeline *pvr_counting_fence_timeline_create(
        if (!timeline->context)
                goto err_free_timeline;
 
-       srv_err = PVRSRVRegisterDbgRequestNotify(&timeline->dbg_request_handle,
-                               dev_cookie,
+       srv_err = PVRSRVRegisterDriverDbgRequestNotify(
+                               &timeline->dbg_request_handle,
                                pvr_counting_fence_timeline_debug_request,
                                DEBUG_REQUEST_LINUXFENCE,
                                timeline);
        if (srv_err != PVRSRV_OK) {
                pr_err("%s: failed to register debug request callback (%s)\n",
-                      __func__, PVRSRVGetErrorString(srv_err));
+                          __func__, PVRSRVGetErrorString(srv_err));
                goto err_free_timeline_ctx;
        }
 
@@ -183,10 +182,12 @@ void pvr_counting_fence_timeline_force_complete(
 
        spin_lock_irqsave(&timeline->active_fences_lock, flags);
 
-       /* This is just a safety measurement. Normally we should never see any
+#if defined(DEBUG) && !defined(SUPPORT_AUTOVZ)
+       /* This is just a safety measure. Normally we should never see any
         * unsignaled sw fences when we come here. Warn if we still do!
         */
        WARN_ON(!list_empty(&timeline->active_fences));
+#endif
 
        list_for_each_safe(entry, tmp, &timeline->active_fences) {
                struct pvr_counting_fence *fence =
@@ -209,7 +210,7 @@ static void pvr_counting_fence_timeline_destroy(
 
        WARN_ON(!list_empty(&timeline->active_fences));
 
-       PVRSRVUnregisterDbgRequestNotify(timeline->dbg_request_handle);
+       PVRSRVUnregisterDriverDbgRequestNotify(timeline->dbg_request_handle);
 
        pvr_sw_fence_context_destroy(timeline->context);
        kfree(timeline);
index c9282fd..2cb8db1 100644 (file)
@@ -53,7 +53,6 @@ void pvr_counting_fence_timeline_dump_timeline(
        void *dump_debug_file);
 
 struct pvr_counting_fence_timeline *pvr_counting_fence_timeline_create(
-       void *dev_cookie,
        const char *name);
 void pvr_counting_fence_timeline_put(
        struct pvr_counting_fence_timeline *fence_timeline);
index 338551b..fa6a94c 100644 (file)
@@ -112,6 +112,12 @@ typedef struct DFS_FILE
 
 /* ----- native callbacks interface ----------------------------------------- */
 
+static void _WriteData(void *pvNativeHandle, const void *pvData,
+                       IMG_UINT32 uiSize)
+{
+       seq_write(pvNativeHandle, pvData, uiSize);
+}
+
 static void _VPrintf(void *pvNativeHandle, const IMG_CHAR *pszFmt,
                      va_list pArgs)
 {
@@ -141,6 +147,7 @@ static IMG_BOOL _HasOverflowed(void *pvNativeHandle)
 }
 
 static OSDI_IMPL_ENTRY_CB _g_sEntryCallbacks = {
+       .pfnWrite = _WriteData,
        .pfnVPrintf = _VPrintf,
        .pfnPuts = _Puts,
        .pfnHasOverflowed = _HasOverflowed,
@@ -348,9 +355,9 @@ static loff_t _LSeek(struct file *psFile, loff_t iOffset, int iOrigin)
                iRes = seq_lseek(psFile, iOffset, iOrigin);
                if (iRes < 0)
                {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: failed to set file position to offset "
-                               "%lld, pfnSeek() returned %lld", __func__,
-                               iOffset, iRes));
+                       PVR_DPF((PVR_DBG_ERROR, "%s: failed to set file position in psFile<%p> to offset "
+                               "%lld, iOrigin %d, seq_lseek() returned %lld (dentry='%s')", __func__,
+                               psFile, iOffset, iOrigin, iRes, psFile->f_path.dentry->d_name.name));
                        goto return_;
                }
        }
@@ -403,22 +410,29 @@ static ssize_t _Write(struct file *psFile, const char __user *pszBuffer,
        DFS_FILE *psDFSFile = psINode->i_private;
        DI_ITERATOR_CB *psIter = &psDFSFile->sEntry.sIterCb;
        IMG_CHAR *pcLocalBuffer;
-       IMG_UINT64 ui64Count = uiCount + 1, ui64Pos = *puiPos;
+       IMG_UINT64 ui64Count;
        IMG_INT64 i64Res = -EIO;
+       IMG_UINT64 ui64Pos = *puiPos;
 
        PVR_LOG_RETURN_IF_FALSE(psDFSFile != NULL, "psDFSFile is NULL",
                                -EIO);
        PVR_LOG_RETURN_IF_FALSE(psIter->pfnWrite != NULL, "pfnWrite is NULL",
                                -EIO);
 
+
+       /* Make sure we allocate the smallest amount of needed memory*/
+       ui64Count = psIter->ui32WriteLenMax;
+       PVR_LOG_GOTO_IF_FALSE(uiCount <= ui64Count, "uiCount too long", return_);
+       ui64Count = MIN(uiCount + 1, ui64Count);
+
        _DRIVER_THREAD_ENTER();
 
-       /* allocate buffer with one additional byte fore NUL character */
+       /* allocate buffer with one additional byte for NUL character */
        pcLocalBuffer = OSAllocMem(ui64Count);
        PVR_LOG_GOTO_IF_FALSE(pcLocalBuffer != NULL, "OSAllocMem() failed",
                              return_);
 
-       i64Res = pvr_copy_from_user(pcLocalBuffer, pszBuffer, uiCount);
+       i64Res = pvr_copy_from_user(pcLocalBuffer, pszBuffer, ui64Count);
        PVR_LOG_GOTO_IF_FALSE(i64Res == 0, "pvr_copy_from_user() failed",
                              free_local_buffer_);
 
index 8f7afee..65a8e51 100644 (file)
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/mutex.h>
 
 #include "module_common.h"
 #include "pvr_drm.h"
 #include "pvr_drv.h"
 #include "pvrversion.h"
 #include "services_kernel_client.h"
+#include "pvr_sync_ioctl_drm.h"
 
 #include "kernel_compatibility.h"
 
 #define PVR_DRM_DRIVER_DESC "Imagination Technologies PVR DRM"
 #define        PVR_DRM_DRIVER_DATE "20170530"
 
+/*
+ * Protects global PVRSRV_DATA on a multi device system. i.e. this is used to
+ * protect the PVRSRVCommonDeviceXXXX() APIs in the Server common layer which
+ * are not re-entrant for device creation and initialisation.
+ */
+static DEFINE_MUTEX(g_device_mutex);
 
 static int pvr_pm_suspend(struct device *dev)
 {
@@ -137,14 +145,7 @@ int pvr_drm_load(struct drm_device *ddev, unsigned long flags)
                ddev->dev->dma_parms = &priv->dma_parms;
        dma_set_max_seg_size(ddev->dev, DMA_BIT_MASK(32));
 
-#if defined(SUPPORT_BUFFER_SYNC) || defined(SUPPORT_NATIVE_FENCE_SYNC)
-       priv->fence_status_wq = create_freezable_workqueue("pvr_fce_status");
-       if (!priv->fence_status_wq) {
-               DRM_ERROR("failed to create fence status workqueue\n");
-               err = -ENOMEM;
-               goto err_unset_dma_parms;
-       }
-#endif
+       mutex_lock(&g_device_mutex);
 
        srv_err = PVRSRVCommonDeviceCreate(ddev->dev, deviceId, &priv->dev_node);
        if (srv_err != PVRSRV_OK) {
@@ -154,7 +155,7 @@ int pvr_drm_load(struct drm_device *ddev, unsigned long flags)
                        err = -EPROBE_DEFER;
                else
                        err = -ENODEV;
-               goto err_workqueue_destroy;
+               goto err_unset_dma_parms;
        }
 
        err = PVRSRVDeviceInit(priv->dev_node);
@@ -166,27 +167,29 @@ int pvr_drm_load(struct drm_device *ddev, unsigned long flags)
 
        drm_mode_config_init(ddev);
 
-#if defined(SUPPORT_FWLOAD_ON_PROBE)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_PROBE)
        srv_err = PVRSRVCommonDeviceInitialise(priv->dev_node);
        if (srv_err != PVRSRV_OK) {
                err = -ENODEV;
                DRM_ERROR("device %p initialisation failed (err=%d)\n",
                          ddev->dev, err);
-               drm_mode_config_cleanup(ddev);
-               PVRSRVDeviceDeinit(priv->dev_node);
-               goto err_device_destroy;
+               goto err_device_deinit;
        }
 #endif
 
+       mutex_unlock(&g_device_mutex);
+
        return 0;
 
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_PROBE)
+err_device_deinit:
+       drm_mode_config_cleanup(ddev);
+       PVRSRVDeviceDeinit(priv->dev_node);
+#endif
 err_device_destroy:
        PVRSRVCommonDeviceDestroy(priv->dev_node);
-err_workqueue_destroy:
-#if defined(SUPPORT_BUFFER_SYNC) || defined(SUPPORT_NATIVE_FENCE_SYNC)
-       destroy_workqueue(priv->fence_status_wq);
 err_unset_dma_parms:
-#endif
+       mutex_unlock(&g_device_mutex);
        if (ddev->dev->dma_parms == &priv->dma_parms)
                ddev->dev->dma_parms = NULL;
        kfree(priv);
@@ -211,11 +214,9 @@ void pvr_drm_unload(struct drm_device *ddev)
 
        PVRSRVDeviceDeinit(priv->dev_node);
 
+       mutex_lock(&g_device_mutex);
        PVRSRVCommonDeviceDestroy(priv->dev_node);
-
-#if defined(SUPPORT_BUFFER_SYNC) || defined(SUPPORT_NATIVE_FENCE_SYNC)
-       destroy_workqueue(priv->fence_status_wq);
-#endif
+       mutex_unlock(&g_device_mutex);
 
        if (ddev->dev->dma_parms == &priv->dma_parms)
                ddev->dev->dma_parms = NULL;
@@ -230,19 +231,25 @@ void pvr_drm_unload(struct drm_device *ddev)
 
 static int pvr_drm_open(struct drm_device *ddev, struct drm_file *dfile)
 {
+#if (PVRSRV_DEVICE_INIT_MODE != PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
        struct pvr_drm_private *priv = ddev->dev_private;
        int err;
+#endif
 
        if (!try_module_get(THIS_MODULE)) {
                DRM_ERROR("failed to get module reference\n");
                return -ENOENT;
        }
 
-       err = PVRSRVDeviceOpen(priv->dev_node, dfile);
+#if (PVRSRV_DEVICE_INIT_MODE != PVRSRV_LINUX_DEV_INIT_ON_CONNECT)
+       err = PVRSRVDeviceServicesOpen(priv->dev_node, dfile);
        if (err)
                module_put(THIS_MODULE);
 
        return err;
+#else
+       return 0;
+#endif
 }
 
 static void pvr_drm_release(struct drm_device *ddev, struct drm_file *dfile)
@@ -258,7 +265,20 @@ static void pvr_drm_release(struct drm_device *ddev, struct drm_file *dfile)
  * The DRM global lock is taken for ioctls unless the DRM_UNLOCKED flag is set.
  */
 static struct drm_ioctl_desc pvr_drm_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(PVR_SRVKM_CMD, PVRSRV_BridgeDispatchKM, DRM_RENDER_ALLOW | DRM_UNLOCKED)
+       DRM_IOCTL_DEF_DRV(PVR_SRVKM_CMD, PVRSRV_BridgeDispatchKM,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(PVR_SRVKM_INIT, drm_pvr_srvkm_init,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE)
+       DRM_IOCTL_DEF_DRV(PVR_SYNC_RENAME_CMD, pvr_sync_rename_ioctl,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(PVR_SYNC_FORCE_SW_ONLY_CMD, pvr_sync_force_sw_only_ioctl,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(PVR_SW_SYNC_CREATE_FENCE_CMD, pvr_sw_sync_create_fence_ioctl,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+       DRM_IOCTL_DEF_DRV(PVR_SW_SYNC_INC_CMD, pvr_sw_sync_inc_ioctl,
+                         DRM_RENDER_ALLOW | DRM_UNLOCKED),
+#endif
 };
 
 #if defined(CONFIG_COMPAT)
@@ -274,7 +294,7 @@ static long pvr_compat_ioctl(struct file *file, unsigned int cmd,
 }
 #endif /* defined(CONFIG_COMPAT) */
 
-static const struct file_operations pvr_drm_fops = {
+const struct file_operations pvr_drm_fops = {
        .owner                  = THIS_MODULE,
        .open                   = drm_open,
        .release                = drm_release,
index 68b964a..15887da 100644 (file)
@@ -74,16 +74,21 @@ struct pvr_drm_private {
         */
        struct device_dma_parameters dma_parms;
 
-#if defined(SUPPORT_BUFFER_SYNC) || defined(SUPPORT_NATIVE_FENCE_SYNC)
-       struct workqueue_struct *fence_status_wq;
-#endif
-
        /* PVR Sync debug notify handle */
        void *sync_debug_notify_handle;
+
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+       /* Only used in fence sync as sync_debug_notify_handle is used
+        * to print a header only. Content is registered separately.
+        * Used to print foreign sync debug
+        */
+       void *sync_foreign_debug_notify_handle;
+#endif
 };
 
 extern const struct dev_pm_ops pvr_pm_ops;
 extern const struct drm_driver pvr_drm_generic_driver;
+extern const struct file_operations pvr_drm_fops;
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
 int pvr_drm_load(struct drm_device *ddev, unsigned long flags);
index d40a7cf..e65a4ab 100644 (file)
@@ -49,6 +49,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 #include <linux/version.h>
 #include <linux/device.h>
+#include <drm/drm.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#else
+#include <drm/drmP.h>
+#endif
 
 #include "power.h"
 #include "pvrsrv.h"
@@ -64,13 +71,34 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "kernel_compatibility.h"
 
-static PVRSRV_DEVICE_NODE *gpsDeviceNode;
+static int _device_get_devid(struct device *dev)
+{
+       struct drm_device *ddev = dev_get_drvdata(dev);
+       int deviceId;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
+       /*
+        * Older kernels do not have render drm_minor member in drm_device,
+        * so we fallback to primary node for device identification
+        */
+       deviceId = ddev->primary->index;
+#else
+       if (ddev->render)
+               deviceId = ddev->render->index;
+       else /* when render node is NULL, fallback to primary node */
+               deviceId = ddev->primary->index;
+#endif
+
+       return deviceId;
+}
 
 static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_freq, IMG_UINT32 flags)
 {
-       RGX_DATA                *psRGXData = (RGX_DATA*) gpsDeviceNode->psDevConfig->hDevData;
-       IMG_DVFS_DEVICE         *psDVFSDevice = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
-       IMG_DVFS_DEVICE_CFG     *psDVFSDeviceCfg = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+       int deviceId = _device_get_devid(dev);
+       PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
+       RGX_DATA                *psRGXData = NULL;
+       IMG_DVFS_DEVICE         *psDVFSDevice = NULL;
+       IMG_DVFS_DEVICE_CFG     *psDVFSDeviceCfg = NULL;
        RGX_TIMING_INFORMATION  *psRGXTimingInfo = NULL;
        IMG_UINT32              ui32Freq, ui32CurFreq, ui32Volt;
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
@@ -79,6 +107,16 @@ static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_fre
        struct dev_pm_opp *opp;
 #endif
 
+       /* Check the device is registered */
+       if (!psDeviceNode)
+       {
+               return -ENODEV;
+       }
+
+       psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+
        /* Check the RGX device is initialised */
        if (!psRGXData)
        {
@@ -121,7 +159,7 @@ static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_fre
                return 0;
        }
 
-       if (PVRSRV_OK != PVRSRVDevicePreClockSpeedChange(gpsDeviceNode,
+       if (PVRSRV_OK != PVRSRVDevicePreClockSpeedChange(psDeviceNode,
                                                                                                         psDVFSDeviceCfg->bIdleReq,
                                                                                                         NULL))
        {
@@ -145,7 +183,7 @@ static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_fre
 
        psRGXTimingInfo->ui32CoreClockSpeed = ui32Freq;
 
-       PVRSRVDevicePostClockSpeedChange(gpsDeviceNode, psDVFSDeviceCfg->bIdleReq,
+       PVRSRVDevicePostClockSpeedChange(psDeviceNode, psDVFSDeviceCfg->bIdleReq,
                                                                         NULL);
 
        return 0;
@@ -153,13 +191,25 @@ static IMG_INT32 devfreq_target(struct device *dev, unsigned long *requested_fre
 
 static int devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat)
 {
-       PVRSRV_RGXDEV_INFO      *psDevInfo = gpsDeviceNode->pvDevice;
-       IMG_DVFS_DEVICE         *psDVFSDevice = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
-       RGX_DATA                *psRGXData = (RGX_DATA*) gpsDeviceNode->psDevConfig->hDevData;
+       int                      deviceId = _device_get_devid(dev);
+       PVRSRV_DEVICE_NODE      *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
+       PVRSRV_RGXDEV_INFO      *psDevInfo = NULL;
+       IMG_DVFS_DEVICE         *psDVFSDevice = NULL;
+       RGX_DATA                *psRGXData = NULL;
        RGX_TIMING_INFORMATION  *psRGXTimingInfo = NULL;
        RGXFWIF_GPU_UTIL_STATS   sGpuUtilStats;
        PVRSRV_ERROR             eError;
 
+       /* Check the device is registered */
+       if (!psDeviceNode)
+       {
+               return -ENODEV;
+       }
+
+       psDevInfo = psDeviceNode->pvDevice;
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
+
        /* Check the RGX device is initialised */
        if (!psDevInfo || !psRGXData)
        {
@@ -177,7 +227,7 @@ static int devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status
                return 0;
        }
 
-       eError = psDevInfo->pfnGetGpuUtilStats(psDevInfo->psDeviceNode,
+       eError = psDevInfo->pfnGetGpuUtilStats(psDeviceNode,
                                                psDVFSDevice->hGpuUtilUserDVFS,
                                                &sGpuUtilStats);
 
@@ -195,7 +245,17 @@ static int devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
 static IMG_INT32 devfreq_cur_freq(struct device *dev, unsigned long *freq)
 {
-       RGX_DATA *psRGXData = (RGX_DATA*) gpsDeviceNode->psDevConfig->hDevData;
+       int deviceId = _device_get_devid(dev);
+       PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetDeviceInstanceByOSId(deviceId);
+       RGX_DATA *psRGXData = NULL;
+
+       /* Check the device is registered */
+       if (!psDeviceNode)
+       {
+               return -ENODEV;
+       }
+
+       psRGXData = (RGX_DATA*) psDeviceNode->psDevConfig->hDevData;
 
        /* Check the RGX device is initialised */
        if (!psRGXData)
@@ -218,11 +278,19 @@ static struct devfreq_dev_profile img_devfreq_dev_profile =
 #endif
 };
 
-static int FillOPPTable(struct device *dev)
+static int FillOPPTable(struct device *dev, PVRSRV_DEVICE_NODE *psDeviceNode)
 {
        const IMG_OPP *iopp;
        int i, err = 0;
-       IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+       IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
+
+       /* Check the device exists */
+       if (!dev || !psDeviceNode)
+       {
+               return -ENODEV;
+       }
+
+       psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
 
        for (i = 0, iopp = psDVFSDeviceCfg->pasOPPTable;
             i < psDVFSDeviceCfg->ui32OPPTableSize;
@@ -238,13 +306,21 @@ static int FillOPPTable(struct device *dev)
        return 0;
 }
 
-static void ClearOPPTable(struct device *dev)
+static void ClearOPPTable(struct device *dev, PVRSRV_DEVICE_NODE *psDeviceNode)
 {
 #if (defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))) || \
        (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
        const IMG_OPP *iopp;
        int i;
-       IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+       IMG_DVFS_DEVICE_CFG *psDVFSDeviceCfg = NULL;
+
+       /* Check the device exists */
+       if (!dev || !psDeviceNode)
+       {
+               return;
+       }
+
+       psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
 
        for (i = 0, iopp = psDVFSDeviceCfg->pasOPPTable;
             i < psDVFSDeviceCfg->ui32OPPTableSize;
@@ -374,6 +450,11 @@ static int RegisterCoolingDevice(struct device *dev,
        int err = 0;
        PVRSRV_VZ_RET_IF_MODE(GUEST, err);
 
+       if (!psDVFSDevice)
+       {
+               return -EINVAL;
+       }
+
        if (!powerOps)
        {
                dev_info(dev, "Cooling: power ops not registered, not enabling cooling");
@@ -403,10 +484,7 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
 {
        IMG_DVFS_DEVICE        *psDVFSDevice = NULL;
        IMG_DVFS_DEVICE_CFG    *psDVFSDeviceCfg = NULL;
-       IMG_DVFS_GOVERNOR_CFG  *psDVFSGovernorCfg = NULL;
-       RGX_TIMING_INFORMATION *psRGXTimingInfo = NULL;
-       struct device          *psDev = psDeviceNode->psDevConfig->pvOSDevice;
-       unsigned long           min_freq = 0, max_freq = 0, min_volt = 0;
+       struct device          *psDev;
        PVRSRV_ERROR            eError;
        int                     err;
 
@@ -416,19 +494,23 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
        return PVRSRV_ERROR_NOT_SUPPORTED;
 #endif
 
-       if (gpsDeviceNode)
+       if (!psDeviceNode)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending)
        {
                PVR_DPF((PVR_DBG_ERROR,
-                                "DVFS already initialised for device node %p",
-                                gpsDeviceNode));
+                                "DVFS initialise pending for device node %p",
+                                psDeviceNode));
                return PVRSRV_ERROR_INIT_FAILURE;
        }
 
-       gpsDeviceNode = psDeviceNode;
+       psDev = psDeviceNode->psDevConfig->pvOSDevice;
        psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
        psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
-       psDVFSGovernorCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSGovernorCfg;
-       psRGXTimingInfo = ((RGX_DATA *)psDeviceNode->psDevConfig->hDevData)->psRGXTimingInfo;
+       psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending = IMG_TRUE;
 
 #if defined(SUPPORT_SOC_TIMER)
        if (! psDeviceNode->psDevConfig->pfnSoCTimerRead)
@@ -464,7 +546,7 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
 
        if (psDVFSDeviceCfg->pasOPPTable)
        {
-               err = FillOPPTable(psDev);
+               err = FillOPPTable(psDev, psDeviceNode);
                if (err)
                {
                        PVR_DPF((PVR_DBG_ERROR, "Failed to fill OPP table with data, %d", err));
@@ -473,6 +555,48 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
                }
        }
 
+       PVR_TRACE(("PVR DVFS init pending: dev = %p, PVR device = %p",
+                          psDev, psDeviceNode));
+
+       return PVRSRV_OK;
+
+err_exit:
+       DeinitDVFS(psDeviceNode);
+       return eError;
+}
+
+PVRSRV_ERROR RegisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
+{
+       IMG_DVFS_DEVICE        *psDVFSDevice = NULL;
+       IMG_DVFS_DEVICE_CFG    *psDVFSDeviceCfg = NULL;
+       IMG_DVFS_GOVERNOR_CFG  *psDVFSGovernorCfg = NULL;
+       RGX_TIMING_INFORMATION *psRGXTimingInfo = NULL;
+       struct device          *psDev;
+       unsigned long           min_freq = 0, max_freq = 0, min_volt = 0;
+       PVRSRV_ERROR            eError;
+       int                     err;
+
+       if (!psDeviceNode)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (!psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                                "DVFS initialise not yet pending for device node %p",
+                                psDeviceNode));
+               return PVRSRV_ERROR_INIT_FAILURE;
+       }
+
+       psDev = psDeviceNode->psDevConfig->pvOSDevice;
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       psDVFSDeviceCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSDeviceCfg;
+       psDVFSGovernorCfg = &psDeviceNode->psDevConfig->sDVFS.sDVFSGovernorCfg;
+       psRGXTimingInfo = ((RGX_DATA *)psDeviceNode->psDevConfig->hDevData)->psRGXTimingInfo;
+       psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bInitPending = IMG_FALSE;
+       psDeviceNode->psDevConfig->sDVFS.sDVFSDevice.bReady = IMG_TRUE;
+
        err = GetOPPValues(psDev, &min_freq, &min_volt, &max_freq);
        if (err)
        {
@@ -514,7 +638,7 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
                goto err_exit;
        }
 
-       eError = SuspendDVFS();
+       eError = SuspendDVFS(psDeviceNode);
        if (eError != PVRSRV_OK)
        {
                PVR_DPF((PVR_DBG_ERROR, "PVRSRVInit: Failed to suspend DVFS"));
@@ -557,19 +681,26 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
        return PVRSRV_OK;
 
 err_exit:
-       DeinitDVFS(psDeviceNode);
+       UnregisterDVFSDevice(psDeviceNode);
        return eError;
 }
 
-void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
+void UnregisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode)
 {
-       IMG_DVFS_DEVICE *psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
-       struct device *psDev = psDeviceNode->psDevConfig->pvOSDevice;
+       IMG_DVFS_DEVICE *psDVFSDevice = NULL;
+       struct device *psDev = NULL;
        IMG_INT32 i32Error;
 
+       /* Check the device exists */
+       if (!psDeviceNode)
+       {
+               return;
+       }
+
        PVRSRV_VZ_RETN_IF_MODE(GUEST);
 
-       PVR_ASSERT(psDeviceNode == gpsDeviceNode);
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       psDev = psDeviceNode->psDevConfig->pvOSDevice;
 
        if (! psDVFSDevice)
        {
@@ -606,8 +737,28 @@ void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
        kfree(img_devfreq_dev_profile.freq_table);
 #endif
 
+       psDVFSDevice->bInitPending = IMG_FALSE;
+       psDVFSDevice->bReady = IMG_FALSE;
+}
+
+void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
+{
+       IMG_DVFS_DEVICE *psDVFSDevice = NULL;
+       struct device *psDev = NULL;
+
+       /* Check the device exists */
+       if (!psDeviceNode)
+       {
+               return;
+       }
+
+       PVRSRV_VZ_RETN_IF_MODE(GUEST);
+
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       psDev = psDeviceNode->psDevConfig->pvOSDevice;
+
        /* Remove OPP entries for this device */
-       ClearOPPTable(psDev);
+       ClearOPPTable(psDev, psDeviceNode);
 
 #if defined(CONFIG_OF)
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) || \
@@ -618,22 +769,37 @@ void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
 
        SORgxGpuUtilStatsUnregister(psDVFSDevice->hGpuUtilUserDVFS);
        psDVFSDevice->hGpuUtilUserDVFS = NULL;
-
-       gpsDeviceNode = NULL;
+       psDVFSDevice->bInitPending = IMG_FALSE;
+       psDVFSDevice->bReady = IMG_FALSE;
 }
 
-PVRSRV_ERROR SuspendDVFS(void)
+PVRSRV_ERROR SuspendDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
 {
-       IMG_DVFS_DEVICE *psDVFSDevice = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       IMG_DVFS_DEVICE *psDVFSDevice = NULL;
+
+       /* Check the device is registered */
+       if (!psDeviceNode)
+       {
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
 
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
        psDVFSDevice->bEnabled = IMG_FALSE;
 
        return PVRSRV_OK;
 }
 
-PVRSRV_ERROR ResumeDVFS(void)
+PVRSRV_ERROR ResumeDVFS(PPVRSRV_DEVICE_NODE psDeviceNode)
 {
-       IMG_DVFS_DEVICE *psDVFSDevice = &gpsDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
+       IMG_DVFS_DEVICE *psDVFSDevice = NULL;
+
+       /* Check the device is registered */
+       if (!psDeviceNode)
+       {
+               return PVRSRV_ERROR_INVALID_DEVICE;
+       }
+
+       psDVFSDevice = &psDeviceNode->psDevConfig->sDVFS.sDVFSDevice;
 
        /* Not supported in GuestOS drivers */
        psDVFSDevice->bEnabled = !PVRSRV_VZ_MODE_IS(GUEST);
index 84bcb26..a246b24 100644 (file)
@@ -51,8 +51,12 @@ PVRSRV_ERROR InitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
 
 void DeinitDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
 
-PVRSRV_ERROR SuspendDVFS(void);
+PVRSRV_ERROR RegisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
 
-PVRSRV_ERROR ResumeDVFS(void);
+void UnregisterDVFSDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
+
+PVRSRV_ERROR SuspendDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
+
+PVRSRV_ERROR ResumeDVFS(PPVRSRV_DEVICE_NODE psDeviceNode);
 
 #endif /* PVR_DVFS_DEVICE_H */
index cd8d8ab..e94522a 100644 (file)
@@ -279,17 +279,13 @@ pvr_fence_context_signal_fences_nohw(void *data)
 }
 
 static void
-pvr_fence_context_destroy_work(struct work_struct *data)
+pvr_fence_context_destroy_internal(struct pvr_fence_context *fctx)
 {
-       struct pvr_fence_context *fctx =
-               container_of(data, struct pvr_fence_context, destroy_work);
-
        pvr_fence_context_free_deferred(fctx);
 
        if (WARN_ON(!list_empty_careful(&fctx->fence_list)))
                pvr_fence_context_fences_dump(fctx, NULL, NULL);
 
-       PVRSRVUnregisterDbgRequestNotify(fctx->dbg_request_handle);
        PVRSRVUnregisterCmdCompleteNotify(fctx->cmd_complete_handle);
 
        // wait for all fences to be freed before kmem_cache_destroy() is called
@@ -306,6 +302,31 @@ pvr_fence_context_destroy_work(struct work_struct *data)
 }
 
 static void
+pvr_fence_context_unregister_dbg(void *dbg_request_handle)
+{
+       PVRSRVUnregisterDeviceDbgRequestNotify(dbg_request_handle);
+}
+
+static void
+pvr_fence_foreign_context_destroy_work(struct work_struct *data)
+{
+       struct pvr_fence_context *fctx =
+               container_of(data, struct pvr_fence_context, destroy_work);
+
+       pvr_fence_context_destroy_internal(fctx);
+}
+
+static void
+pvr_fence_context_destroy_work(struct work_struct *data)
+{
+       struct pvr_fence_context *fctx =
+               container_of(data, struct pvr_fence_context, destroy_work);
+
+       pvr_fence_context_unregister_dbg(fctx->dbg_request_handle);
+       pvr_fence_context_destroy_internal(fctx);
+}
+
+static void
 pvr_fence_context_debug_request(void *data, u32 verbosity,
                                DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                void *pvDumpDebugFile)
@@ -317,22 +338,10 @@ pvr_fence_context_debug_request(void *data, u32 verbosity,
                                              pvDumpDebugFile);
 }
 
-/**
- * pvr_fence_context_create - creates a PVR fence context
- * @dev_cookie: services device cookie
- * @name: context name (used for debugging)
- *
- * Creates a PVR fence context that can be used to create PVR fences or to
- * create PVR fences from an existing fence.
- *
- * pvr_fence_context_destroy should be called to clean up the fence context.
- *
- * Returns NULL if a context cannot be created.
- */
-struct pvr_fence_context *
-pvr_fence_context_create(void *dev_cookie,
-                        struct workqueue_struct *fence_status_wq,
-                        const char *name)
+static struct pvr_fence_context *
+pvr_fence_context_create_internal(struct workqueue_struct *fence_status_wq,
+                       const char *name,
+                       work_func_t destroy_callback)
 {
        struct pvr_fence_context *fctx;
        PVRSRV_ERROR srv_err;
@@ -344,7 +353,7 @@ pvr_fence_context_create(void *dev_cookie,
        spin_lock_init(&fctx->lock);
        atomic_set(&fctx->fence_seqno, 0);
        INIT_WORK(&fctx->check_status_work, pvr_fence_context_check_status);
-       INIT_WORK(&fctx->destroy_work, pvr_fence_context_destroy_work);
+       INIT_WORK(&fctx->destroy_work, destroy_callback);
        spin_lock_init(&fctx->list_lock);
        INIT_LIST_HEAD(&fctx->signal_list);
        INIT_LIST_HEAD(&fctx->fence_list);
@@ -378,33 +387,113 @@ pvr_fence_context_create(void *dev_cookie,
        pvr_fence_cache_refcount++;
        mutex_unlock(&pvr_fence_cache_mutex);
 
-       srv_err = PVRSRVRegisterDbgRequestNotify(&fctx->dbg_request_handle,
-                               dev_cookie,
+       kref_init(&fctx->kref);
+
+       PVR_FENCE_CTX_TRACE(fctx, "created fence context (%s)\n", name);
+       trace_pvr_fence_context_create(fctx);
+
+       return fctx;
+
+err_unregister_cmd_complete_notify:
+       PVRSRVUnregisterCmdCompleteNotify(fctx->cmd_complete_handle);
+err_free_fctx:
+       kfree(fctx);
+       return NULL;
+}
+
+/**
+ * pvr_fence_context_register_dbg - registers the debug handler for a
+ * fence context
+ *
+ * @dbg_request_handle: handle used to keep a reference for deregister
+ * @dev: device to attach the debug notifier.
+ * @pvr_fence_context: context used as data to the callback for debug
+ *
+ * Registers a debug notifier for a given context for a given device.
+ *
+ * Returns PVRSRV_OK if successful.
+ */
+PVRSRV_ERROR pvr_fence_context_register_dbg(void *dbg_request_handle,
+                               void *dev,
+                               struct pvr_fence_context *fctx)
+{
+       PVRSRV_ERROR srv_err;
+
+       srv_err = PVRSRVRegisterDeviceDbgRequestNotify(dbg_request_handle,
+                               dev,
                                pvr_fence_context_debug_request,
                                DEBUG_REQUEST_LINUXFENCE,
                                fctx);
        if (srv_err != PVRSRV_OK) {
                pr_err("%s: failed to register debug request callback (%s)\n",
                       __func__, PVRSRVGetErrorString(srv_err));
-               goto err_free_pvr_fence_cache;
        }
 
-       kref_init(&fctx->kref);
+       return srv_err;
+}
 
-       PVR_FENCE_CTX_TRACE(fctx, "created fence context (%s)\n", name);
-       trace_pvr_fence_context_create(fctx);
+/**
+ * pvr_fence_foreign_context_create - creates a PVR fence context
+ * @fence_status_wq: linux workqueue used to signal foreign fences
+ * @name: context name (used for debugging)
+ *
+ * Creates a PVR foreign fence context that can be used to create PVR fences
+ * or to create PVR fences from an existing fence.
+ *
+ * pvr_fence_context_destroy should be called to clean up the fence context.
+ *
+ * Returns NULL if a context cannot be created.
+ */
+struct pvr_fence_context *
+pvr_fence_foreign_context_create(struct workqueue_struct *fence_status_wq,
+               const char *name)
+{
+       return pvr_fence_context_create_internal(fence_status_wq, name,
+                                                       pvr_fence_foreign_context_destroy_work);
+}
+
+/**
+ * pvr_fence_context_create - creates a PVR fence context
+ * @dev_cookie: services device cookie
+ * @fence_status_wq: Status workqueue to queue fence update CBs.
+ * @name: context name (used for debugging)
+ *
+ * Creates a PVR fence context that can be used to create PVR fences or to
+ * create PVR fences from an existing fence.
+ *
+ * pvr_fence_context_destroy should be called to clean up the fence context.
+ *
+ * Returns NULL if a context cannot be created.
+ */
+struct pvr_fence_context *
+pvr_fence_context_create(void *dev_cookie,
+                        struct workqueue_struct *fence_status_wq,
+                        const char *name)
+{
+       struct pvr_fence_context *fctx;
+       PVRSRV_ERROR eError;
+
+       fctx = pvr_fence_context_create_internal(fence_status_wq, name,
+                                       pvr_fence_context_destroy_work);
+       if (fctx == NULL) {
+               pr_err("%s: failed to create fence context", __func__);
+               goto err_out;
+       }
+
+       eError = pvr_fence_context_register_dbg(&fctx->dbg_request_handle,
+                                       dev_cookie,
+                                       fctx);
+       if (eError != PVRSRV_OK) {
+               pr_err("%s: failed to register fence context debug (%s)\n",
+                      __func__, PVRSRVGetErrorString(eError));
+               goto err_destroy_ctx;
+       }
 
        return fctx;
 
-err_free_pvr_fence_cache:
-       mutex_lock(&pvr_fence_cache_mutex);
-       if (--pvr_fence_cache_refcount == 0)
-               kmem_cache_destroy(pvr_fence_cache);
-       mutex_unlock(&pvr_fence_cache_mutex);
-err_unregister_cmd_complete_notify:
-       PVRSRVUnregisterCmdCompleteNotify(fctx->cmd_complete_handle);
-err_free_fctx:
-       kfree(fctx);
+err_destroy_ctx:
+       pvr_fence_context_destroy(fctx);
+err_out:
        return NULL;
 }
 
@@ -571,7 +660,7 @@ const struct dma_fence_ops pvr_fence_ops = {
  */
 struct pvr_fence *
 pvr_fence_create(struct pvr_fence_context *fctx,
-               struct _SYNC_CHECKPOINT_CONTEXT *sync_checkpoint_ctx,
+               struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
                int timeline_fd, const char *name)
 {
        struct pvr_fence *pvr_fence;
@@ -783,7 +872,7 @@ pvr_fence_foreign_signal_sync(struct dma_fence *fence, struct dma_fence_cb *cb)
 
 struct pvr_fence *
 pvr_fence_create_from_fence(struct pvr_fence_context *fctx,
-                           struct _SYNC_CHECKPOINT_CONTEXT *sync_checkpoint_ctx,
+                           struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
                            struct dma_fence *fence,
                            PVRSRV_FENCE fence_fd,
                            const char *name)
@@ -961,9 +1050,9 @@ pvr_fence_sw_error(struct pvr_fence *pvr_fence)
 
 int
 pvr_fence_get_checkpoints(struct pvr_fence **pvr_fences, u32 nr_fences,
-                         struct _SYNC_CHECKPOINT **fence_checkpoints)
+                         struct SYNC_CHECKPOINT_TAG **fence_checkpoints)
 {
-       struct _SYNC_CHECKPOINT **next_fence_checkpoint = fence_checkpoints;
+       struct SYNC_CHECKPOINT_TAG **next_fence_checkpoint = fence_checkpoints;
        struct pvr_fence **next_pvr_fence = pvr_fences;
        int fence_checkpoint_idx;
 
@@ -983,7 +1072,7 @@ pvr_fence_get_checkpoints(struct pvr_fence **pvr_fences, u32 nr_fences,
        return 0;
 }
 
-struct _SYNC_CHECKPOINT *
+struct SYNC_CHECKPOINT_TAG *
 pvr_fence_get_checkpoint(struct pvr_fence *update_fence)
 {
        return update_fence->sync_checkpoint;
@@ -1022,7 +1111,7 @@ u32 pvr_fence_dump_info_on_stalled_ufos(struct pvr_fence_context *fctx,
                DUMPDEBUG_PRINTF_FUNC *pfnDummy = NULL;
 
                for (ufo_num = 0; ufo_num < nr_ufos; ufo_num++) {
-                       struct _SYNC_CHECKPOINT *checkpoint =
+                       struct SYNC_CHECKPOINT_TAG *checkpoint =
                                pvr_fence->sync_checkpoint;
                        const u32 fence_ufo_addr =
                                SyncCheckpointGetFirmwareAddr(checkpoint);
index 500086a..21870ba 100644 (file)
@@ -57,8 +57,8 @@ static inline void pvr_fence_cleanup(void)
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
 
-struct _SYNC_CHECKPOINT_CONTEXT;
-struct _SYNC_CHECKPOINT;
+struct SYNC_CHECKPOINT_CONTEXT_TAG;
+struct SYNC_CHECKPOINT_TAG;
 
 /**
  * pvr_fence_context - PVR fence context used to create and manage PVR fences
@@ -117,7 +117,7 @@ struct pvr_fence {
        char name[32];
 
        struct dma_fence *fence;
-       struct _SYNC_CHECKPOINT *sync_checkpoint;
+       struct SYNC_CHECKPOINT_TAG *sync_checkpoint;
 
        struct list_head fence_head;
        struct list_head signal_head;
@@ -148,6 +148,12 @@ static inline struct pvr_fence *to_pvr_fence(struct dma_fence *fence)
        return NULL;
 }
 
+PVRSRV_ERROR pvr_fence_context_register_dbg(void *dbg_request_handle,
+                               void *dev,
+                               struct pvr_fence_context *fctx);
+struct pvr_fence_context *
+pvr_fence_foreign_context_create(struct workqueue_struct *fence_status_wq,
+               const char *name);
 struct pvr_fence_context *
 pvr_fence_context_create(void *dev_cookie,
                         struct workqueue_struct *fence_status_wq,
@@ -157,11 +163,11 @@ void pvr_context_value_str(struct pvr_fence_context *fctx, char *str, int size);
 
 struct pvr_fence *
 pvr_fence_create(struct pvr_fence_context *fctx,
-                struct _SYNC_CHECKPOINT_CONTEXT *sync_checkpoint_ctx,
+                struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
                 int timeline_fd, const char *name);
 struct pvr_fence *
 pvr_fence_create_from_fence(struct pvr_fence_context *fctx,
-                           struct _SYNC_CHECKPOINT_CONTEXT *sync_checkpoint_ctx,
+                           struct SYNC_CHECKPOINT_CONTEXT_TAG *sync_checkpoint_ctx,
                            struct dma_fence *fence,
                            PVRSRV_FENCE fence_fd,
                            const char *name);
@@ -170,8 +176,8 @@ int pvr_fence_sw_signal(struct pvr_fence *pvr_fence);
 int pvr_fence_sw_error(struct pvr_fence *pvr_fence);
 
 int pvr_fence_get_checkpoints(struct pvr_fence **pvr_fences, u32 nr_fences,
-                             struct _SYNC_CHECKPOINT **fence_checkpoints);
-struct _SYNC_CHECKPOINT *
+                             struct SYNC_CHECKPOINT_TAG **fence_checkpoints);
+struct SYNC_CHECKPOINT_TAG *
 pvr_fence_get_checkpoint(struct pvr_fence *update_fence);
 
 void pvr_fence_context_signal_fences_nohw(void *data);
index 873df3b..3e65aa3 100644 (file)
@@ -90,13 +90,6 @@ typedef struct RGX_HWPERF_FTRACE_DATA {
 static POS_LOCK ghGPUTraceStateLock;
 static IMG_BOOL gbFTraceGPUEventsEnabled = PVRSRV_APPHINT_ENABLEFTRACEGPU;
 
-/* Saved value of the clock source before the trace was enabled. We're keeping
- * it here so that we know which clock should be selected after we disable the
- * gpu ftrace. */
-#if defined(SUPPORT_RGX)
-static RGXTIMECORR_CLOCK_TYPE geLastTimeCorrClock = PVRSRV_APPHINT_TIMECORRCLOCK;
-#endif
-
 /* This lock ensures that the reference counting operation on the FTrace UFO
  * events and enable/disable operation on firmware event are performed as
  * one atomic operation. This should ensure that there are no race conditions
@@ -287,10 +280,18 @@ static PVRSRV_ERROR _GpuTraceEnable(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
                IMG_UINT64 ui64UFOFilter = psRgxDevInfo->ui64HWPerfFilter &
                        (RGX_HWPERF_EVENT_MASK_FW_SED | RGX_HWPERF_EVENT_MASK_FW_UFO);
 
-               eError = PVRSRVRGXCtrlHWPerfKM(NULL, psRgxDevNode,
-                                              RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE,
-                                              RGX_HWPERF_EVENT_MASK_HW_KICKFINISH |
-                                              ui64UFOFilter);
+               /* Do not call into PVRSRVRGXCtrlHWPerfKM if we're in GUEST mode. */
+               if (PVRSRV_VZ_MODE_IS(GUEST))
+               {
+                       eError = PVRSRV_OK;
+               }
+               else
+               {
+                       eError = PVRSRVRGXCtrlHWPerfKM(NULL, psRgxDevNode,
+                                                      RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE,
+                                                      RGX_HWPERF_EVENT_MASK_HW_KICKFINISH |
+                                                      ui64UFOFilter);
+               }
                PVR_LOG_GOTO_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM", err_out);
        }
        else
@@ -327,10 +328,10 @@ static PVRSRV_ERROR _GpuTraceEnable(PVRSRV_RGXDEV_INFO *psRgxDevInfo)
        PVR_LOG_GOTO_IF_ERROR(eError, "TLClientOpenStream", err_out);
 
 #if defined(SUPPORT_RGX)
-       if (RGXTimeCorrGetClockSource() != RGXTIMECORR_CLOCK_SCHED)
+       if (RGXTimeCorrGetClockSource(psRgxDevNode) != RGXTIMECORR_CLOCK_SCHED)
        {
                /* Set clock source for timer correlation data to sched_clock */
-               geLastTimeCorrClock = RGXTimeCorrGetClockSource();
+               psRgxDevInfo->ui32LastClockSource = RGXTimeCorrGetClockSource(psRgxDevNode);
                RGXTimeCorrSetClockSource(psRgxDevNode, RGXTIMECORR_CLOCK_SCHED);
        }
 #endif
@@ -381,10 +382,11 @@ static PVRSRV_ERROR _GpuTraceDisable(PVRSRV_RGXDEV_INFO *psRgxDevInfo, IMG_BOOL
        if (!psRgxDevInfo->bFirmwareInitialised)
        {
                psRgxDevInfo->ui64HWPerfFilter = RGX_HWPERF_EVENT_MASK_NONE;
+#if !defined(NO_HARDWARE)
                PVR_DPF((PVR_DBG_WARNING,
-                                "HWPerfFW mask has been SET to (%" IMG_UINT64_FMTSPECx ")",
-                                psRgxDevInfo->ui64HWPerfFilter));
-
+                        "HWPerfFW mask has been SET to (%" IMG_UINT64_FMTSPECx ")",
+                        psRgxDevInfo->ui64HWPerfFilter));
+#endif
                return PVRSRV_OK;
        }
 
@@ -397,9 +399,17 @@ static PVRSRV_ERROR _GpuTraceDisable(PVRSRV_RGXDEV_INFO *psRgxDevInfo, IMG_BOOL
 #if defined(SUPPORT_RGX)
        if (!bDeInit)
        {
-               eError = PVRSRVRGXCtrlHWPerfKM(NULL, psRgxDevNode,
-                                              RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE,
-                                              (RGX_HWPERF_EVENT_MASK_NONE));
+               /* Do not call into PVRSRVRGXCtrlHWPerfKM if we are in GUEST mode. */
+               if (PVRSRV_VZ_MODE_IS(GUEST))
+               {
+                       eError = PVRSRV_OK;
+               }
+               else
+               {
+                       eError = PVRSRVRGXCtrlHWPerfKM(NULL, psRgxDevNode,
+                                                      RGX_HWPERF_STREAM_ID0_FW, IMG_FALSE,
+                                                      (RGX_HWPERF_EVENT_MASK_NONE));
+               }
                PVR_LOG_IF_ERROR(eError, "PVRSRVRGXCtrlHWPerfKM");
        }
 #endif
@@ -441,9 +451,9 @@ static PVRSRV_ERROR _GpuTraceDisable(PVRSRV_RGXDEV_INFO *psRgxDevInfo, IMG_BOOL
        }
 
 #if defined(SUPPORT_RGX)
-       if (geLastTimeCorrClock != RGXTIMECORR_CLOCK_SCHED)
+       if (psRgxDevInfo->ui32LastClockSource != RGXTIMECORR_CLOCK_SCHED)
        {
-               RGXTimeCorrSetClockSource(psRgxDevNode, geLastTimeCorrClock);
+               RGXTimeCorrSetClockSource(psRgxDevNode, psRgxDevInfo->ui32LastClockSource);
        }
 #endif
 
@@ -482,7 +492,9 @@ static PVRSRV_ERROR _GpuTraceSetEnabledForAllDevices(IMG_BOOL bNewValue)
        PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_NODE *psDeviceNode;
 
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
        psDeviceNode = psPVRSRVData->psDeviceNodeList;
+
        /* enable/disable GPU trace on all devices */
        while (psDeviceNode)
        {
@@ -494,6 +506,8 @@ static PVRSRV_ERROR _GpuTraceSetEnabledForAllDevices(IMG_BOOL bNewValue)
                psDeviceNode = psDeviceNode->psNext;
        }
 
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
+
        PVR_DPF_RETURN_RC(eError);
 }
 
@@ -508,10 +522,10 @@ PVRSRV_ERROR PVRGpuTraceSetEnabled(PVRSRV_DEVICE_NODE *psDeviceNode,
 static const IMG_CHAR *_HWPerfKickTypeToStr(RGX_HWPERF_KICK_TYPE eKickType)
 {
        static const IMG_CHAR *aszKickType[RGX_HWPERF_KICK_TYPE_LAST+1] = {
-#if defined(HWPERF_PACKET_V2C_SIG)
-               "TA3D", "CDM", "RS", "SHG", "TQTDM", "SYNC", "LAST"
+#if defined(RGX_FEATURE_HWPERF_VOLCANIC)
+               "TA3D", "CDM", "RS", "SHG", "TQTDM", "SYNC", "TA", "3D", "LAST"
 #else
-               "TA3D", "TQ2D", "TQ3D", "CDM", "RS", "VRDM", "TQTDM", "SYNC", "LAST"
+               "TA3D", "TQ2D", "TQ3D", "CDM", "RS", "VRDM", "TQTDM", "SYNC", "TA", "3D", "LAST"
 #endif
        };
 
@@ -1060,7 +1074,8 @@ void PVRGpuTraceInitAppHintCallbacks(const PVRSRV_DEVICE_NODE *psDeviceNode)
 
 void PVRGpuTraceEnableUfoCallback(void)
 {
-       PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetPVRSRVData()->psDeviceNodeList;
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 #if defined(SUPPORT_RGX)
        PVRSRV_RGXDEV_INFO *psRgxDevInfo;
        PVRSRV_ERROR eError;
@@ -1070,6 +1085,9 @@ void PVRGpuTraceEnableUfoCallback(void)
        OSLockAcquire(ghLockFTraceEventLock);
        if (guiUfoEventRef++ == 0)
        {
+               OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+               psDeviceNode = psPVRSRVData->psDeviceNodeList;
+
                /* make sure UFO events are enabled on all rogue devices */
                while (psDeviceNode)
                {
@@ -1097,6 +1115,8 @@ void PVRGpuTraceEnableUfoCallback(void)
 #endif
                        psDeviceNode = psDeviceNode->psNext;
                }
+
+               OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
        }
        OSLockRelease(ghLockFTraceEventLock);
 }
@@ -1106,6 +1126,7 @@ void PVRGpuTraceDisableUfoCallback(void)
 #if defined(SUPPORT_RGX)
        PVRSRV_ERROR eError;
 #endif
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_NODE *psDeviceNode;
 
        /* We have to check if lock is valid because on driver unload
@@ -1117,7 +1138,8 @@ void PVRGpuTraceDisableUfoCallback(void)
        if (ghLockFTraceEventLock == NULL)
                return;
 
-       psDeviceNode = PVRSRVGetPVRSRVData()->psDeviceNodeList;
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode = psPVRSRVData->psDeviceNodeList;
 
        /* Lock down events state, for consistent value of guiUfoEventRef */
        OSLockAcquire(ghLockFTraceEventLock);
@@ -1149,15 +1171,19 @@ void PVRGpuTraceDisableUfoCallback(void)
                                        psDeviceNode->sDevId.i32OsDeviceID));
                        }
 #endif
+
                        psDeviceNode = psDeviceNode->psNext;
                }
        }
        OSLockRelease(ghLockFTraceEventLock);
+
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
 }
 
 void PVRGpuTraceEnableFirmwareActivityCallback(void)
 {
-       PVRSRV_DEVICE_NODE *psDeviceNode = PVRSRVGetPVRSRVData()->psDeviceNodeList;
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
+       PVRSRV_DEVICE_NODE *psDeviceNode;
 #if defined(SUPPORT_RGX)
        PVRSRV_RGXDEV_INFO *psRgxDevInfo;
        uint64_t ui64Filter, ui64FWEventsFilter = 0;
@@ -1169,6 +1195,10 @@ void PVRGpuTraceEnableFirmwareActivityCallback(void)
                ui64FWEventsFilter |= RGX_HWPERF_EVENT_MASK_VALUE(i);
        }
 #endif
+
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode = psPVRSRVData->psDeviceNodeList;
+
        OSLockAcquire(ghLockFTraceEventLock);
        /* Enable all FW events on all the devices */
        while (psDeviceNode)
@@ -1180,7 +1210,7 @@ void PVRGpuTraceEnableFirmwareActivityCallback(void)
 
                eError = PVRSRVRGXCtrlHWPerfKM(NULL, psDeviceNode, RGX_HWPERF_STREAM_ID0_FW,
                                               IMG_FALSE, ui64Filter);
-               if (eError != PVRSRV_OK)
+               if ((eError != PVRSRV_OK) && !PVRSRV_VZ_MODE_IS(GUEST))
                {
                        PVR_DPF((PVR_DBG_ERROR, "Could not enable HWPerf event for firmware"
                                " task timings (%s).", PVRSRVGetErrorString(eError)));
@@ -1189,10 +1219,13 @@ void PVRGpuTraceEnableFirmwareActivityCallback(void)
                psDeviceNode = psDeviceNode->psNext;
        }
        OSLockRelease(ghLockFTraceEventLock);
+
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
 }
 
 void PVRGpuTraceDisableFirmwareActivityCallback(void)
 {
+       PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData();
        PVRSRV_DEVICE_NODE *psDeviceNode;
 #if defined(SUPPORT_RGX)
        IMG_UINT64 ui64FWEventsFilter = ~0;
@@ -1208,7 +1241,8 @@ void PVRGpuTraceDisableFirmwareActivityCallback(void)
        if (ghLockFTraceEventLock == NULL)
                return;
 
-       psDeviceNode = PVRSRVGetPVRSRVData()->psDeviceNodeList;
+       OSWRLockAcquireRead(psPVRSRVData->hDeviceNodeListLock);
+       psDeviceNode = psPVRSRVData->psDeviceNodeList;
 
 #if defined(SUPPORT_RGX)
        for (i = RGX_HWPERF_FW_EVENT_RANGE_FIRST_TYPE;
@@ -1227,8 +1261,9 @@ void PVRGpuTraceDisableFirmwareActivityCallback(void)
                PVRSRV_RGXDEV_INFO *psRgxDevInfo = psDeviceNode->pvDevice;
                IMG_UINT64 ui64Filter = psRgxDevInfo->ui64HWPerfFilter & ui64FWEventsFilter;
 
-               if (PVRSRVRGXCtrlHWPerfKM(NULL, psDeviceNode, RGX_HWPERF_STREAM_ID0_FW,
-                                         IMG_FALSE, ui64Filter) != PVRSRV_OK)
+               if ((PVRSRVRGXCtrlHWPerfKM(NULL, psDeviceNode, RGX_HWPERF_STREAM_ID0_FW,
+                                         IMG_FALSE, ui64Filter) != PVRSRV_OK) &&
+                   !PVRSRV_VZ_MODE_IS(GUEST))
                {
                        PVR_DPF((PVR_DBG_ERROR, "Could not disable HWPerf event for firmware task timings."));
                }
@@ -1237,6 +1272,8 @@ void PVRGpuTraceDisableFirmwareActivityCallback(void)
        }
 
        OSLockRelease(ghLockFTraceEventLock);
+
+       OSWRLockReleaseRead(psPVRSRVData->hDeviceNodeListLock);
 }
 
 /******************************************************************************
index 893bdda..58f7c0a 100644 (file)
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <asm/page.h>
 
 #include "module_common.h"
 #include "pvr_drv.h"
 #include "pvrmodule.h"
 #include "sysinfo.h"
-#include "pvr_debug.h"
-
 
 
 /* This header must always be included last */
@@ -148,6 +145,7 @@ static int pvr_devices_register(void)
        return 0;
 }
 #endif
+
 static void pvr_devices_unregister(void)
 {
 #if defined(MODULE) && !defined(PVR_LDM_PLATFORM_PRE_REGISTERED)
@@ -163,90 +161,6 @@ static void pvr_devices_unregister(void)
 #endif /* defined(MODULE) && !defined(PVR_LDM_PLATFORM_PRE_REGISTERED) */
 }
 
-#ifdef IMG_GPU_DEBUG
-unsigned long va2pa(const void *vaddr_in);
-unsigned long va2pa(const void *vaddr_in)
-{
-    pgd_t *pgd;
-    p4d_t *p4d;
-    pud_t *pud;
-    pmd_t *pmd;
-    pte_t *pte;
-    unsigned long paddr = 0;
-    unsigned long page_addr = 0;
-    unsigned long page_offset = 0;
-    unsigned long vaddr = (unsigned long)vaddr_in;
-
-    printk("CSR_SATP = %lx\n", csr_read(CSR_SATP));
-
-    pgd = pgd_offset_k(vaddr);
-    printk("pgd_val = 0x%lx\n", pgd_val(*pgd));
-    printk("pgd_index = %lu\n", pgd_index(vaddr));
-    if (pgd_none(*pgd)) {
-        printk("not mapped in pgd\n");
-        return -1;
-    }
-
-    p4d = p4d_offset(pgd, vaddr);
-    printk("p4d_val = 0x%lx\n", p4d_val(*p4d));
-    if (p4d_none(*p4d)) {
-        printk("not mapped in p4d\n");
-        return -1;
-    }
-
-    pud = pud_offset(p4d, vaddr);
-    printk("pud_val = 0x%lx\n", pud_val(*pud));
-    if (pud_none(*pud)) {
-        printk("not mapped in pud\n");
-        return -1;
-    }
-
-    pmd = pmd_offset(pud, vaddr);
-    printk("pmd_val = 0x%lx\n", pmd_val(*pmd));
-    printk("pmd_index = %lu\n", pmd_index(vaddr));
-    if (pmd_none(*pmd)) {
-        printk("not mapped in pmd\n");
-        return -1;
-    }
-
-
-    pte = pte_offset_kernel(pmd, vaddr);
-    printk("pte_val = 0x%lx\n", pte_val(*pte));
-    printk("pte_index = %lu\n", pte_index(vaddr));
-    if (pte_none(*pte)) {
-        printk("not mapped in pte\n");
-        return -1;
-    }
-
-    /*Risc-v PTE format: PFN << 10 | prot_val*/
-    /* If PMD entry's bits 1-3 is non-zeor, then this is the leaf PTE */
-    if ((pmd_val(*pmd) & 0xE)) {
-        page_addr = pfn_to_phys(pmd_val(*pmd) >> _PAGE_PFN_SHIFT);
-        page_offset = vaddr & ~PMD_MASK;
-    } else {
-        page_addr = pfn_to_phys(pte_pfn(*pte));
-        page_offset = vaddr & ~PAGE_MASK;
-    }
-
-    paddr = page_addr | page_offset;
-    printk("page_addr = %lx, page_offset = %lx\n", page_addr, page_offset);
-    printk("vaddr = %lx, paddr = %lx\n", vaddr, paddr);
-
-    printk("!Only valid for linear space! - virt_to_phys(vaddr) = %lx\n", virt_to_phys((unsigned long *)vaddr_in));
-
-    return paddr;
-}
-
-void va2pa_test(void)
-{
-       void *tmp = kmalloc(256, GFP_KERNEL);
-
-       memset(tmp, 0x55, 256);
-       va2pa(tmp);
-       kfree(tmp);
-}
-#endif /* IMG_GPU_DEBUG */
-
 static int pvr_probe(struct platform_device *pdev)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
@@ -254,8 +168,7 @@ static int pvr_probe(struct platform_device *pdev)
        int ret;
 
        DRM_DEBUG_DRIVER("device %p\n", &pdev->dev);
-       printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
-       
+
        ddev = drm_dev_alloc(&pvr_drm_platform_driver, &pdev->dev);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
        if (IS_ERR(ddev))
@@ -341,7 +254,7 @@ static void pvr_shutdown(struct platform_device *pdev)
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
 static const struct of_device_id pvr_of_ids[] = {
-#if 1// defined(SYS_RGX_OF_COMPATIBLE)
+#if defined(SYS_RGX_OF_COMPATIBLE)
        { .compatible = SYS_RGX_OF_COMPATIBLE, },
 #endif
        {},
@@ -388,17 +301,17 @@ static int __init pvr_init(void)
        (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
        pvr_drm_platform_driver.set_busid = drm_platform_set_busid;
 #endif
-       printk("@@@@@#################################################\n");
+
+       printk("@@#########################@@\n");
        err = PVRSRVDriverInit();
        if (err)
                return err;
 
-       printk("%s...%d.. compatable:%s\n", __func__, __LINE__, pvr_platform_driver.driver.of_match_table->compatible);
        err = platform_driver_register(&pvr_platform_driver);
        if (err)
                return err;
 
-       return 0;
+       return 0;//pvr_devices_register();
 }
 
 static void __exit pvr_exit(void)
index d7d6957..8ca3886 100644 (file)
@@ -112,6 +112,12 @@ typedef struct DFS_FILE
 
 /* ----- native callbacks interface ----------------------------------------- */
 
+static void _WriteData(void *pvNativeHandle, const void *pvData,
+                       IMG_UINT32 uiSize)
+{
+       seq_write(pvNativeHandle, pvData, uiSize);
+}
+
 static void _VPrintf(void *pvNativeHandle, const IMG_CHAR *pszFmt,
                      va_list pArgs)
 {
@@ -141,6 +147,7 @@ static IMG_BOOL _HasOverflowed(void *pvNativeHandle)
 }
 
 static OSDI_IMPL_ENTRY_CB _g_sEntryCallbacks = {
+       .pfnWrite = _WriteData,
        .pfnVPrintf = _VPrintf,
        .pfnPuts = _Puts,
        .pfnHasOverflowed = _HasOverflowed,
@@ -402,21 +409,28 @@ static ssize_t _Write(struct file *psFile, const char __user *pszBuffer,
        DFS_FILE *psDFSFile = PDE_DATA(psINode);
        DI_ITERATOR_CB *psIter = &psDFSFile->sEntry.sIterCb;
        IMG_CHAR *pcLocalBuffer;
-       IMG_UINT64 ui64Count = uiCount + 1, ui64Pos = *puiPos;
+       IMG_UINT64 ui64Count;
        IMG_INT64 i64Res = -EIO;
+       IMG_UINT64 ui64Pos = *puiPos;
 
        PVR_LOG_RETURN_IF_FALSE(psDFSFile != NULL, "psDFSFile is NULL",
                                -EIO);
        PVR_LOG_RETURN_IF_FALSE(psIter->pfnWrite != NULL, "pfnWrite is NULL",
                                -EIO);
 
+       /* Make sure we allocate the smallest amount of needed memory*/
+       ui64Count = psIter->ui32WriteLenMax;
+       PVR_LOG_GOTO_IF_FALSE(uiCount <= ui64Count, "uiCount too long", return_);
+       ui64Count = MIN(uiCount+1, ui64Count);
+
        _DRIVER_THREAD_ENTER();
 
+       /* allocate buffer with one additional byte for NUL character */
        pcLocalBuffer = OSAllocMem(ui64Count);
        PVR_LOG_GOTO_IF_FALSE(pcLocalBuffer != NULL, "OSAllocMem() failed",
                              return_);
 
-       i64Res = pvr_copy_from_user(pcLocalBuffer, pszBuffer, uiCount);
+       i64Res = pvr_copy_from_user(pcLocalBuffer, pszBuffer, ui64Count);
        PVR_LOG_GOTO_IF_FALSE(i64Res == 0, "pvr_copy_from_user() failed",
                              free_local_buffer_);
 
index 4f1d155..a8ecd8b 100644 (file)
@@ -92,10 +92,12 @@ enum PVRSRV_ERROR_TAG pvr_sync_fence_release(void *fence);
 
 enum PVRSRV_ERROR_TAG pvr_sync_fence_get(int fence_fd, void **fence_out);
 
-enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
-                                                   const char *fence_name,
-                                                   int *fence_fd_out,
-                                                   u64 *sync_pt_idx);
+enum PVRSRV_ERROR_TAG
+pvr_sync_sw_timeline_fence_create(struct _PVRSRV_DEVICE_NODE_ *pvrsrv_dev_node,
+                                 int timeline_fd,
+                                 const char *fence_name,
+                                 int *fence_fd_out,
+                                 u64 *sync_pt_idx);
 
 enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_advance(void *timeline,
                                               u64 *sync_pt_idx);
index 6b2ded2..d454de8 100644 (file)
@@ -68,6 +68,8 @@
 
 #include "linux_sw_sync.h"
 
+#include "pvr_sync_api.h"
+
 #include "kernel_compatibility.h"
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0))
@@ -171,7 +173,7 @@ struct pvr_sync_native_sync_prim {
        struct list_head list;
 
        /* Base services sync prim structure */
-       struct PVRSRV_CLIENT_SYNC_PRIM *client_sync;
+       struct PVRSRV_CLIENT_SYNC_PRIM_TAG *client_sync;
 
        /* The next queued value which should be used */
        u32 next_value;
@@ -361,16 +363,10 @@ static struct {
        struct workqueue_struct *defer_free_wq;
        struct work_struct defer_free_work;
 
-       /* check_status workqueue: When a foreign point is completed, a SW
-        * operation marks the sync as completed to allow the operations to
-        * continue. This completion may require the hardware to be notified,
-        * which may be expensive/take locks, so we push that to a workqueue
-        */
-       struct workqueue_struct *check_status_wq;
        struct work_struct check_status_work;
 
        /* Context used to create client sync prims. */
-       struct SYNC_PRIM_CONTEXT *sync_prim_context;
+       struct SYNC_PRIM_CONTEXT_TAG *sync_prim_context;
 
        /* Unique id counter for the sync prims */
        atomic_t sync_id;
@@ -704,8 +700,7 @@ sync_pool_get(struct pvr_sync_native_sync_prim **_sync,
        sync->id = atomic_inc_return(&pvr_sync_data.sync_id);
        sync->type = type;
 
-       strncpy(sync->class, class_name, sizeof(sync->class));
-       sync->class[sizeof(sync->class) - 1] = '\0';
+       strlcpy(sync->class, class_name, sizeof(sync->class));
        /* It's crucial to reset the sync to zero */
        set_sync_prim_value(sync, 0);
        sync->next_value = 0;
@@ -1146,7 +1141,7 @@ pvr_sync_create_sync_data(struct pvr_sync_timeline *timeline,
        sync_data->kernel->fence_sync->id =
                SyncCheckpointGetId(sync_data->kernel->fence_sync->client_sync_checkpoint);
        sync_data->kernel->fence_sync->type = SYNC_PT_FENCE_TYPE;
-       strncpy(sync_data->kernel->fence_sync->class, pt_name,
+       strlcpy(sync_data->kernel->fence_sync->class, pt_name,
                        sizeof(sync_data->kernel->fence_sync->class));
 
        /* Update list (for debug ) */
@@ -1277,7 +1272,7 @@ static void pvr_sync_foreign_sync_pt_signaled(struct sync_fence *fence,
                /* The completed sw-sync may allow other tasks to complete,
                 * so we need to allow them to progress.
                 */
-               queue_work(pvr_sync_data.check_status_wq,
+               queue_work(NativeSyncGetFenceStatusWq(),
                        &pvr_sync_data.check_status_work);
 
                kfree(waiter);
@@ -1344,7 +1339,9 @@ pvr_sync_create_waiter_for_foreign_sync(int fd, PSYNC_CHECKPOINT_CONTEXT psSyncC
        kernel->fence_sync->client_sync_checkpoint = checkpoint;
 
        kernel->fence_sync->foreign_sync_fence = fence;
-       strncpy(kernel->fence_sync->foreign_sync_fence_name, fence->name, 32);
+       strlcpy(kernel->fence_sync->foreign_sync_fence_name,
+                       fence->name,
+                       sizeof(kernel->fence_sync->foreign_sync_fence_name));
 
        kernel->fence_sync->vaddr =
                SyncCheckpointGetFirmwareAddr(kernel->fence_sync->client_sync_checkpoint);
@@ -1451,21 +1448,11 @@ err_out:
        return NULL;
 }
 
-/* Predeclare the pvr_sync_fops as it's used for comparison to ensure the
- * update_timeline_fd passed in to pvr_sync_append_fences() is a pvr_sync
- * timeline.
- */
-static const struct file_operations pvr_sync_fops;
-
-
-/* ioctl and fops handling */
-
-static int pvr_sync_open(struct inode *inode, struct file *file)
+int pvr_sync_api_init(void *file_handle, void **api_priv)
 {
        struct pvr_sync_timeline_wrapper *timeline_wrapper;
        struct pvr_sync_timeline *timeline;
        char task_comm[TASK_COMM_LEN];
-       int err = -ENOMEM;
        unsigned long flags;
 
        get_task_comm(task_comm, current);
@@ -1503,10 +1490,9 @@ static int pvr_sync_open(struct inode *inode, struct file *file)
 
        DPF("%s: # %s", __func__, debug_info_timeline(timeline));
 
-       file->private_data = timeline_wrapper;
-       err = 0;
-err_out:
-       return err;
+       *api_priv = (void *)timeline_wrapper;
+
+       return 0;
 
 err_free_timeline:
        kfree(timeline);
@@ -1518,20 +1504,24 @@ err_free_timeline:
        timeline_wrapper->timeline = NULL;
 err_free_timeline_wrapper:
        sync_timeline_destroy(&timeline_wrapper->obj);
-       goto err_out;
+err_out:
+       return -ENOMEM;
 }
 
-static int pvr_sync_close(struct inode *inode, struct file *file)
+int pvr_sync_api_deinit(void *api_priv, bool is_sw)
 {
-       struct sync_timeline *obj = file->private_data;
+       if (!api_priv)
+               return 0;
+
+       if (!is_sw) {
+               struct sync_timeline *obj = api_priv;
 
-       if (is_pvr_timeline(obj)) {
                DPF("%s: # %s", __func__,
                    debug_info_timeline(get_timeline(obj)));
 
                sync_timeline_destroy(obj);
        } else {
-               struct pvr_sw_sync_timeline *pvr_sw_sync_timeline = file->private_data;
+               struct pvr_sw_sync_timeline *pvr_sw_sync_timeline = api_priv;
 
                /* SW timeline */
                kref_put(&pvr_sw_sync_timeline->kref, pvr_sw_sync_destroy_timeline);
@@ -1570,6 +1560,7 @@ pvr_sync_finalise_fence(PVRSRV_FENCE fence_fd, void *finalise_data)
  * in that fence. The OS native sync code needs to implement a function
  * meeting this specification.
  *
+ * Input: device                   Not currently used.
  * Input: fence_name               A string to annotate the fence with (for
  *                                 debug).
  * Input: timeline                 The timeline on which the new fence is to be
@@ -1581,7 +1572,8 @@ pvr_sync_finalise_fence(PVRSRV_FENCE fence_fd, void *finalise_data)
  * Output: new_checkpoint_handle   The PSYNC_CHECKPOINT used by the new fence.
  */
 static enum PVRSRV_ERROR_TAG
-pvr_sync_create_fence(const char *fence_name,
+pvr_sync_create_fence(struct _PVRSRV_DEVICE_NODE_ *device,
+                     const char *fence_name,
                      PVRSRV_TIMELINE new_fence_timeline,
                      PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
                      PVRSRV_FENCE *new_fence,
@@ -1591,9 +1583,10 @@ pvr_sync_create_fence(const char *fence_name,
                      void **timeline_update_sync,
                      __u32 *timeline_update_value)
 {
-       PVRSRV_ERROR err = PVRSRV_OK;
+       PVRSRV_ERROR err;
        PVRSRV_FENCE new_fence_fd = -1;
        struct file *timeline_file;
+       struct sync_timeline *obj;
        struct pvr_sync_timeline *timeline;
        struct pvr_sync_pt *native_sync_point = NULL;
        struct sync_fence *native_fence = NULL;
@@ -1622,25 +1615,20 @@ pvr_sync_create_fence(const char *fence_name,
                goto err_put_fd;
        }
 
-       if (timeline_file->f_op != &pvr_sync_fops) {
+       obj = pvr_sync_get_api_priv(timeline_file);
+       if (!obj) {
                pr_err("pvr_sync2: %s: Supplied timeline not pvr_sync timeline\n",
                        __func__);
                err = PVRSRV_ERROR_INVALID_PARAMS;
                goto err_put_timeline;
        }
 
-       timeline = get_timeline(timeline_file->private_data);
-
-       /* We know this will not free the timeline as the user still
-        * has the fd referencing it.
-        */
-       fput(timeline_file);
-
+       timeline = get_timeline(obj);
        if (!timeline) {
                pr_err("pvr_sync2: %s: Supplied timeline has no private data\n",
                        __func__);
                err = PVRSRV_ERROR_INVALID_PARAMS;
-               goto err_put_fd;
+               goto err_put_timeline;
        }
 
        /* Check if this timeline already has a sync prim, if not create it now */
@@ -1653,7 +1641,7 @@ pvr_sync_create_fence(const char *fence_name,
                        pr_err("pvr_sync2: %s: Failed to allocate timeline sync prim (%s)\n",
                                                        __func__, PVRSRVGetErrorString(err));
                        err = PVRSRV_ERROR_OUT_OF_MEMORY;
-                       goto err_put_fd;
+                       goto err_put_timeline;
                }
        }
 
@@ -1663,7 +1651,7 @@ pvr_sync_create_fence(const char *fence_name,
                pr_err("pvr_sync2: %s: Failed to create sync point\n",
                        __func__);
                err = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto err_put_fd;
+               goto err_put_timeline;
        }
 
        native_fence = sync_fence_create(fence_name, &native_sync_point->pt);
@@ -1686,7 +1674,7 @@ pvr_sync_create_fence(const char *fence_name,
                error_sync_checkpoint(native_sync_point->sync_data->kernel->fence_sync,
                                      PVRSRV_FENCE_FLAG_NONE);
                pvr_sync_free_sync(&native_sync_point->pt);
-               goto err_put_fd;
+               goto err_put_timeline;
        }
 
        sync_kernel = native_sync_point->sync_data->kernel;
@@ -1709,7 +1697,9 @@ pvr_sync_create_fence(const char *fence_name,
        *fence_uid = OSGetCurrentClientProcessIDKM();
        *fence_uid = (*fence_uid << 32) | (new_fence_fd & U32_MAX);
 
-       goto err_out;
+       fput(timeline_file);
+
+       return PVRSRV_OK;
 
 err_put_timeline:
        fput(timeline_file);
@@ -1932,15 +1922,15 @@ err_out:
 #if defined(PDUMP)
 static enum PVRSRV_ERROR_TAG
 pvr_sync_fence_get_checkpoints(PVRSRV_FENCE fence_to_pdump, u32 *nr_checkpoints,
-                               struct _SYNC_CHECKPOINT ***checkpoint_handles)
+                               struct SYNC_CHECKPOINT_TAG ***checkpoint_handles)
 {
        enum PVRSRV_ERROR_TAG err;
        struct sync_fence *sync_fence;
        struct sync_pt *sync_pt;
        struct pvr_sync_kernel_pair *sync_kernel;
        u32 points_on_fence = 0;
-       struct _SYNC_CHECKPOINT **next_checkpoint;
-       struct _SYNC_CHECKPOINT **checkpoints = NULL;
+       struct SYNC_CHECKPOINT_TAG **next_checkpoint;
+       struct SYNC_CHECKPOINT_TAG **checkpoints = NULL;
        int j = 0;
 
        if (!nr_checkpoints || !checkpoint_handles) {
@@ -2046,31 +2036,22 @@ pvr_sync_dump_info_on_stalled_ufos(u32 nr_ufos, u32 *vaddrs)
        return our_ufo_ct;
 }
 
-static long pvr_sync_ioctl_rename(struct pvr_sync_timeline *timeline,
-       void __user *user_data)
+int pvr_sync_api_rename(void *api_priv, void *user_data)
 {
-       int err = 0;
-       struct pvr_sync_rename_ioctl_data data;
-
-       if (!access_ok(user_data, sizeof(data))) {
-               err = -EFAULT;
-               goto err;
-       }
+       struct sync_timeline *obj = api_priv;
+       struct pvr_sync_timeline *timeline = get_timeline(obj);
+       struct pvr_sync_rename_ioctl_data *data = user_data;
 
-       if (copy_from_user(&data, user_data, sizeof(data))) {
-               err = -EFAULT;
-               goto err;
-       }
+       data->szName[sizeof(data->szName) - 1] = '\0';
+       strlcpy(timeline->obj->name, data->szName, sizeof(timeline->obj->name));
 
-       data.szName[sizeof(data.szName) - 1] = '\0';
-       strlcpy(timeline->obj->name, data.szName, sizeof(timeline->obj->name));
-err:
-       return err;
+       return 0;
 }
 
-static long pvr_sync_ioctl_force_sw_only(struct pvr_sync_timeline *timeline,
-       void **private_data)
+int pvr_sync_api_force_sw_only(void *api_priv, void **api_priv_new)
 {
+       struct sync_timeline *obj = api_priv;
+       struct pvr_sync_timeline *timeline = get_timeline(obj);
        struct pvr_sw_sync_timeline *pvr_sw_sync_timeline;
 
        /* We can only convert an empty GPU timeline */
@@ -2112,19 +2093,21 @@ static long pvr_sync_ioctl_force_sw_only(struct pvr_sync_timeline *timeline,
            pvr_sw_sync_timeline->sw_sync_timeline,
            pvr_sw_sync_timeline->current_value,
            pvr_sw_sync_timeline->next_value);
-       *private_data = pvr_sw_sync_timeline;
+
+       *api_priv_new = (void *)pvr_sw_sync_timeline;
+
        return 0;
 }
 
-static long pvr_sync_ioctl_sw_create_fence(struct pvr_sw_sync_timeline *pvr_sw_timeline,
-       void __user *user_data)
+int pvr_sync_api_sw_create_fence(void *api_priv, void *user_data)
 {
-       struct pvr_sw_sync_create_fence_data data;
+       struct pvr_sw_sync_timeline *pvr_sw_timeline = api_priv;
+       struct pvr_sw_sync_create_fence_data *data = user_data;
        struct sync_fence *fence;
        int fd = get_unused_fd_flags(O_CLOEXEC);
        struct sync_pt *sync_pt;
        struct sw_sync_timeline *timeline;
-       int err = -EFAULT;
+       int err;
 
        if (fd < 0) {
                pr_err("pvr_sync2: %s: Failed to find unused fd (%d)\n",
@@ -2133,16 +2116,8 @@ static long pvr_sync_ioctl_sw_create_fence(struct pvr_sw_sync_timeline *pvr_sw_t
                goto err_out;
        }
 
-       if (!pvr_sw_timeline) {
-               pr_err("pvr_sync2: %s: passed a NULL pvr_sw_timeline\n", __func__);
-               goto err_out;
-       }
-
        timeline = pvr_sw_timeline->sw_sync_timeline;
 
-       if (copy_from_user(&data, user_data, sizeof(data)))
-               goto err_put_fd;
-
        sync_pt = sw_sync_pt_create(timeline, pvr_sw_timeline->next_value);
        if (!sync_pt) {
                pr_err("pvr_sync2: %s: Failed to create a sync point (%d)\n",
@@ -2151,8 +2126,8 @@ static long pvr_sync_ioctl_sw_create_fence(struct pvr_sw_sync_timeline *pvr_sw_t
                goto err_put_fd;
        }
 
-       data.name[sizeof(data.name) - 1] = '\0';
-       fence = sync_fence_create(data.name, sync_pt);
+       data->name[sizeof(data->name) - 1] = '\0';
+       fence = sync_fence_create(data->name, sync_pt);
        if (!fence) {
                pr_err("pvr_sync2: %s: Failed to create a fence (%d)\n",
                       __func__, fd);
@@ -2161,35 +2136,26 @@ static long pvr_sync_ioctl_sw_create_fence(struct pvr_sw_sync_timeline *pvr_sw_t
                goto err_put_fd;
        }
 
-       data.fence = fd;
-       data.sync_pt_idx = pvr_sw_timeline->next_value;
-
-       if (copy_to_user(user_data, &data, sizeof(data)))
-               goto err_put_fence;
+       data->fence = fd;
+       data->sync_pt_idx = pvr_sw_timeline->next_value;
 
        sync_fence_install(fence, fd);
        pvr_sw_timeline->next_value++;
 
-       err = 0;
-err_out:
-       return err;
-err_put_fence:
-       sync_fence_put(fence);
+       return 0;
+
 err_put_fd:
        pr_err("pvr_sync2: %s: putting fd %d back to unused\n", __func__, fd);
        put_unused_fd(fd);
-       goto err_out;
+err_out:
+       return err;
 }
 
-static long pvr_sync_ioctl_sw_inc(struct pvr_sw_sync_timeline *pvr_timeline, void __user *user_data)
+int pvr_sync_api_sw_inc(void *api_priv, void *user_data)
 {
+       struct pvr_sw_sync_timeline *pvr_timeline = api_priv;
        struct sw_sync_timeline *timeline;
-       struct pvr_sw_timeline_advance_data data;
-
-       if (!pvr_timeline) {
-               pr_err("pvr_sync2: %s: passed a NULL pvr_timeline\n", __func__);
-               return -EFAULT;
-       }
+       struct pvr_sw_timeline_advance_data *data = user_data;
 
        timeline = pvr_timeline->sw_sync_timeline;
 
@@ -2201,55 +2167,11 @@ static long pvr_sync_ioctl_sw_inc(struct pvr_sw_sync_timeline *pvr_timeline, voi
 
        sw_sync_timeline_inc(timeline, 1);
        pvr_timeline->current_value++;
-       data.sync_pt_idx = pvr_timeline->current_value;
-
-       if (copy_to_user(user_data, &data, sizeof(data))) {
-               pr_err("pvr_sync2: %s: Failed copy to user\n", __func__);
-               return -EFAULT;
-       }
+       data->sync_pt_idx = pvr_timeline->current_value;
 
        return 0;
 }
 
-static long
-pvr_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct sync_timeline *obj = file->private_data;
-       void __user *user_data = (void __user *)arg;
-       long err = -ENOTTY;
-
-       if (is_pvr_timeline(obj)) {
-               struct pvr_sync_timeline *pvr = get_timeline(obj);
-
-               switch (cmd) {
-               case PVR_SYNC_IOC_RENAME:
-                       err = pvr_sync_ioctl_rename(pvr, user_data);
-                       break;
-               case PVR_SYNC_IOC_FORCE_SW_ONLY:
-                       err = pvr_sync_ioctl_force_sw_only(pvr,
-                               &file->private_data);
-                       break;
-               default:
-                       break;
-               }
-       } else {
-               struct pvr_sw_sync_timeline *sw = file->private_data;
-
-               switch (cmd) {
-               case PVR_SW_SYNC_IOC_CREATE_FENCE:
-                       err = pvr_sync_ioctl_sw_create_fence(sw, user_data);
-                       break;
-               case PVR_SW_SYNC_IOC_INC:
-                       err = pvr_sync_ioctl_sw_inc(sw, user_data);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       return err;
-}
-
 static void
 pvr_sync_check_status_work_queue_function(struct work_struct *data)
 {
@@ -2270,7 +2192,7 @@ pvr_sync_clean_freelist(void)
        unsigned long flags;
        bool freelist_empty;
 
-       /* We can't call PVRSRVServerSyncFreeKM directly in this loop because
+       /* We can't free the sync directly in this loop because
         * that will take the mmap mutex. We can't take mutexes while we have
         * this list locked with a spinlock. So move all the items we want to
         * free to another, local list (no locking required) and process it
@@ -2398,20 +2320,6 @@ pvr_sync_defer_free_work_queue_function(struct work_struct *data)
        }
 }
 
-static const struct file_operations pvr_sync_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pvr_sync_open,
-       .release        = pvr_sync_close,
-       .unlocked_ioctl = pvr_sync_ioctl,
-       .compat_ioctl   = pvr_sync_ioctl,
-};
-
-static struct miscdevice pvr_sync_device = {
-       .minor          = MISC_DYNAMIC_MINOR,
-       .name           = PVRSYNC_MODNAME,
-       .fops           = &pvr_sync_fops,
-};
-
 static
 void pvr_sync_free_checkpoint_list_mem(void *mem_ptr)
 {
@@ -2497,19 +2405,12 @@ enum PVRSRV_ERROR_TAG pvr_sync_register_functions(void)
 
 int pvr_sync_init(void)
 {
-       int err;
-
-       err = misc_register(&pvr_sync_device);
-       if (err) {
-               pr_err("pvr_sync2: %s: Failed to register pvr_sync device (%d)\n",
-                      __func__, err);
-       }
-       return err;
+       return pvr_sync_ioctl_init();
 }
 
 void pvr_sync_deinit(void)
 {
-       misc_deregister(&pvr_sync_device);
+       pvr_sync_ioctl_deinit();
 }
 
 enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
@@ -2518,6 +2419,14 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
        struct pvr_drm_private *priv = ddev->dev_private;
        enum PVRSRV_ERROR_TAG error;
 
+       /* Multi-Device not supported for sync2, if we attempt to init
+        * another device then print a big warning to kernel log
+        */
+       if (WARN_ON(pvr_sync_data.defer_free_wq)) {
+               pr_err("pvr_sync2: Multi-Device not supported\n");
+               return PVRSRV_ERROR_ALREADY_EXISTS;
+       }
+
        DPF("%s", __func__);
 
        atomic_set(&pvr_sync_data.sync_id, 0);
@@ -2530,7 +2439,6 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
                goto err_out;
        }
 
-
        error = SyncPrimContextCreate(priv->dev_node,
                                      &pvr_sync_data.sync_prim_context);
        if (error != PVRSRV_OK) {
@@ -2550,9 +2458,6 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
        INIT_WORK(&pvr_sync_data.defer_free_work,
                pvr_sync_defer_free_work_queue_function);
 
-       /* Use the shared workqueue */
-       pvr_sync_data.check_status_wq = priv->fence_status_wq;
-
        INIT_WORK(&pvr_sync_data.check_status_work,
                pvr_sync_check_status_work_queue_function);
        error = PVRSRVRegisterCmdCompleteNotify(
@@ -2565,7 +2470,7 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
                goto err_destroy_defer_free_wq;
        }
 
-       error = PVRSRVRegisterDbgRequestNotify(
+       error = PVRSRVRegisterDeviceDbgRequestNotify(
                        &priv->sync_debug_notify_handle,
                        priv->dev_node,
                        pvr_sync_debug_request,
@@ -2601,7 +2506,7 @@ void pvr_sync_device_deinit(struct device *dev)
 
        DPF("%s", __func__);
 
-       PVRSRVUnregisterDbgRequestNotify(priv->sync_debug_notify_handle);
+       PVRSRVUnregisterDeviceDbgRequestNotify(priv->sync_debug_notify_handle);
 
        PVRSRVUnregisterCmdCompleteNotify(
                pvr_sync_data.command_complete_handle);
@@ -2665,10 +2570,12 @@ enum PVRSRV_ERROR_TAG pvr_sync_fence_get(int fence_fd, void **pfence)
        return PVRSRV_OK;
 }
 
-enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
-                                                   const char *fence_name,
-                                                   int *fence_fd_out,
-                                                   u64 *sync_pt_idx)
+enum PVRSRV_ERROR_TAG
+pvr_sync_sw_timeline_fence_create(struct _PVRSRV_DEVICE_NODE_ *pvrsrv_dev_node,
+                                 int timeline_fd,
+                                 const char *fence_name,
+                                 int *fence_fd_out,
+                                 u64 *sync_pt_idx)
 {
        enum PVRSRV_ERROR_TAG srv_err;
        struct file *file;
@@ -2677,6 +2584,8 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
        struct sync_pt *sync_point;
        int fd;
 
+       (void)(pvrsrv_dev_node);
+
        fd = get_unused_fd_flags(O_CLOEXEC);
        if (fd < 0) {
                pr_err("%s: invalid fd\n", __func__);
@@ -2685,27 +2594,26 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
        }
 
        file = fget(timeline_fd);
-       if (!file || !file->private_data) {
+       pvr_sw_timeline = pvr_sync_get_api_priv(file);
+       if (!pvr_sw_timeline) {
                /* unrecognised timeline */
                pr_err("%s: unrecognised timeline\n", __func__);
 
                srv_err = PVRSRV_ERROR_INVALID_PARAMS;
                if (file)
-                       fput(file);
-               goto err_put_fd;
+                       goto err_put_file;
+               else
+                       goto err_put_fd;
        }
 
-       pvr_sw_timeline = (struct pvr_sw_sync_timeline *)file->private_data;
-
        DPF("pvr_sw_timeline<%p>", pvr_sw_timeline);
        DPF("psSWTimeline<%p>", pvr_sw_timeline->sw_sync_timeline);
 
        sync_point = sw_sync_pt_create(pvr_sw_timeline->sw_sync_timeline,
                                       pvr_sw_timeline->next_value);
-       fput(file);
        if (!sync_point) {
                srv_err = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto err_put_fd;
+               goto err_put_file;
        }
 
        fence = sync_fence_create(fence_name, sync_point);
@@ -2720,6 +2628,8 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
                *sync_pt_idx = pvr_sw_timeline->next_value;
        pvr_sw_timeline->next_value++;
 
+       fput(file);
+
        *fence_fd_out = fd;
 
        DPF("returned fence fd %d <%p> '%s'", *fence_fd_out, fence, fence_name);
@@ -2728,6 +2638,8 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
 
 err_free_pt:
        sync_pt_free(sync_point);
+err_put_file:
+       fput(file);
 err_put_fd:
        put_unused_fd(fd);
        return srv_err;
@@ -2781,13 +2693,17 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_get(int timeline_fd,
        int ret;
 
        file = fget(timeline_fd);
-       if (file == NULL || file->private_data == NULL) {
+       pvr_sw_timeline = pvr_sync_get_api_priv(file);
+       if (!pvr_sw_timeline) {
                pr_err("%s: invalid params\n", __func__);
-               return PVRSRV_ERROR_INVALID_PARAMS;
+               srv_err = PVRSRV_ERROR_INVALID_PARAMS;
+               if (file)
+                       goto err_put_file;
+               else
+                       goto err_out;
        }
 
-       *timeline_out = file->private_data;
-       pvr_sw_timeline = (struct pvr_sw_sync_timeline *)file->private_data;
+       *timeline_out = (void *)pvr_sw_timeline;
 
        /* Take ref on pvr_sw_timeline */
        ret = kref_get_unless_zero(&pvr_sw_timeline->kref);
@@ -2796,9 +2712,6 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_get(int timeline_fd,
        else
                srv_err = PVRSRV_ERROR_INVALID_PARAMS;
 
-       /* Release reference taken on file */
-       fput(file);
-
        DPF("pvr_sw_timeline=<%p>, pvr_sw_timeline->c=%llu, n=%llu",
            pvr_sw_timeline->sw_sync_timeline, pvr_sw_timeline->current_value,
            pvr_sw_timeline->next_value);
@@ -2806,6 +2719,9 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_get(int timeline_fd,
            &pvr_sw_timeline->current_value);
        DPF("returned, *timeline_out=<%p>", *timeline_out);
 
+err_put_file:
+       fput(file);
+err_out:
        return srv_err;
 }
 
@@ -1,5 +1,6 @@
 /*
- * @File
+ * @File        pvr_sync_api.h
+ * @Title       Kernel driver for Android's sync mechanism
  * @Codingstyle LinuxKernel
  * @Copyright   Copyright (c) Imagination Technologies Ltd. All Rights Reserved
  * @License     Dual MIT/GPLv2
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef __DRM_NULLDISP_DRV_H__
-#define __DRM_NULLDISP_DRV_H__
+#ifndef _PVR_SYNC_API_H
+#define _PVR_SYNC_API_H
 
-#include <linux/version.h>
+#include <stdbool.h>
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-#include <drm/drm_fourcc.h>
-#endif
+int pvr_sync_api_init(void *file_handle, void **api_priv);
+int pvr_sync_api_deinit(void *api_priv, bool is_sw);
+int pvr_sync_api_rename(void *api_priv, void *user_data);
+int pvr_sync_api_force_sw_only(void *api_priv, void **api_priv_new);
+int pvr_sync_api_sw_create_fence(void *api_priv, void *user_data);
+int pvr_sync_api_sw_inc(void *api_priv, void *user_data);
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0))
-#define NULLDISP_USE_ATOMIC
-#endif
+struct file;
 
-struct drm_framebuffer;
+int pvr_sync_ioctl_init(void);
+void pvr_sync_ioctl_deinit(void);
+void *pvr_sync_get_api_priv(struct file *file);
+struct file *pvr_sync_get_file_struct(void *file_handle);
 
-/******************************************************************************
- * Linux compatibility functions
- ******************************************************************************/
-static inline u32 nulldisp_drm_fb_format(struct drm_framebuffer *fb)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-       return fb->format->format;
-#else  /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) */
-       return fb->pixel_format;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) */
-}
-
-static inline u64 nulldisp_drm_fb_modifier(struct drm_framebuffer *fb)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
-       return fb->modifier;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
-       return fb->modifier[0];
-#else
-       /* 0 represents DRM_FORMAT_MOD_NONE, doesn't exist before 4.1 */
-       return 0;
-#endif
-}
-
-/******************************************************************************
- * DRM framebuffer support functions
- ******************************************************************************/
-static inline int nulldisp_drm_fb_num_planes(struct drm_framebuffer *fb)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
-       return fb->format->num_planes;
-#else
-       return drm_format_num_planes(nulldisp_drm_fb_format(fb));
-#endif
-}
-#endif /* __DRM_NULLDISP_DRV_H__ */
+#endif /* _PVR_SYNC_API_H */
index 98c4185..e365610 100644 (file)
@@ -57,6 +57,8 @@
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 
+#include "pvr_sync_api.h"
+
 /* This header must always be included last */
 #include "kernel_compatibility.h"
 
@@ -89,8 +91,6 @@ struct sw_sync_create_fence_data {
 
 /* Global data for the sync driver */
 static struct {
-       void *dev_cookie;
-       struct workqueue_struct *fence_status_wq;
        struct pvr_fence_context *foreign_fence_context;
        PFN_SYNC_CHECKPOINT_STRUCT sync_checkpoint_ops;
 } pvr_sync_data;
@@ -100,14 +100,12 @@ static DEFINE_MUTEX(pvr_timeline_active_list_lock);
 static struct list_head pvr_timeline_active_list;
 #endif
 
-static const struct file_operations pvr_sync_fops;
-
 /* This is the actual timeline metadata. We might keep this around after the
  * base sync driver has destroyed the pvr_sync_timeline_wrapper object.
  */
 struct pvr_sync_timeline {
        char name[32];
-       struct file *file;
+       void *file_handle;
        bool is_sw;
        /* Fence context used for hw fences */
        struct pvr_fence_context *hw_fence_context;
@@ -140,58 +138,59 @@ void pvr_sync_nohw_signal_fence(void *fence_data_to_signal)
 }
 #endif
 
-static bool is_pvr_timeline(struct file *file)
-{
-       return file->f_op == &pvr_sync_fops;
-}
-
 static struct pvr_sync_timeline *pvr_sync_timeline_fget(int fd)
 {
        struct file *file = fget(fd);
+       struct pvr_sync_timeline *timeline;
 
        if (!file)
                return NULL;
 
-       if (!is_pvr_timeline(file)) {
+       timeline = pvr_sync_get_api_priv(file);
+       if (!timeline)
                fput(file);
-               return NULL;
-       }
 
-       return file->private_data;
+       return timeline;
 }
 
 static void pvr_sync_timeline_fput(struct pvr_sync_timeline *timeline)
 {
-       fput(timeline->file);
+       struct file *file = pvr_sync_get_file_struct(timeline->file_handle);
+
+       if (file)
+               fput(file);
+       else
+               pr_err(FILE_NAME ": %s: Timeline incomplete\n", __func__);
 }
 
 /* ioctl and fops handling */
 
-static int pvr_sync_open(struct inode *inode, struct file *file)
+int pvr_sync_api_init(void *file_handle, void **api_priv)
 {
        struct pvr_sync_timeline *timeline;
        char task_comm[TASK_COMM_LEN];
-       int err = -ENOMEM;
 
        get_task_comm(task_comm, current);
 
        timeline = kzalloc(sizeof(*timeline), GFP_KERNEL);
        if (!timeline)
-               goto err_out;
+               return -ENOMEM;
 
        strlcpy(timeline->name, task_comm, sizeof(timeline->name));
-       timeline->file = file;
+       timeline->file_handle = file_handle;
        timeline->is_sw = false;
 
-       file->private_data = timeline;
-       err = 0;
-err_out:
-       return err;
+       *api_priv = (void *)timeline;
+
+       return 0;
 }
 
-static int pvr_sync_close(struct inode *inode, struct file *file)
+int pvr_sync_api_deinit(void *api_priv, bool is_sw)
 {
-       struct pvr_sync_timeline *timeline = file->private_data;
+       struct pvr_sync_timeline *timeline = api_priv;
+
+       if (!timeline)
+               return 0;
 
        if (timeline->sw_fence_timeline) {
                /* This makes sure any outstanding SW syncs are marked as
@@ -245,6 +244,11 @@ pvr_sync_finalise_fence(PVRSRV_FENCE fence_fd, void *finalise_data)
 
        pvr_fence = to_pvr_fence(sync_file->fence);
 
+       if (!pvr_fence) {
+               pr_err(FILE_NAME ": %s: Fence not a pvr fence\n", __func__);
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
        /* pvr fences can be signalled any time after creation */
        dma_fence_enable_sw_signaling(&pvr_fence->base);
 
@@ -259,6 +263,7 @@ pvr_sync_finalise_fence(PVRSRV_FENCE fence_fd, void *finalise_data)
  * in that fence. The OS native sync code needs to implement a function
  * meeting this specification.
  *
+ * Input: device                   Device node to use in creating a hw_fence_ctx
  * Input: fence_name               A string to annotate the fence with (for
  *                                 debug).
  * Input: timeline                 The timeline on which the new fence is to be
@@ -270,7 +275,9 @@ pvr_sync_finalise_fence(PVRSRV_FENCE fence_fd, void *finalise_data)
  * Output: new_checkpoint_handle   The PSYNC_CHECKPOINT used by the new fence.
  */
 static enum PVRSRV_ERROR_TAG
-pvr_sync_create_fence(const char *fence_name,
+pvr_sync_create_fence(
+                     struct _PVRSRV_DEVICE_NODE_ *device,
+                     const char *fence_name,
                      PVRSRV_TIMELINE new_fence_timeline,
                      PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
                      PVRSRV_FENCE *new_fence, u64 *fence_uid,
@@ -322,9 +329,10 @@ pvr_sync_create_fence(const char *fence_name,
        if (!timeline->hw_fence_context) {
                /* First time we use this timeline, so create a context. */
                timeline->hw_fence_context =
-                       pvr_fence_context_create(pvr_sync_data.dev_cookie,
-                                                pvr_sync_data.fence_status_wq,
-                                                timeline->name);
+                       pvr_fence_context_create(
+                               device,
+                               NativeSyncGetFenceStatusWq(),
+                               timeline->name);
                if (!timeline->hw_fence_context) {
                        pr_err(FILE_NAME ": %s: Failed to create fence context (%d)\n",
                               __func__, new_fence_timeline);
@@ -454,7 +462,7 @@ pvr_sync_resolve_fence(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
                       PSYNC_CHECKPOINT **checkpoint_handles, u64 *fence_uid)
 {
        PSYNC_CHECKPOINT *checkpoints = NULL;
-       unsigned int i, num_fences, num_used_fences = 0;
+       unsigned int i, num_fences = 0, num_used_fences = 0;
        struct dma_fence **fences = NULL;
        struct dma_fence *fence;
        PVRSRV_ERROR err = PVRSRV_OK;
@@ -484,8 +492,10 @@ pvr_sync_resolve_fence(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
        if (dma_fence_is_array(fence)) {
                struct dma_fence_array *array = to_dma_fence_array(fence);
 
-               fences = array->fences;
-               num_fences = array->num_fences;
+               if (array) {
+                       fences = array->fences;
+                       num_fences = array->num_fences;
+               }
        } else {
                fences = &fence;
                num_fences = 1;
@@ -498,9 +508,16 @@ pvr_sync_resolve_fence(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
                goto err_put_fence;
        }
        for (i = 0; i < num_fences; i++) {
-               /* Only return the checkpoint if the fence is still active. */
+               /*
+                * Only return the checkpoint if the fence is still active.
+                * Don't checked for signalled on PDUMP drivers as we need
+                * to make sure that all fences make it to the pdump.
+                */
+#if !defined(PDUMP)
                if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
-                             &fences[i]->flags)) {
+                             &fences[i]->flags))
+#endif
+               {
                        struct pvr_fence *pvr_fence =
                                pvr_fence_create_from_fence(
                                        pvr_sync_data.foreign_fence_context,
@@ -574,12 +591,12 @@ pvr_sync_dump_info_on_stalled_ufos(u32 nr_ufos, u32 *vaddrs)
 #if defined(PDUMP)
 static enum PVRSRV_ERROR_TAG
 pvr_sync_fence_get_checkpoints(PVRSRV_FENCE fence_to_pdump, u32 *nr_checkpoints,
-                               struct _SYNC_CHECKPOINT ***checkpoint_handles)
+                               struct SYNC_CHECKPOINT_TAG ***checkpoint_handles)
 {
        struct dma_fence **fences = NULL;
        struct dma_fence *fence;
        struct pvr_fence *pvr_fence;
-       struct _SYNC_CHECKPOINT **checkpoints = NULL;
+       struct SYNC_CHECKPOINT_TAG **checkpoints = NULL;
        unsigned int i, num_fences, num_used_fences = 0;
        enum PVRSRV_ERROR_TAG err;
 
@@ -641,42 +658,30 @@ err_out:
 }
 #endif
 
-static long pvr_sync_ioctl_rename(struct pvr_sync_timeline *timeline,
-       void __user *user_data)
+int pvr_sync_api_rename(void *api_priv, void *user_data)
 {
-       int err = 0;
-       struct pvr_sync_rename_ioctl_data data;
+       struct pvr_sync_timeline *timeline = api_priv;
+       struct pvr_sync_rename_ioctl_data *data = user_data;
 
-       if (!access_ok(user_data, sizeof(data))) {
-               err = -EFAULT;
-               goto err;
-       }
-
-       if (copy_from_user(&data, user_data, sizeof(data))) {
-               err = -EFAULT;
-               goto err;
-       }
-
-       data.szName[sizeof(data.szName) - 1] = '\0';
-       strlcpy(timeline->name, data.szName, sizeof(timeline->name));
+       data->szName[sizeof(data->szName) - 1] = '\0';
+       strlcpy(timeline->name, data->szName, sizeof(timeline->name));
        if (timeline->hw_fence_context)
-               strlcpy(timeline->hw_fence_context->name, data.szName,
+               strlcpy(timeline->hw_fence_context->name, data->szName,
                        sizeof(timeline->hw_fence_context->name));
 
-err:
-       return err;
+       return 0;
 }
 
-static long pvr_sync_ioctl_force_sw_only(struct pvr_sync_timeline *timeline,
-       void **private_data)
+int pvr_sync_api_force_sw_only(void *api_priv, void **api_priv_new)
 {
+       struct pvr_sync_timeline *timeline = api_priv;
+
        /* Already in SW mode? */
        if (timeline->sw_fence_timeline)
                return 0;
 
        /* Create a sw_sync timeline with the old GPU timeline's name */
        timeline->sw_fence_timeline = pvr_counting_fence_timeline_create(
-               pvr_sync_data.dev_cookie,
                timeline->name);
        if (!timeline->sw_fence_timeline)
                return -ENOMEM;
@@ -686,14 +691,14 @@ static long pvr_sync_ioctl_force_sw_only(struct pvr_sync_timeline *timeline,
        return 0;
 }
 
-static long pvr_sync_ioctl_sw_create_fence(struct pvr_sync_timeline *timeline,
-       void __user *user_data)
+int pvr_sync_api_sw_create_fence(void *api_priv, void *user_data)
 {
-       struct pvr_sw_sync_create_fence_data data;
+       struct pvr_sync_timeline *timeline = api_priv;
+       struct pvr_sw_sync_create_fence_data *data = user_data;
        struct sync_file *sync_file;
        int fd = get_unused_fd_flags(O_CLOEXEC);
        struct dma_fence *fence;
-       int err = -EFAULT;
+       int err;
 
        if (fd < 0) {
                pr_err(FILE_NAME ": %s: Failed to find unused fd (%d)\n",
@@ -702,12 +707,7 @@ static long pvr_sync_ioctl_sw_create_fence(struct pvr_sync_timeline *timeline,
                goto err_out;
        }
 
-       if (copy_from_user(&data, user_data, sizeof(data))) {
-               pr_err(FILE_NAME ": %s: Failed copy from user\n", __func__);
-               goto err_put_fd;
-       }
-
-       fence = pvr_counting_fence_create(timeline->sw_fence_timeline, &data.sync_pt_idx);
+       fence = pvr_counting_fence_create(timeline->sw_fence_timeline, &data->sync_pt_idx);
        if (!fence) {
                pr_err(FILE_NAME ": %s: Failed to create a sync point (%d)\n",
                       __func__, fd);
@@ -716,41 +716,33 @@ static long pvr_sync_ioctl_sw_create_fence(struct pvr_sync_timeline *timeline,
        }
 
        sync_file = sync_file_create(fence);
+       dma_fence_put(fence);
        if (!sync_file) {
                pr_err(FILE_NAME ": %s: Failed to create a sync point (%d)\n",
                        __func__, fd);
                err = -ENOMEM;
-               goto err_put_fence;
+               goto err_put_fd;
        }
 
-       data.fence = fd;
-
-       if (copy_to_user(user_data, &data, sizeof(data))) {
-               pr_err(FILE_NAME ": %s: Failed copy to user\n", __func__);
-               goto err_put_fence;
-       }
+       data->fence = fd;
 
        fd_install(fd, sync_file->file);
-       err = 0;
 
-       dma_fence_put(fence);
-err_out:
-       return err;
+       return 0;
 
-err_put_fence:
-       dma_fence_put(fence);
 err_put_fd:
        put_unused_fd(fd);
-       goto err_out;
+err_out:
+       return err;
 }
 
-static long pvr_sync_ioctl_sw_inc(struct pvr_sync_timeline *timeline,
-                                 void __user *user_data)
+int pvr_sync_api_sw_inc(void *api_priv, void *user_data)
 {
+       struct pvr_sync_timeline *timeline = api_priv;
+       struct pvr_sw_timeline_advance_data *data = user_data;
        bool res;
-       struct pvr_sw_timeline_advance_data data;
 
-       res = pvr_counting_fence_timeline_inc(timeline->sw_fence_timeline, &data.sync_pt_idx);
+       res = pvr_counting_fence_timeline_inc(timeline->sw_fence_timeline, &data->sync_pt_idx);
 
        /* pvr_counting_fence_timeline_inc won't allow sw timeline to be
         * advanced beyond the last defined point
@@ -760,66 +752,9 @@ static long pvr_sync_ioctl_sw_inc(struct pvr_sync_timeline *timeline,
                return -EPERM;
        }
 
-       if (copy_to_user(user_data, &data, sizeof(data))) {
-               pr_err(FILE_NAME ": %s: Failed copy to user\n", __func__);
-               return -EFAULT;
-       }
-
        return 0;
 }
 
-static long
-pvr_sync_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       void __user *user_data = (void __user *)arg;
-       long err = -ENOTTY;
-       struct pvr_sync_timeline *timeline = file->private_data;
-
-       if (!timeline->is_sw) {
-
-               switch (cmd) {
-               case PVR_SYNC_IOC_RENAME:
-                       err = pvr_sync_ioctl_rename(timeline, user_data);
-                       break;
-               case PVR_SYNC_IOC_FORCE_SW_ONLY:
-                       err = pvr_sync_ioctl_force_sw_only(timeline,
-                               &file->private_data);
-                       break;
-               default:
-                       break;
-               }
-       } else {
-
-               switch (cmd) {
-               case PVR_SW_SYNC_IOC_CREATE_FENCE:
-                       err = pvr_sync_ioctl_sw_create_fence(timeline,
-                                                            user_data);
-                       break;
-               case PVR_SW_SYNC_IOC_INC:
-                       err = pvr_sync_ioctl_sw_inc(timeline, user_data);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       return err;
-}
-
-static const struct file_operations pvr_sync_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pvr_sync_open,
-       .release        = pvr_sync_close,
-       .unlocked_ioctl = pvr_sync_ioctl,
-       .compat_ioctl   = pvr_sync_ioctl,
-};
-
-static struct miscdevice pvr_sync_device = {
-       .minor          = MISC_DYNAMIC_MINOR,
-       .name           = PVRSYNC_MODNAME,
-       .fops           = &pvr_sync_fops,
-};
-
 static void
 pvr_sync_debug_request_heading(void *data, u32 verbosity,
                                DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
@@ -865,17 +800,42 @@ int pvr_sync_init(void)
 {
        int err;
 
-       err = misc_register(&pvr_sync_device);
+       pvr_sync_data.foreign_fence_context =
+                       pvr_fence_foreign_context_create(
+                                       NativeSyncGetFenceStatusWq(),
+                                       "foreign_sync");
+       if (!pvr_sync_data.foreign_fence_context) {
+               pr_err(FILE_NAME ": %s: Failed to create foreign sync context\n",
+                       __func__);
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+#if defined(NO_HARDWARE)
+       INIT_LIST_HEAD(&pvr_timeline_active_list);
+#endif
+
+       err = pvr_sync_ioctl_init();
        if (err) {
                pr_err(FILE_NAME ": %s: Failed to register pvr_sync device (%d)\n",
                       __func__, err);
+               goto err_ioctl_init;
        }
+
+       return 0;
+
+err_ioctl_init:
+       pvr_fence_context_destroy(pvr_sync_data.foreign_fence_context);
+       pvr_fence_cleanup();
+err_out:
        return err;
 }
 
 void pvr_sync_deinit(void)
 {
-       misc_deregister(&pvr_sync_device);
+       pvr_sync_ioctl_deinit();
+       pvr_fence_context_destroy(pvr_sync_data.foreign_fence_context);
+       pvr_fence_cleanup();
 }
 
 enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
@@ -884,7 +844,7 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
        struct pvr_drm_private *priv = ddev->dev_private;
        enum PVRSRV_ERROR_TAG error;
 
-       error = PVRSRVRegisterDbgRequestNotify(
+       error = PVRSRVRegisterDeviceDbgRequestNotify(
                                &priv->sync_debug_notify_handle,
                                priv->dev_node,
                                pvr_sync_debug_request_heading,
@@ -896,24 +856,25 @@ enum PVRSRV_ERROR_TAG pvr_sync_device_init(struct device *dev)
                goto err_out;
        }
 
-       pvr_sync_data.dev_cookie = priv->dev_node;
-       pvr_sync_data.fence_status_wq = priv->fence_status_wq;
-
-       pvr_sync_data.foreign_fence_context =
-               pvr_fence_context_create(pvr_sync_data.dev_cookie,
-                                        pvr_sync_data.fence_status_wq,
-                                        "foreign_sync");
-       if (!pvr_sync_data.foreign_fence_context) {
-               pr_err(FILE_NAME ": %s: Failed to create foreign sync context\n",
-                       __func__);
-               error = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto err_out;
+       /* Register the foreign sync context debug notifier on each device */
+       error = pvr_fence_context_register_dbg(
+                               &priv->sync_foreign_debug_notify_handle,
+                               priv->dev_node,
+                               pvr_sync_data.foreign_fence_context);
+       if (error != PVRSRV_OK) {
+               pr_err("%s: failed to register fence debug request callback (%s)\n",
+                      __func__, PVRSRVGetErrorString(error));
+               goto err_context_regdbg;
        }
 
 #if defined(NO_HARDWARE)
        INIT_LIST_HEAD(&pvr_timeline_active_list);
 #endif
 
+       return PVRSRV_OK;
+
+err_context_regdbg:
+       PVRSRVUnregisterDeviceDbgRequestNotify(priv->sync_debug_notify_handle);
 err_out:
        return error;
 }
@@ -923,8 +884,8 @@ void pvr_sync_device_deinit(struct device *dev)
        struct drm_device *ddev = dev_get_drvdata(dev);
        struct pvr_drm_private *priv = ddev->dev_private;
 
-       pvr_fence_context_destroy(pvr_sync_data.foreign_fence_context);
-       PVRSRVUnregisterDbgRequestNotify(priv->sync_debug_notify_handle);
+       PVRSRVUnregisterDeviceDbgRequestNotify(priv->sync_foreign_debug_notify_handle);
+       PVRSRVUnregisterDeviceDbgRequestNotify(priv->sync_debug_notify_handle);
 }
 
 enum PVRSRV_ERROR_TAG pvr_sync_fence_wait(void *fence, u32 timeout_in_ms)
@@ -967,10 +928,12 @@ enum PVRSRV_ERROR_TAG pvr_sync_fence_get(int fence_fd, void **fence_out)
        return PVRSRV_OK;
 }
 
-enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
-                                                   const char *fence_name,
-                                                   int *fence_fd_out,
-                                                   u64 *sync_pt_idx)
+enum PVRSRV_ERROR_TAG
+pvr_sync_sw_timeline_fence_create(struct _PVRSRV_DEVICE_NODE_ *pvrsrv_dev_node,
+                                 int timeline_fd,
+                                 const char *fence_name,
+                                 int *fence_fd_out,
+                                 u64 *sync_pt_idx)
 {
        enum PVRSRV_ERROR_TAG srv_err;
        struct pvr_sync_timeline *timeline;
@@ -978,6 +941,8 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
        struct sync_file *sync_file = NULL;
        int fd;
 
+       (void)(pvrsrv_dev_node);
+
        fd = get_unused_fd_flags(O_CLOEXEC);
        if (fd < 0)
                return PVRSRV_ERROR_UNABLE_TO_ADD_HANDLE;
@@ -988,6 +953,11 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
                srv_err = PVRSRV_ERROR_RESOURCE_UNAVAILABLE;
                goto err_put_fd;
        }
+       if (!timeline->is_sw) {
+               pvr_sync_timeline_fput(timeline);
+               srv_err = PVRSRV_ERROR_INVALID_PARAMS;
+               goto err_put_fd;
+       }
 
        fence = pvr_counting_fence_create(timeline->sw_fence_timeline, sync_pt_idx);
        pvr_sync_timeline_fput(timeline);
@@ -997,9 +967,10 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
        }
 
        sync_file = sync_file_create(fence);
+       dma_fence_put(fence);
        if (!sync_file) {
                srv_err = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto err_put_fence;
+               goto err_put_fd;
        }
 
        fd_install(fd, sync_file->file);
@@ -1008,8 +979,6 @@ enum PVRSRV_ERROR_TAG pvr_sync_sw_timeline_fence_create(int timeline_fd,
 
        return PVRSRV_OK;
 
-err_put_fence:
-       dma_fence_put(fence);
 err_put_fd:
        put_unused_fd(fd);
        return srv_err;
@@ -1083,15 +1052,17 @@ static void _dump_fence(struct dma_fence *fence,
                struct dma_fence_array *fence_array = to_dma_fence_array(fence);
                int i;
 
-               PVR_DUMPDEBUG_LOG(dump_debug_printf,
-                                 dump_debug_file,
-                                 "Fence: [%p] Sync Points:\n",
-                                 fence_array);
+               if (fence_array) {
+                       PVR_DUMPDEBUG_LOG(dump_debug_printf,
+                                         dump_debug_file,
+                                         "Fence: [%p] Sync Points:\n",
+                                         fence_array);
 
-               for (i = 0; i < fence_array->num_fences; i++)
-                       _dump_sync_point(fence_array->fences[i],
-                                        dump_debug_printf,
-                                        dump_debug_file);
+                       for (i = 0; i < fence_array->num_fences; i++)
+                               _dump_sync_point(fence_array->fences[i],
+                                                dump_debug_printf,
+                                                dump_debug_file);
+               }
 
        } else {
                _dump_sync_point(fence, dump_debug_printf, dump_debug_file);
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_common.c b/drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_common.c
new file mode 100644 (file)
index 0000000..60ba355
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * @File        pvr_sync_ioctl_common.c
+ * @Title       Kernel driver for Android's sync mechanism
+ * @Codingstyle LinuxKernel
+ * @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.
+ */
+
+#include <linux/slab.h>
+
+#include "pvr_drm.h"
+#include "pvr_sync_api.h"
+#include "pvr_sync_ioctl_common.h"
+
+/*
+ * The PVR Sync API is unusual in that some operations configure the
+ * timeline for use, and are no longer allowed once the timeline is
+ * in use. A locking mechanism, such as a read/write semaphore, would
+ * be one method of helping to ensure the API rules are followed, but
+ * this would add unnecessary overhead once the timeline has been
+ * configured, as read locks would continue to have to be taken after
+ * the timeline is in use. To avoid locks, two atomic variables are used,
+ * together with memory barriers. The in_setup variable indicates a "rename"
+ * or "force software only" ioctl is in progress. At most one of these two
+ * configuration ioctls can be in progress at any one time, and they can't
+ * overlap with any other Sync ioctl. The in_use variable indicates one
+ * of the other Sync ioctls has started. Once set, in_use stays set, and
+ * prevents any further configuration ioctls. Non-configuration ioctls
+ * are allowed to overlap.
+ * It is possible for a configuration and non-configuration ioctl to race,
+ * but at most one will be allowed to proceed, and perhaps neither.
+ * Given the intended usage of the API in user space, where the timeline
+ * is fully configured before being used, the race behaviour won't be
+ * an issue.
+ */
+
+struct pvr_sync_file_data {
+       atomic_t in_setup;
+       atomic_t in_use;
+       void *api_private;
+       bool is_sw;
+};
+
+static bool pvr_sync_set_in_use(struct pvr_sync_file_data *fdata)
+{
+       if (atomic_read(&fdata->in_use) < 2) {
+               atomic_set(&fdata->in_use, 1);
+               /* Ensure in_use change is visible before in_setup is read */
+               smp_mb();
+               if (atomic_read(&fdata->in_setup) != 0)
+                       return false;
+
+               atomic_set(&fdata->in_use, 2);
+       } else {
+               /* Ensure stale private data isn't read */
+               smp_rmb();
+       }
+
+       return true;
+}
+
+static bool pvr_sync_set_in_setup(struct pvr_sync_file_data *fdata)
+{
+       int in_setup;
+
+       in_setup = atomic_inc_return(&fdata->in_setup);
+       if (in_setup > 1 || atomic_read(&fdata->in_use) != 0) {
+               atomic_dec(&fdata->in_setup);
+               return false;
+       }
+
+       return true;
+}
+
+static inline void pvr_sync_reset_in_setup(struct pvr_sync_file_data *fdata)
+{
+       /*
+        * Ensure setup changes are visible before allowing other
+        * operations to proceed.
+        */
+       smp_mb__before_atomic();
+       atomic_dec(&fdata->in_setup);
+}
+
+void *pvr_sync_get_api_priv_common(struct file *file)
+{
+       if (file != NULL && pvr_sync_is_timeline(file)) {
+               struct pvr_sync_file_data *fdata = pvr_sync_get_private_data(file);
+
+               if (fdata != NULL && pvr_sync_set_in_use(fdata))
+                       return fdata->api_private;
+       }
+
+       return NULL;
+}
+
+int pvr_sync_open_common(void *connection_data, void *file_handle)
+{
+       void *data = NULL;
+       struct pvr_sync_file_data *fdata;
+       int err;
+
+       fdata = kzalloc(sizeof(*fdata), GFP_KERNEL);
+       if (!fdata)
+               return -ENOMEM;
+
+       atomic_set(&fdata->in_setup, 0);
+       atomic_set(&fdata->in_use, 0);
+
+       if (!pvr_sync_set_private_data(connection_data, fdata)) {
+               kfree(fdata);
+               return -EINVAL;
+       }
+
+       err = pvr_sync_api_init(file_handle, &data);
+       if (err)
+               kfree(fdata);
+       else
+               fdata->api_private = data;
+
+       return err;
+}
+
+int pvr_sync_close_common(void *connection_data)
+{
+       struct pvr_sync_file_data *fdata;
+
+       fdata = pvr_sync_connection_private_data(connection_data);
+       if (fdata) {
+               int err;
+
+               err = pvr_sync_api_deinit(fdata->api_private, fdata->is_sw);
+
+               kfree(fdata);
+
+               return err;
+       }
+
+       return 0;
+}
+
+static inline int pvr_sync_ioctl_rename(void *api_priv, void *arg)
+{
+       struct pvr_sync_rename_ioctl_data *data = arg;
+
+       return pvr_sync_api_rename(api_priv, data);
+}
+
+static inline int pvr_sync_ioctl_force_sw_only(struct pvr_sync_file_data *fdata)
+{
+       void *data = fdata->api_private;
+       int err;
+
+       err = pvr_sync_api_force_sw_only(fdata->api_private, &data);
+       if (!err) {
+               if (data != fdata->api_private)
+                       fdata->api_private = data;
+
+               fdata->is_sw = true;
+       }
+
+       return err;
+}
+
+static inline int pvr_sync_ioctl_sw_create_fence(void *api_priv, void *arg)
+{
+       struct pvr_sw_sync_create_fence_data *data = arg;
+
+       return pvr_sync_api_sw_create_fence(api_priv, data);
+}
+
+static inline int pvr_sync_ioctl_sw_inc(void *api_priv, void *arg)
+{
+       struct pvr_sw_timeline_advance_data *data = arg;
+
+       return pvr_sync_api_sw_inc(api_priv, data);
+}
+
+int pvr_sync_ioctl_common(struct file *file, unsigned int cmd, void *arg)
+{
+       int err = -ENOTTY;
+       struct pvr_sync_file_data *fdata;
+       bool in_setup;
+
+       fdata = pvr_sync_get_private_data(file);
+       if (!fdata)
+               return -EINVAL;
+
+       switch (cmd) {
+       case DRM_PVR_SYNC_RENAME_CMD:
+       case DRM_PVR_SYNC_FORCE_SW_ONLY_CMD:
+               if (!pvr_sync_set_in_setup(fdata))
+                       return -EBUSY;
+
+               in_setup = true;
+               break;
+       default:
+               if (!pvr_sync_set_in_use(fdata))
+                       return -EBUSY;
+
+               in_setup = false;
+               break;
+       }
+
+       if (in_setup) {
+               if (fdata->is_sw)
+                       err = -ENOTTY;
+               else
+                       switch (cmd) {
+                       case DRM_PVR_SYNC_RENAME_CMD:
+                               err = pvr_sync_ioctl_rename(fdata->api_private,
+                                                           arg);
+                               break;
+                       case DRM_PVR_SYNC_FORCE_SW_ONLY_CMD:
+                               err = pvr_sync_ioctl_force_sw_only(fdata);
+                               break;
+                       default:
+                               break;
+                       }
+       } else {
+               if (!fdata->is_sw)
+                       err = -ENOTTY;
+               else
+                       switch (cmd) {
+                       case DRM_PVR_SW_SYNC_CREATE_FENCE_CMD:
+                               err = pvr_sync_ioctl_sw_create_fence(fdata->api_private,
+                                                                    arg);
+                               break;
+                       case DRM_PVR_SW_SYNC_INC_CMD:
+                               err = pvr_sync_ioctl_sw_inc(fdata->api_private,
+                                                           arg);
+                               break;
+                       default:
+                               break;
+                       }
+       }
+
+       if (in_setup)
+               pvr_sync_reset_in_setup(fdata);
+
+       return err;
+}
@@ -1,5 +1,6 @@
 /*
- * @File
+ * @File        pvr_sync_ioctl_common.h
+ * @Title       Kernel driver for Android's sync mechanism
  * @Codingstyle LinuxKernel
  * @Copyright   Copyright (c) Imagination Technologies Ltd. All Rights Reserved
  * @License     Dual MIT/GPLv2
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef __DRM_NULLDISP_NETLINK_H__
-#define __DRM_NULLDISP_NETLINK_H__
+#ifndef _PVR_SYNC_IOCTL_COMMON_H
+#define _PVR_SYNC_IOCTL_COMMON_H
 
-#include <linux/types.h>
-#include <linux/version.h>
+struct file;
 
-typedef void (*nlpvrdpy_disconnect_cb)(void *data);
-typedef int (*nlpvrdpy_flipped_cb)(void *data);
-typedef int (*nlpvrdpy_copied_cb)(void *data);
+/* Functions provided by pvr_sync_ioctl_common */
 
-struct nlpvrdpy *nlpvrdpy_create(struct drm_device *dev,
-                                       nlpvrdpy_disconnect_cb disconnect_cb,
-                                       void *disconnect_cb_data,
-                                       nlpvrdpy_flipped_cb flipped_cb,
-                                       void *flipped_cb_data,
-                                       nlpvrdpy_copied_cb copied_cb,
-                                       void *copied_cb_data);
+int pvr_sync_open_common(void *connection_data, void *file_handle);
+int pvr_sync_close_common(void *connection_data);
+int pvr_sync_ioctl_common(struct file *file, unsigned int cmd, void *arg);
+void *pvr_sync_get_api_priv_common(struct file *file);
 
-void nlpvrdpy_destroy(struct nlpvrdpy *nlpvrdpy);
+struct pvr_sync_file_data;
 
-int nlpvrdpy_send_flip(struct nlpvrdpy *nlpvrdpy,
-                      struct drm_framebuffer *fb,
-                      struct drm_gem_object **objs);
+/* Functions required by pvr_sync_ioctl_common */
 
-int nlpvrdpy_send_copy(struct nlpvrdpy *nlpvrdpy,
-                      struct drm_framebuffer *fb,
-                      struct drm_gem_object **objs);
+bool pvr_sync_set_private_data(void *connection_data,
+                              struct pvr_sync_file_data *fdata);
 
-void nlpvrdpy_send_disconnect(struct nlpvrdpy *nlpvrdpy);
+struct pvr_sync_file_data *
+pvr_sync_connection_private_data(void *connection_data);
 
-int nlpvrdpy_register(void);
+struct pvr_sync_file_data *
+pvr_sync_get_private_data(struct file *file);
 
-int nlpvrdpy_unregister(void);
+bool pvr_sync_is_timeline(struct file *file);
 
-#endif /* __DRM_NULLDISP_NETLINK_H__ */
+#endif /* _PVR_SYNC_IOCTL_COMMON_H */
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_drm.c b/drivers/gpu/drm/img/img-rogue/services/server/env/linux/pvr_sync_ioctl_drm.c
new file mode 100644 (file)
index 0000000..423c8d3
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * @File        pvr_sync_ioctl_drm.c
+ * @Title       Kernel driver for Android's sync mechanism
+ * @Codingstyle LinuxKernel
+ * @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.
+ */
+
+#include "pvr_drv.h"
+#include "pvr_drm.h"
+#include "private_data.h"
+#include "env_connection.h"
+#include "pvr_sync_api.h"
+#include "pvr_sync_ioctl_common.h"
+#include "pvr_sync_ioctl_drm.h"
+
+bool pvr_sync_set_private_data(void *connection_data,
+                              struct pvr_sync_file_data *fdata)
+{
+       if (connection_data) {
+               ENV_CONNECTION_DATA *env_data;
+
+               env_data = PVRSRVConnectionPrivateData(connection_data);
+               if (env_data) {
+                       env_data->pvPvrSyncPrivateData = fdata;
+
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+struct pvr_sync_file_data *
+pvr_sync_connection_private_data(void *connection_data)
+{
+       if (connection_data) {
+               ENV_CONNECTION_DATA *env_data;
+
+               env_data = PVRSRVConnectionPrivateData(connection_data);
+
+               if (env_data)
+                       return env_data->pvPvrSyncPrivateData;
+       }
+
+       return NULL;
+}
+
+struct pvr_sync_file_data *
+pvr_sync_get_private_data(struct file *file)
+{
+       CONNECTION_DATA *connection_data = LinuxSyncConnectionFromFile(file);
+
+       return pvr_sync_connection_private_data(connection_data);
+}
+
+bool pvr_sync_is_timeline(struct file *file)
+{
+       return file->f_op == &pvr_drm_fops;
+}
+
+void *pvr_sync_get_api_priv(struct file *file)
+{
+       return pvr_sync_get_api_priv_common(file);
+}
+
+struct file *pvr_sync_get_file_struct(void *file_handle)
+{
+       if (file_handle) {
+               struct drm_file *file = file_handle;
+
+               return file->filp;
+       }
+
+       return NULL;
+}
+
+int pvr_sync_open(void *connection_data, struct drm_file *file)
+{
+       /*
+        * The file structure pointer (file->filp) may not have been
+        * initialised at this point, so pass down a pointer to the
+        * drm_file structure instead.
+        */
+       return pvr_sync_open_common(connection_data, file);
+}
+
+void pvr_sync_close(void *connection_data)
+{
+       int iErr = pvr_sync_close_common(connection_data);
+
+       if (iErr < 0)
+               pr_err("%s: ERROR (%d) returned by pvr_sync_close_common()\n",
+                      __func__, iErr);
+}
+
+
+int pvr_sync_rename_ioctl(struct drm_device __maybe_unused *dev,
+                         void *arg, struct drm_file *file)
+{
+       return pvr_sync_ioctl_common(file->filp,
+                                    DRM_PVR_SYNC_RENAME_CMD, arg);
+}
+
+int pvr_sync_force_sw_only_ioctl(struct drm_device __maybe_unused *dev,
+                                void *arg, struct drm_file *file)
+{
+       return pvr_sync_ioctl_common(file->filp,
+                                    DRM_PVR_SYNC_FORCE_SW_ONLY_CMD, arg);
+}
+
+int pvr_sw_sync_create_fence_ioctl(struct drm_device __maybe_unused *dev,
+                                  void *arg, struct drm_file *file)
+{
+       return pvr_sync_ioctl_common(file->filp,
+                                    DRM_PVR_SW_SYNC_CREATE_FENCE_CMD, arg);
+}
+
+int pvr_sw_sync_inc_ioctl(struct drm_device __maybe_unused *dev,
+                         void *arg, struct drm_file *file)
+{
+       return pvr_sync_ioctl_common(file->filp,
+                                    DRM_PVR_SW_SYNC_INC_CMD, arg);
+}
+
+int pvr_sync_ioctl_init(void)
+{
+       return 0;
+}
+
+void pvr_sync_ioctl_deinit(void)
+{
+}
@@ -1,5 +1,6 @@
 /*
- * @File
+ * @File        pvr_sync_ioctl_drm.h
+ * @Title       Kernel driver for Android's sync mechanism
  * @Codingstyle LinuxKernel
  * @Copyright   Copyright (c) Imagination Technologies Ltd. All Rights Reserved
  * @License     Dual MIT/GPLv2
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#if !defined(__DRM_NETLINK_GEM_H__)
-#define __DRM_NETLINK_GEM_H__
+#ifndef _PVR_SYNC_IOCTL_DRM_H
+#define _PVR_SYNC_IOCTL_DRM_H
 
-#include <linux/version.h>
+struct drm_device;
+struct drm_file;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0))
-struct file;
-struct vm_area_struct;
-#else
-#include <drm/drmP.h>
-#endif
+int pvr_sync_open(void *connection_data, struct drm_file *file);
+void pvr_sync_close(void *connection_data);
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
-#include <drm/drm_gem.h>
-#endif
+int pvr_sync_rename_ioctl(struct drm_device *dev, void *arg,
+                         struct drm_file *file);
+int pvr_sync_force_sw_only_ioctl(struct drm_device *dev, void *arg,
+                                struct drm_file *file);
+int pvr_sw_sync_create_fence_ioctl(struct drm_device *dev, void *arg,
+                                  struct drm_file *file);
+int pvr_sw_sync_inc_ioctl(struct drm_device *dev, void *arg,
+                         struct drm_file *file);
 
-int netlink_gem_mmap(struct file *file, struct vm_area_struct *vma);
-
-#endif /* !defined(__DRM_NETLINK_GEM_H__) */
+#endif /* _PVR_SYNC_IOCTL_DRM_H */
index c649488..aaca47f 100644 (file)
@@ -55,11 +55,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv_sync_km.h"
 #include "sync_checkpoint_external.h"
 
+/* included for the define PVRSRV_LINUX_DEV_INIT_ON_PROBE */
+#include "pvr_drm.h"
+
 #ifndef __pvrsrv_defined_struct_enum__
 
 /* sync_external.h */
 
-struct PVRSRV_CLIENT_SYNC_PRIM {
+struct PVRSRV_CLIENT_SYNC_PRIM_TAG {
        volatile __u32 *pui32LinAddr;
 };
 
@@ -72,7 +75,7 @@ struct PVRSRV_CLIENT_SYNC_PRIM_OP {
 
 #else /* __pvrsrv_defined_struct_enum__ */
 
-struct PVRSRV_CLIENT_SYNC_PRIM;
+struct PVRSRV_CLIENT_SYNC_PRIM_TAG;
 struct PVRSRV_CLIENT_SYNC_PRIM_OP;
 
 enum tag_img_bool;
@@ -82,7 +85,7 @@ enum tag_img_bool;
 struct _PMR_;
 struct _PVRSRV_DEVICE_NODE_;
 struct dma_buf;
-struct SYNC_PRIM_CONTEXT;
+struct SYNC_PRIM_CONTEXT_TAG;
 
 /* pvr_notifier.h */
 
@@ -97,13 +100,15 @@ void PVRSRVCheckStatus(void *hCmdCompCallerHandle);
 
 #define DEBUG_REQUEST_DC               0
 #define DEBUG_REQUEST_SYNCTRACKING     1
-#define DEBUG_REQUEST_SYS              2
-#define DEBUG_REQUEST_ANDROIDSYNC      3
-#define DEBUG_REQUEST_LINUXFENCE       4
-#define DEBUG_REQUEST_SYNCCHECKPOINT   5
-#define DEBUG_REQUEST_HTB              6
-#define DEBUG_REQUEST_APPHINT          7
-#define DEBUG_REQUEST_FALLBACKSYNC     8
+#define DEBUG_REQUEST_SRV              2
+#define DEBUG_REQUEST_SYS              3
+#define DEBUG_REQUEST_RGX              4
+#define DEBUG_REQUEST_ANDROIDSYNC      5
+#define DEBUG_REQUEST_LINUXFENCE       6
+#define DEBUG_REQUEST_SYNCCHECKPOINT   7
+#define DEBUG_REQUEST_HTB              8
+#define DEBUG_REQUEST_APPHINT          9
+#define DEBUG_REQUEST_FALLBACKSYNC     10
 
 #define DEBUG_REQUEST_VERBOSITY_LOW    0
 #define DEBUG_REQUEST_VERBOSITY_MEDIUM 1
@@ -121,12 +126,17 @@ typedef void (*PFN_DBGREQ_NOTIFY) (void *hDebugRequestHandle,
        void *pvDumpDebugFile);
 #define DBGNOTIFY_PFNS
 #endif
-enum PVRSRV_ERROR_TAG PVRSRVRegisterDbgRequestNotify(void **phNotify,
+enum PVRSRV_ERROR_TAG PVRSRVRegisterDeviceDbgRequestNotify(void **phNotify,
        struct _PVRSRV_DEVICE_NODE_ *psDevNode,
        PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
        __u32 ui32RequesterID,
        void *hDbgRequestHandle);
-enum PVRSRV_ERROR_TAG PVRSRVUnregisterDbgRequestNotify(void *hNotify);
+enum PVRSRV_ERROR_TAG PVRSRVUnregisterDeviceDbgRequestNotify(void *hNotify);
+enum PVRSRV_ERROR_TAG PVRSRVRegisterDriverDbgRequestNotify(void **phNotify,
+       PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+       __u32 ui32RequesterID,
+       void *hDbgRequestHandle);
+enum PVRSRV_ERROR_TAG PVRSRVUnregisterDriverDbgRequestNotify(void *hNotify);
 
 /* physmem_dmabuf.h */
 
@@ -141,14 +151,14 @@ enum PVRSRV_ERROR_TAG PVRSRVReleaseGlobalEventObjectKM(void *hGlobalEventObject)
 
 enum PVRSRV_ERROR_TAG SyncPrimContextCreate(
        struct _PVRSRV_DEVICE_NODE_ *psDevConnection,
-       struct SYNC_PRIM_CONTEXT **phSyncPrimContext);
-void SyncPrimContextDestroy(struct SYNC_PRIM_CONTEXT *hSyncPrimContext);
+       struct SYNC_PRIM_CONTEXT_TAG **phSyncPrimContext);
+void SyncPrimContextDestroy(struct SYNC_PRIM_CONTEXT_TAG *hSyncPrimContext);
 
-enum PVRSRV_ERROR_TAG SyncPrimAlloc(struct SYNC_PRIM_CONTEXT *hSyncPrimContext,
-       struct PVRSRV_CLIENT_SYNC_PRIM **ppsSync, const char *pszClassName);
-enum PVRSRV_ERROR_TAG SyncPrimFree(struct PVRSRV_CLIENT_SYNC_PRIM *psSync);
+enum PVRSRV_ERROR_TAG SyncPrimAlloc(struct SYNC_PRIM_CONTEXT_TAG *hSyncPrimContext,
+       struct PVRSRV_CLIENT_SYNC_PRIM_TAG **ppsSync, const char *pszClassName);
+enum PVRSRV_ERROR_TAG SyncPrimFree(struct PVRSRV_CLIENT_SYNC_PRIM_TAG *psSync);
 enum PVRSRV_ERROR_TAG SyncPrimGetFirmwareAddr(
-       struct PVRSRV_CLIENT_SYNC_PRIM *psSync,
+       struct PVRSRV_CLIENT_SYNC_PRIM_TAG *psSync,
        __u32 *sync_addr);
 
 /* osfunc.h */
@@ -166,7 +176,7 @@ enum PVRSRV_ERROR_TAG PVRSRVCommonDeviceCreate(void *pvOSDevice,
 enum PVRSRV_ERROR_TAG PVRSRVCommonDeviceDestroy(
        struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 const char *PVRSRVGetErrorString(enum PVRSRV_ERROR_TAG eError);
-#if defined(SUPPORT_FWLOAD_ON_PROBE)
+#if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_PROBE)
 enum PVRSRV_ERROR_TAG PVRSRVCommonDeviceInitialise(
        struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
 #endif
@@ -176,6 +186,7 @@ typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN)(PSYNC_CHECKPOINT_CO
 
 #ifndef CHECKPOINT_PFNS
 typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN)(
+               struct _PVRSRV_DEVICE_NODE_ *device,
                const char *fence_name,
                PVRSRV_TIMELINE timeline,
                PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
@@ -261,7 +272,20 @@ __u32 SyncCheckpointGetEnqueuedCount(PSYNC_CHECKPOINT psSyncCheckpoint);
 __u32 SyncCheckpointGetReferenceCount(PSYNC_CHECKPOINT psSyncCheckpoint);
 PVRSRV_TIMELINE SyncCheckpointGetTimeline(PSYNC_CHECKPOINT psSyncCheckpoint);
 const char *SyncCheckpointGetStateString(PSYNC_CHECKPOINT psSyncCheckpoint);
+#if defined(SUPPORT_NATIVE_FENCE_SYNC)
+struct _PVRSRV_DEVICE_NODE_ *SyncCheckpointGetAssociatedDevice(PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext);
+#endif
 
 #endif
 
+#if defined(SUPPORT_NATIVE_FENCE_SYNC) || defined(SUPPORT_BUFFER_SYNC)
+/*************************************************************************/ /*!
+@Function       NativeSyncGetFenceStatusWq
+@Description    Called to get the Foreign Fence status workqueue used in
+                Fence sync and Buffer sync.
+@Return         struct workqueue_struct ptr on success, NULL otherwise.
+*/ /**************************************************************************/
+struct workqueue_struct *NativeSyncGetFenceStatusWq(void);
+#endif
+
 #endif /* __SERVICES_KERNEL_CLIENT__ */
index fd2e00f..282ff5b 100644 (file)
@@ -132,19 +132,7 @@ PVRSRV_ERROR CacheOpQueue(CONNECTION_DATA *psConnection,
                                                IMG_DEVMEM_OFFSET_T *puiOffset,
                                                IMG_DEVMEM_SIZE_T *puiSize,
                                                PVRSRV_CACHE_OP *puiCacheOp,
-                                               IMG_UINT32 ui32OpTimeline,
-                                               IMG_UINT32 uiCurrentFenceSeqNum,
-                                               IMG_UINT32 *puiNextFenceSeqNum);
-
-/*
- * CacheOpFence()
- *
- * This is used for fencing for any client in-flight cache maintenance
- * operations that might have been deferred by the use of CacheOpQueue().
- * This should be called before any subsequent HW device kicks to ensure
- * device memory is coherent with the HW before the kick.
- */
-PVRSRV_ERROR CacheOpFence(RGXFWIF_DM eOpType, IMG_UINT32 ui32OpSeqNum);
+                                               IMG_UINT32 ui32OpTimeline);
 
 /*
  * CacheOpLog()
@@ -156,9 +144,8 @@ PVRSRV_ERROR CacheOpLog(PMR *psPMR,
                                                IMG_UINT64 uiAddress,
                                                IMG_DEVMEM_OFFSET_T uiOffset,
                                                IMG_DEVMEM_SIZE_T uiSize,
-                                               IMG_UINT64 ui64QueuedTimeMs,
-                                               IMG_UINT64 ui64ExecuteTimeMs,
-                                               IMG_UINT32 ui32NumRBF,
+                                               IMG_UINT64 ui64StartTime,
+                                               IMG_UINT64 ui64EndTime,
                                                PVRSRV_CACHE_OP uiCacheOp);
 
 #endif /* CACHE_KM_H */
index 4e1c646..d11a6ea 100644 (file)
@@ -117,9 +117,19 @@ typedef struct _CONNECTION_DATA_
 PVRSRV_ERROR PVRSRVCommonConnectionConnect(void **ppvPrivData, void *pvOSData);
 void PVRSRVCommonConnectionDisconnect(void *pvPrivData);
 
+/**************************************************************************/ /*!
+@Function       PVRSRVGetPurgeConnectionPid
+
+@Description    Returns PID associated with Connection currently being purged by
+                Cleanup Thread. If no Connection is purged 0 is returned.
+
+@Return         PID associated with currently purged connection or 0 if no
+                connection is being purged
+*/ /***************************************************************************/
 IMG_PID PVRSRVGetPurgeConnectionPid(void);
 
-void PVRSRVConnectionDebugNotify(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
+void PVRSRVConnectionDebugNotify(PVRSRV_DEVICE_NODE *psDevNode,
+                                 DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
                                  void *pvDumpDebugFile);
 
 #ifdef INLINE_IS_PRAGMA
index 289144e..e8b902f 100644 (file)
@@ -44,8 +44,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DEBUG_COMMON_H
 
 #include "pvrsrv_error.h"
+#include "device.h"
 
-PVRSRV_ERROR DebugCommonInit(void);
-void DebugCommonDeInit(void);
+PVRSRV_ERROR DebugCommonInitDriver(void);
+void DebugCommonDeInitDriver(void);
+
+PVRSRV_ERROR DebugCommonInitDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
+void DebugCommonDeInitDevice(PVRSRV_DEVICE_NODE *psDeviceNode);
 
 #endif /* DEBUG_COMMON_H */
index 1a92688..f5948d7 100644 (file)
@@ -124,33 +124,6 @@ typedef struct _DEVICE_MEMORY_INFO_
        DEVMEM_HEAP_BLUEPRINT   *psDeviceMemoryHeap;
 } DEVICE_MEMORY_INFO;
 
-
-typedef struct _PG_HANDLE_
-{
-       union
-       {
-               void *pvHandle;
-               IMG_UINT64 ui64Handle;
-       }u;
-       /* The allocation order is log2 value of the number of pages to allocate.
-        * As such this is a correspondingly small value. E.g, for order 4 we
-        * are talking 2^4 * PAGE_SIZE contiguous allocation.
-        * DevPxAlloc API does not need to support orders higher than 4.
-        */
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-       IMG_BYTE    uiOrder;    /* Order of the corresponding allocation */
-       IMG_BYTE    uiOSid;     /* OSid to use for allocation arena.
-                                * Connection-specific. */
-       IMG_BYTE    uiPad1,
-                   uiPad2;     /* Spare */
-#else
-       IMG_BYTE    uiOrder;    /* Order of the corresponding allocation */
-       IMG_BYTE    uiPad1,
-                   uiPad2,
-                   uiPad3;     /* Spare */
-#endif
-} PG_HANDLE;
-
 #define MMU_BAD_PHYS_ADDR (0xbadbad00badULL)
 #define DUMMY_PAGE     ("DUMMY_PAGE")
 #define DEV_ZERO_PAGE  ("DEV_ZERO_PAGE")
@@ -208,35 +181,78 @@ typedef enum _PVRSRV_DEVICE_DEBUG_DUMP_STATUS_
        PVRSRV_DEVICE_DEBUG_DUMP_CAPTURE
 } PVRSRV_DEVICE_DEBUG_DUMP_STATUS;
 
-typedef struct _MMU_PX_SETUP_
+#ifndef DI_GROUP_DEFINED
+#define DI_GROUP_DEFINED
+typedef struct DI_GROUP DI_GROUP;
+#endif
+#ifndef DI_ENTRY_DEFINED
+#define DI_ENTRY_DEFINED
+typedef struct DI_ENTRY DI_ENTRY;
+#endif
+
+typedef struct _PVRSRV_DEVICE_DEBUG_INFO_
 {
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-       PVRSRV_ERROR (*pfnDevPxAllocGPV)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, size_t uiSize,
-                                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                                       IMG_UINT32 ui32OSid, IMG_PID uiPid);
+       DI_GROUP *psGroup;
+       DI_ENTRY *psDumpDebugEntry;
+#ifdef SUPPORT_RGX
+       DI_ENTRY *psFWTraceEntry;
+#ifdef SUPPORT_FIRMWARE_GCOV
+       DI_ENTRY *psFWGCOVEntry;
+#endif
+       DI_ENTRY *psFWMappingsEntry;
+#if defined(SUPPORT_VALIDATION) || defined(SUPPORT_RISCV_GDB)
+       DI_ENTRY *psRiscvDmiDIEntry;
+       IMG_UINT64 ui64RiscvDmi;
 #endif
-       PVRSRV_ERROR (*pfnDevPxAlloc)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, size_t uiSize,
-                                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                                       IMG_PID uiPid);
+#endif /* SUPPORT_RGX */
+#ifdef SUPPORT_VALIDATION
+       DI_ENTRY *psRGXRegsEntry;
+#endif /* SUPPORT_VALIDATION */
+#ifdef SUPPORT_POWER_VALIDATION_VIA_DEBUGFS
+       DI_ENTRY *psPowMonEntry;
+#endif
+#ifdef SUPPORT_POWER_SAMPLING_VIA_DEBUGFS
+       DI_ENTRY *psPowerDataEntry;
+#endif
+} PVRSRV_DEVICE_DEBUG_INFO;
 
-       void (*pfnDevPxFree)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, PG_HANDLE *psMemHandle);
+#if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+#define RGX_LISR_INIT                                                  (0U)
+#define RGX_LISR_DEVICE_NOT_POWERED                            (1U)
+#define RGX_LISR_NOT_TRIGGERED_BY_HW                   (2U)
+#define RGX_LISR_FW_IRQ_COUNTER_NOT_UPDATED            (3U)
+#define RGX_LISR_PROCESSED                                             (4U)
 
-       PVRSRV_ERROR (*pfnDevPxMap)(struct _PVRSRV_DEVICE_NODE_ *psDevNode, PG_HANDLE *pshMemHandle,
-                                                               size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
-                                                               void **pvPtr);
+typedef IMG_UINT32 LISR_STATUS;
 
-       void (*pfnDevPxUnMap)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-                                                 PG_HANDLE *psMemHandle, void *pvPtr);
+typedef struct _LISR_EXECUTION_INFO_
+{
+       /* status of last LISR invocation */
+       LISR_STATUS ui32Status;
 
-       PVRSRV_ERROR (*pfnDevPxClean)(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-                                                               PG_HANDLE *pshMemHandle,
-                                                               IMG_UINT32 uiOffset,
-                                                               IMG_UINT32 uiLength);
+       /* snapshot from the last LISR invocation */
+#if defined(RGX_FW_IRQ_OS_COUNTERS)
+       IMG_UINT32 aui32InterruptCountSnapshot[RGX_NUM_OS_SUPPORTED];
+#else
+       IMG_UINT32 aui32InterruptCountSnapshot[RGXFW_THREAD_NUM];
+#endif
 
-       IMG_UINT32 uiMMUPxLog2AllocGran;
+       /* time of the last LISR invocation */
+       IMG_UINT64 ui64Clockns;
+} LISR_EXECUTION_INFO;
 
-       RA_ARENA *psPxRA;
-} MMU_PX_SETUP;
+#define UPDATE_LISR_DBG_STATUS(status)         psDeviceNode->sLISRExecutionInfo.ui32Status = (status)
+#define UPDATE_LISR_DBG_SNAPSHOT(idx, val)     psDeviceNode->sLISRExecutionInfo.aui32InterruptCountSnapshot[idx] = (val)
+#define UPDATE_LISR_DBG_TIMESTAMP()                    psDeviceNode->sLISRExecutionInfo.ui64Clockns = OSClockns64()
+#define UPDATE_LISR_DBG_COUNTER()                      psDeviceNode->ui64nLISR++
+#define UPDATE_MISR_DBG_COUNTER()                      psDeviceNode->ui64nMISR++
+#else
+#define UPDATE_LISR_DBG_STATUS(status)
+#define UPDATE_LISR_DBG_SNAPSHOT(idx, val)
+#define UPDATE_LISR_DBG_TIMESTAMP()
+#define UPDATE_LISR_DBG_COUNTER()
+#define UPDATE_MISR_DBG_COUNTER()
+#endif /* defined(PVRSRV_DEBUG_LISR_EXECUTION) */
 
 typedef struct _PVRSRV_DEVICE_NODE_
 {
@@ -256,7 +272,7 @@ typedef struct _PVRSRV_DEVICE_NODE_
        /* Device specific MMU firmware attributes, used only in some devices */
        MMU_DEVICEATTRIBS      *psFirmwareMMUDevAttrs;
 
-       MMU_PX_SETUP           sDevMMUPxSetup;
+       PHYS_HEAP              *psMMUPhysHeap;
 
        /* lock for power state transitions */
        POS_LOCK                                hPowerLock;
@@ -362,8 +378,6 @@ typedef struct _PVRSRV_DEVICE_NODE_
 #if defined(SUPPORT_GPUVIRT_VALIDATION)
        RA_ARENA                *psOSSharedArena;
        RA_ARENA                                *psOSidSubArena[GPUVIRT_VALIDATION_NUM_OS];
-       /* Number of supported OSid for this device node given available memory */
-       IMG_UINT32              ui32NumOSId;
 #endif
 
        /* FW_MAIN, FW_CONFIG and FW_GUEST heaps. Should be part of registered heaps? */
@@ -379,24 +393,18 @@ typedef struct _PVRSRV_DEVICE_NODE_
         * the PHYS_HEAP_CONFIG data from the platform's system layer at device
         * creation time.
         *
-        * The first entry (apsPhysHeap[PVRSRV_PHYS_HEAP_GPU_LOCAL]) will be used for allocations
-        *  where the phys heap hint CPU_LOCAL flag is not set. Normally this will be an LMA heap
-        *  (but the device configuration could specify a UMA heap here, if desired)
-        * The second entry (apsPhysHeap[PVRSRV_PHYS_HEAP_CPU_LOCAL]) will be used for allocations
-        *  where the phys heap hint CPU_LOCAL flag is set. Normally this will be a UMA heap
-        *  (but the configuration could specify an LMA heap here, if desired)
-        * The third entry (apsPhysHeap[PVRSRV_PHYS_HEAP_FW_MAIN]) will be used for allocations
-        *  where the memalloc flags phys heap hint is MAIN,CONFIG or RAW; this is used when virtualization is enabled
-        * The device configuration will always specify two physical heap IDs - in the event of the device
-        *  only using one physical heap, both of these IDs will be the same, and hence both pointers below
-        *  will also be the same; when virtualization is enabled the device configuration specifies
-        *  three physical heap IDs, the last being for PVRSRV_PHYS_HEAP_FW_MAIN allocations
+        * Contains PVRSRV_PHYS_HEAP_LAST entries for all the possible physical heaps allowed in the design.
+        * It allows the system layer PhysHeaps for the device to be identified for use in creating new PMRs.
+        * See PhysHeapCreatePMR()
         */
        PHYS_HEAP                               *apsPhysHeap[PVRSRV_PHYS_HEAP_LAST];
+       IMG_UINT32                              ui32UserAllocHeapCount;
 
-       /* RA reserved for storing the MMU mappings of firmware.
-        * The memory backing up this RA must persist between driver or OS reboots */
-       RA_ARENA                                *psFwMMUReservedMemArena;
+#if defined(SUPPORT_AUTOVZ)
+       /* Phys Heap reserved for storing the MMU mappings of firmware.
+        * The memory backing up this Phys Heap must persist between driver or OS reboots */
+       PHYS_HEAP               *psFwMMUReservedPhysHeap;
+#endif
 
        /* Flag indicating if the firmware has been initialised during the
         * 1st boot of the Host driver according to the AutoVz life-cycle. */
@@ -415,10 +423,6 @@ typedef struct _PVRSRV_DEVICE_NODE_
        AllocUFOBlockCallback   pfnAllocUFOBlock;       /*!< Callback for allocation of a block of UFO memory */
        FreeUFOBlockCallback    pfnFreeUFOBlock;        /*!< Callback for freeing of a block of UFO memory */
 
-       IMG_HANDLE                              hSyncServerNotify;
-       POS_LOCK                                hSyncServerListLock;
-       DLLIST_NODE                             sSyncServerSyncsList;
-
        IMG_HANDLE                              hSyncServerRecordNotify;
        POS_LOCK                                hSyncServerRecordLock;
        IMG_UINT32                              ui32SyncServerRecordCount;
@@ -449,9 +453,8 @@ typedef struct _PVRSRV_DEVICE_NODE_
 
        IMG_HANDLE                              hCmdCompNotify;
        IMG_HANDLE                              hDbgReqNotify;
-       IMG_HANDLE                              hHtbDbgReqNotify;
        IMG_HANDLE                              hAppHintDbgReqNotify;
-       IMG_HANDLE                              hThreadsDbgReqNotify;
+       IMG_HANDLE                              hPhysHeapDbgReqNotify;
 
        PVRSRV_DEF_PAGE                 sDummyPage;
        PVRSRV_DEF_PAGE                 sDevZeroPage;
@@ -496,15 +499,20 @@ typedef struct _PVRSRV_DEVICE_NODE_
 #endif
 
 #if defined(SUPPORT_VALIDATION)
-       POS_LOCK                                hValidationLock;
+       POS_LOCK                        hValidationLock;
 #endif
 
+       /* Members for linking which connections are open on this device */
        POS_LOCK                hConnectionsLock;    /*!< Lock protecting sConnections */
        DLLIST_NODE             sConnections;        /*!< The list of currently active connection objects for this device node */
+
 #if defined(PVRSRV_DEBUG_LISR_EXECUTION)
+       LISR_EXECUTION_INFO     sLISRExecutionInfo;  /*!< Information about the last execution of the LISR */
        IMG_UINT64              ui64nLISR;           /*!< Number of LISR calls seen */
        IMG_UINT64              ui64nMISR;           /*!< Number of MISR calls made */
 #endif
+
+       PVRSRV_DEVICE_DEBUG_INFO sDebugInfo;
 } PVRSRV_DEVICE_NODE;
 
 /*
index a09050f..8e7ca59 100644 (file)
@@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv_error.h"
 #include "rgxmem.h"
 #include "devicemem_utils.h"
+#include "connection_server.h"
 
 PVRSRV_ERROR DevicememHistoryInitKM(void);
 
@@ -71,7 +72,9 @@ PVRSRV_ERROR DevicememHistoryUnmapKM(PMR *psPMR,
                                                        IMG_UINT32 ui32AllocationIndex,
                                                        IMG_UINT32 *pui32AllocationIndexOut);
 
-PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+PVRSRV_ERROR DevicememHistoryMapVRangeKM(CONNECTION_DATA *psConnection,
+                                                       PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                        IMG_UINT32 ui32StartPage,
                                                        IMG_UINT32 ui32NumPages,
                                                        IMG_DEVMEM_SIZE_T uiAllocSize,
@@ -80,7 +83,9 @@ PVRSRV_ERROR DevicememHistoryMapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                        IMG_UINT32 ui32AllocationIndex,
                                                        IMG_UINT32 *ui32AllocationIndexOut);
 
-PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(IMG_DEV_VIRTADDR sBaseDevVAddr,
+PVRSRV_ERROR DevicememHistoryUnmapVRangeKM(CONNECTION_DATA *psConnection,
+                                                       PVRSRV_DEVICE_NODE *psDeviceNode,
+                                                       IMG_DEV_VIRTADDR sBaseDevVAddr,
                                                        IMG_UINT32 ui32StartPage,
                                                        IMG_UINT32 ui32NumPages,
                                                        IMG_DEVMEM_SIZE_T uiAllocSize,
index d4c7f21..30a2b2e 100644 (file)
@@ -479,21 +479,6 @@ IMG_UINT32
 DevmemIntMMUContextID(DEVMEMINT_CTX *psDevMemContext);
 
 PVRSRV_ERROR
-DevmemIntPDumpBitmap(CONNECTION_DATA * psConnection,
-                     PVRSRV_DEVICE_NODE *psDeviceNode,
-                     IMG_CHAR *pszFileName,
-                     IMG_UINT32 ui32FileOffset,
-                     IMG_UINT32 ui32Width,
-                     IMG_UINT32 ui32Height,
-                     IMG_UINT32 ui32StrideInBytes,
-                     IMG_DEV_VIRTADDR sDevBaseAddr,
-                     DEVMEMINT_CTX *psDevMemContext,
-                     IMG_UINT32 ui32Size,
-                     PDUMP_PIXEL_FORMAT ePixelFormat,
-                     IMG_UINT32 ui32AddrMode,
-                     IMG_UINT32 ui32PDumpFlags);
-
-PVRSRV_ERROR
 DevmemIntPDumpImageDescriptor(CONNECTION_DATA * psConnection,
                               PVRSRV_DEVICE_NODE *psDeviceNode,
                               DEVMEMINT_CTX *psDevMemContext,
@@ -551,40 +536,6 @@ DevmemIntPDumpSaveToFileVirtual(DEVMEMINT_CTX *psDevmemCtx,
 }
 
 #ifdef INLINE_IS_PRAGMA
-#pragma inline(DevmemIntPDumpBitmap)
-#endif
-static INLINE PVRSRV_ERROR
-DevmemIntPDumpBitmap(CONNECTION_DATA * psConnection,
-                     PVRSRV_DEVICE_NODE *psDeviceNode,
-                     IMG_CHAR *pszFileName,
-                     IMG_UINT32 ui32FileOffset,
-                     IMG_UINT32 ui32Width,
-                     IMG_UINT32 ui32Height,
-                     IMG_UINT32 ui32StrideInBytes,
-                     IMG_DEV_VIRTADDR sDevBaseAddr,
-                     DEVMEMINT_CTX *psDevMemContext,
-                     IMG_UINT32 ui32Size,
-                     PDUMP_PIXEL_FORMAT ePixelFormat,
-                     IMG_UINT32 ui32AddrMode,
-                     IMG_UINT32 ui32PDumpFlags)
-{
-       PVR_UNREFERENCED_PARAMETER(psConnection);
-       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
-       PVR_UNREFERENCED_PARAMETER(pszFileName);
-       PVR_UNREFERENCED_PARAMETER(ui32FileOffset);
-       PVR_UNREFERENCED_PARAMETER(ui32Width);
-       PVR_UNREFERENCED_PARAMETER(ui32Height);
-       PVR_UNREFERENCED_PARAMETER(ui32StrideInBytes);
-       PVR_UNREFERENCED_PARAMETER(sDevBaseAddr);
-       PVR_UNREFERENCED_PARAMETER(psDevMemContext);
-       PVR_UNREFERENCED_PARAMETER(ui32Size);
-       PVR_UNREFERENCED_PARAMETER(ePixelFormat);
-       PVR_UNREFERENCED_PARAMETER(ui32AddrMode);
-       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
-       return PVRSRV_OK;
-}
-
-#ifdef INLINE_IS_PRAGMA
 #pragma inline(DevmemIntPDumpImageDescriptor)
 #endif
 static INLINE PVRSRV_ERROR
index 4b54753..ad85c07 100644 (file)
@@ -68,11 +68,7 @@ static INLINE PVRSRV_ERROR DevmemCPUCacheMode(PVRSRV_DEVICE_NODE *psDeviceNode,
                        break;
 
                case PVRSRV_MEMALLOCFLAG_CPU_CACHE_INCOHERENT:
-#if defined(SAFETY_CRITICAL_BUILD)
-                       ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC;
-#else
                        ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
-#endif
                        break;
 
                case PVRSRV_MEMALLOCFLAG_CPU_CACHE_COHERENT:
@@ -90,11 +86,7 @@ static INLINE PVRSRV_ERROR DevmemCPUCacheMode(PVRSRV_DEVICE_NODE *psDeviceNode,
                        }
                        else
                        {
-#if defined(SAFETY_CRITICAL_BUILD)
-                               ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_UNCACHED_WC;
-#else
                                ui32Ret = PVRSRV_MEMALLOCFLAG_CPU_CACHED;
-#endif
                        }
                        break;
 
@@ -136,11 +128,7 @@ static INLINE PVRSRV_ERROR DevmemDeviceCacheMode(PVRSRV_DEVICE_NODE *psDeviceNod
                        break;
 
                case PVRSRV_MEMALLOCFLAG_GPU_CACHE_INCOHERENT:
-#if defined(SAFETY_CRITICAL_BUILD)
-                       ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED_WC;
-#else
                        ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
-#endif
                        break;
 
                case PVRSRV_MEMALLOCFLAG_GPU_CACHE_COHERENT:
@@ -158,11 +146,7 @@ static INLINE PVRSRV_ERROR DevmemDeviceCacheMode(PVRSRV_DEVICE_NODE *psDeviceNod
                        }
                        else
                        {
-#if defined(SAFETY_CRITICAL_BUILD)
-                               ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_UNCACHED_WC;
-#else
                                ui32Ret = PVRSRV_MEMALLOCFLAG_GPU_CACHED;
-#endif
                        }
                        break;
 
index c2589d5..a101787 100644 (file)
@@ -49,8 +49,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DI_START_TOKEN ((void *) 1)
 
 /* This is a public handle to an entry. */
+#ifndef DI_GROUP_DEFINED
+#define DI_GROUP_DEFINED
 typedef struct DI_GROUP DI_GROUP;
+#endif
+#ifndef DI_ENTRY_DEFINED
+#define DI_ENTRY_DEFINED
 typedef struct DI_ENTRY DI_ENTRY;
+#endif
 typedef struct OSDI_IMPL_ENTRY OSDI_IMPL_ENTRY;
 
 /*! Debug Info entries types. */
@@ -220,9 +226,11 @@ typedef struct DI_ITERATOR_CB
     DI_PFN_SEEK pfnSeek;   /*!< Sets data pointer in an entry. */
     DI_PFN_READ pfnRead;   /*!< Reads data from an entry. */
 
-    /* Optional writing to entry interface. */
+    /* Optional writing to entry interface. Null terminated. */
 
     DI_PFN_WRITE pfnWrite; /*!< Performs write operation on an entry. */
+    IMG_UINT32   ui32WriteLenMax; /*!< Maximum char length of entry
+                                       accepted for write. Includes \0 */
 } DI_ITERATOR_CB;
 
 #endif /* DI_COMMON_H */
index a28053f..a68894b 100644 (file)
@@ -43,12 +43,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #ifndef DI_SERVER_H
 #define DI_SERVER_H
 
-/* this inculde caused the redefine error in kernel 5.15, since kernel 5.10 not 
- * include stdarg.h and has no stdarg.h at all, but it does in kernel 5.15 
- */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
+#if defined(__linux__)
+ #include <linux/version.h>
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+  #include <linux/stdarg.h>
+ #else
+  #include <stdarg.h>
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+#else
+ #include <stdarg.h>
+#endif /* __linux__ */
 
 #include "di_common.h"
 #include "pvrsrv_error.h"
@@ -155,6 +160,19 @@ void DIDestroyGroup(DI_GROUP *psGroup);
  */
 void *DIGetPrivData(const OSDI_IMPL_ENTRY *psEntry);
 
+/*! @Function DIWrite
+ *
+ * @Description
+ * Writes the binary data of the DI entry to the output sync, whatever that may
+ * be for the DI implementation.
+ *
+ * @Input psEntry pointer to OSDI_IMPL_ENTRY object
+ * @Input pvData data
+ * @Input uiSize pvData length
+ */
+void DIWrite(const OSDI_IMPL_ENTRY *psEntry, const void *pvData,
+             IMG_UINT32 uiSize);
+
 /*! @Function DIPrintf
  *
  * @Description
@@ -166,6 +184,19 @@ void *DIGetPrivData(const OSDI_IMPL_ENTRY *psEntry);
 void DIPrintf(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszFmt, ...)
        __printf(2, 3);
 
+/*! @Function DIVPrintf
+ *
+ * @Description
+ * Prints formatted string to the DI entry. Equivalent to DIPrintf but takes
+ * va_list instead of a variable number of arguments.
+ *
+ * @Input psEntry pointer to OSDI_IMPL_ENTRY object
+ * @Input pszFmt NUL-terminated format string
+ * @Input pArgs vs_list object
+ */
+void DIVPrintf(const OSDI_IMPL_ENTRY *psEntry, const IMG_CHAR *pszFmt,
+               va_list pArgs);
+
 /*! @Function DIPrintf
  *
  * @Description
index d9db371..92946b6 100644 (file)
@@ -99,7 +99,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * Given a handle for a resource of type eType, return the pointer to the
  * resource.
  *
- * PVRSRV_ERROR PVRSRVLookuSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase,
  *      void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType,
  *      IMH_HANDLE hAncestor);
  *
@@ -152,7 +152,6 @@ typedef struct _PROCESS_HANDLE_BASE_
 {
        PVRSRV_HANDLE_BASE *psHandleBase;
        ATOMIC_T iRefCount;
-
 } PROCESS_HANDLE_BASE;
 
 extern PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
@@ -176,9 +175,12 @@ PVRSRV_ERROR PVRSRVLookupHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, void **ppvDa
 
 PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, void **ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType, IMG_HANDLE hAncestor);
 
-PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
-PVRSRV_ERROR PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
-PVRSRV_ERROR PVRSRVReleaseHandleStagedUnlock(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+void PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+void PVRSRVReleaseHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+
+PVRSRV_ERROR PVRSRVDestroyHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+PVRSRV_ERROR PVRSRVDestroyHandleUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+PVRSRV_ERROR PVRSRVDestroyHandleStagedUnlocked(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
 
 PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase);
 
@@ -195,6 +197,9 @@ PVRSRV_ERROR PVRSRVHandleDeInit(void);
 
 PVRSRV_HANDLE_BASE *PVRSRVRetrieveProcessHandleBase(void);
 
+PVRSRV_ERROR PVRSRVAcquireProcessHandleBase(IMG_PID uiPid, PROCESS_HANDLE_BASE **ppsBase);
+PVRSRV_ERROR PVRSRVReleaseProcessHandleBase(PROCESS_HANDLE_BASE *psBase, IMG_PID uiPid, IMG_UINT64 ui64MaxBridgeTime);
+
 void LockHandle(PVRSRV_HANDLE_BASE *psBase);
 void UnlockHandle(PVRSRV_HANDLE_BASE *psBase);
 
index 4e3a9d9..795e206 100644 (file)
@@ -63,6 +63,9 @@ HANDLETYPE(RGX_SERVER_TQ_TDM_CONTEXT)
 HANDLETYPE(RGX_SERVER_COMPUTE_CONTEXT)
 HANDLETYPE(RGX_SERVER_RAY_CONTEXT)
 HANDLETYPE(RGX_SERVER_KICKSYNC_CONTEXT)
+#if defined(PVR_TESTING_UTILS) && defined(SUPPORT_VALIDATION)
+HANDLETYPE(RGX_SERVER_GPUMAP_CONTEXT)
+#endif
 HANDLETYPE(SYNC_PRIMITIVE_BLOCK)
 HANDLETYPE(SYNC_RECORD_HANDLE)
 HANDLETYPE(PVRSRV_TIMELINE_SERVER)
index 88dd182..c30556c 100644 (file)
@@ -74,29 +74,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv.h"
 #include "htbuffer.h"
 
-
-/************************************************************************/ /*!
- @Function      HTBIDeviceCreate
- @Description   Initialisation actions for HTB at device creation.
-
- @Input         psDeviceNode    Reference to the device node in context
-
- @Return        eError          Internal services call returned eError error
-                                number
-*/ /**************************************************************************/
-PVRSRV_ERROR
-HTBDeviceCreate(PVRSRV_DEVICE_NODE *psDeviceNode);
-
-/************************************************************************/ /*!
- @Function      HTBIDeviceDestroy
- @Description   De-initialisation actions for HTB at device destruction.
-
- @Input         psDeviceNode    Reference to the device node in context
-
-*/ /**************************************************************************/
-void
-HTBDeviceDestroy(PVRSRV_DEVICE_NODE *psDeviceNode);
-
 /************************************************************************/ /*!
  @Function      HTBInit
  @Description   Initialise the Host Trace Buffer and allocate all resources
index f3cd5ae..2e2c29a 100644 (file)
@@ -46,9 +46,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /* instruct QAC to ignore warnings about the following custom formatted macros */
 /* PRQA S 0881,3410 ++ */
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
+
+#if defined(__linux__)
+ #include <linux/version.h>
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+  #include <linux/stdarg.h>
+ #else
+  #include <stdarg.h>
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+#else
+ #include <stdarg.h>
+#endif /* __linux__ */
 
 #include "img_types.h"
 #include "device.h"
index 1a745e4..a84fa69 100644 (file)
@@ -555,6 +555,22 @@ PVRSRV_ERROR
 MMU_AcquireBaseAddr(MMU_CONTEXT *psMMUContext, IMG_DEV_PHYADDR *psPhysAddr);
 
 /*************************************************************************/ /*!
+@Function       MMU_AcquireCPUBaseAddr
+
+@Description    Acquire the CPU Virtual Address of the base level MMU object
+
+@Input          psMMUContext            MMU context to operate on
+
+@Output         ppvCPUVAddr             CPU Virtual Address of the base level
+                                        MMU object
+
+@Return         PVRSRV_OK if successful
+*/
+/*****************************************************************************/
+PVRSRV_ERROR
+MMU_AcquireCPUBaseAddr(MMU_CONTEXT *psMMUContext, void **ppvCPUVAddr);
+
+/*************************************************************************/ /*!
 @Function       MMU_ReleaseBaseAddr
 
 @Description    Release the device physical address of the base level MMU object
index b7b05b3..a4d77e3 100644 (file)
@@ -48,26 +48,32 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "km_apphint.h"
 #include "km_apphint_defs.h"
 
+/* Supplied to SrvInitParamGetXXX() functions when the param/AppHint is
+ * applicable to all devices and not a specific device. Typically used
+ * for server-wide build and module AppHints.
+ */
+#define INITPARAM_NO_DEVICE (NULL)
+
 #define SrvInitParamOpen() NULL
 #define SrvInitParamClose(pvState) ((void)(pvState))
 
-#define SrvInitParamGetBOOL(state, name, value) \
-       ((void) pvr_apphint_get_bool(APPHINT_ID_ ## name, &value))
+#define SrvInitParamGetBOOL(device, state, name, value) \
+       ((void) pvr_apphint_get_bool(device, APPHINT_ID_ ## name, &value))
 
-#define SrvInitParamGetUINT32(state, name, value) \
-       ((void) pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value))
+#define SrvInitParamGetUINT32(device, state, name, value) \
+       ((void) pvr_apphint_get_uint32(device, APPHINT_ID_ ## name, &value))
 
-#define SrvInitParamGetUINT64(state, name, value) \
-       ((void) pvr_apphint_get_uint64(APPHINT_ID_ ## name, &value))
+#define SrvInitParamGetUINT64(device, state, name, value) \
+       ((void) pvr_apphint_get_uint64(device, APPHINT_ID_ ## name, &value))
 
-#define SrvInitParamGetSTRING(state, name, buffer, size) \
-       ((void) pvr_apphint_get_string(APPHINT_ID_ ## name, buffer, size))
+#define SrvInitParamGetSTRING(device, state, name, buffer, size) \
+       ((void) pvr_apphint_get_string(device, APPHINT_ID_ ## name, buffer, size))
 
-#define SrvInitParamGetUINT32BitField(state, name, value) \
-       ((void) pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value))
+#define SrvInitParamGetUINT32BitField(device, state, name, value) \
+       ((void) pvr_apphint_get_uint32(device, APPHINT_ID_ ## name, &value))
 
-#define SrvInitParamGetUINT32List(state, name, value) \
-       ((void) pvr_apphint_get_uint32(APPHINT_ID_ ## name, &value))
+#define SrvInitParamGetUINT32List(device, state, name, value) \
+       ((void) pvr_apphint_get_uint32(device, APPHINT_ID_ ## name, &value))
 
 #else  /* defined(__linux__) && defined(__KERNEL__) */
 
@@ -135,15 +141,15 @@ void _SrvInitParamGetBOOL(
 
 /*! Get the BOOL value for parameter 'name' from the parameter resource store
  *  attached to 'state'. */
-#define SrvInitParamGetBOOL(state, name, value) \
+#define SrvInitParamGetBOOL(device, state, name, value) \
                _SrvInitParamGetBOOL(state, # name, & __SrvInitParam_ ## name, &(value))
 
 /*! Initialise FLAG type parameter identified by 'name'. */
-#define SrvInitParamInitFLAG(name, defval, dummy) \
+#define SrvInitParamInitFLAG(name, defval, unused) \
        static const IMG_BOOL __SrvInitParam_ ## name = defval;
 
 /*! Initialise BOOL type parameter identified by 'name'. */
-#define SrvInitParamInitBOOL(name, defval, dummy) \
+#define SrvInitParamInitBOOL(name, defval, unused) \
        static const IMG_BOOL __SrvInitParam_ ## name = defval;
 
 /*************************************************************************/ /*!
@@ -171,15 +177,15 @@ void _SrvInitParamGetUINT32(
 
 /*! Get the UINT32 value for parameter 'name' from the parameter resource store
  *  attached to 'state'. */
-#define SrvInitParamGetUINT32(state, name, value) \
+#define SrvInitParamGetUINT32(device, state, name, value) \
                _SrvInitParamGetUINT32(state, # name, & __SrvInitParam_ ## name, &(value))
 
 /*! Initialise UINT32 type parameter identified by 'name'. */
-#define SrvInitParamInitUINT32(name, defval, dummy) \
+#define SrvInitParamInitUINT32(name, defval, unused) \
        static const IMG_UINT32 __SrvInitParam_ ## name = defval;
 
 /*! Initialise UINT64 type parameter identified by 'name'. */
-#define SrvInitParamInitUINT64(name, defval, dummy) \
+#define SrvInitParamInitUINT64(name, defval, unused) \
        static const IMG_UINT64 __SrvInitParam_ ## name = defval;
 
 /*! @cond Doxygen_Suppress */
@@ -227,7 +233,7 @@ void _SrvInitParamGetUINT32BitField(
 
 /*! Get the UINT32 bitfield value for parameter 'name' from the parameter
  *  resource store attached to 'state'. */
-#define SrvInitParamGetUINT32BitField(state, name, value) \
+#define SrvInitParamGetUINT32BitField(device, state, name, value) \
                _SrvInitParamGetUINT32BitField(state, # name, __SrvInitParam_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name, &(value))
 
 /*************************************************************************/ /*!
@@ -263,7 +269,7 @@ void _SrvInitParamGetUINT32List(
 
 /*! Get the UINT32 list value for parameter 'name' from the parameter
  *  resource store attached to 'state'. */
-#define SrvInitParamGetUINT32List(state, name, value) \
+#define SrvInitParamGetUINT32List(device, state, name, value) \
                _SrvInitParamGetUINT32List(state, # name, __SrvInitParam_ ## name, __SrvInitParamLookup_ ## name, __SrvInitParamSize_ ## name, &(value))
 
 /*! Initialise UINT32 list type parameter identified by 'name' with
@@ -305,12 +311,12 @@ void _SrvInitParamGetSTRING(
 
 /*! Initialise STRING type parameter identified by 'name' with 'defval' default
  *  value. */
-#define SrvInitParamInitSTRING(name, defval, dummy) \
+#define SrvInitParamInitSTRING(name, defval, unused) \
        static const IMG_CHAR *__SrvInitParam_ ## name = defval;
 
 /*! Get the STRING value for parameter 'name' from the parameter resource store
  *  attached to 'state'. */
-#define SrvInitParamGetSTRING(state, name, buffer, size) \
+#define SrvInitParamGetSTRING(device, state, name, buffer, size) \
                _SrvInitParamGetSTRING(state, # name,  __SrvInitParam_ ## name, buffer, size)
 
 #if defined(__cplusplus)
index c3d1b59..28a6dd3 100644 (file)
@@ -47,6 +47,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "handle.h"
 #include "osfunc.h"
 
+/*! Function not implemented definition. */
+#define OSCONNECTION_SERVER_NOT_IMPLEMENTED 0
+/*! Assert used for OSCONNECTION_SERVER_NOT_IMPLEMENTED. */
+#define OSCONNECTION_SERVER_NOT_IMPLEMENTED_ASSERT() PVR_ASSERT(OSCONNECTION_SERVER_NOT_IMPLEMENTED)
 
 #if defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS)
 PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, void *pvOSData);
@@ -75,7 +79,9 @@ static INLINE PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateDa
        PVR_UNREFERENCED_PARAMETER(phOsPrivateData);
        PVR_UNREFERENCED_PARAMETER(pvOSData);
 
-       return PVRSRV_OK;
+       OSCONNECTION_SERVER_NOT_IMPLEMENTED_ASSERT();
+
+       return PVRSRV_ERROR_NOT_IMPLEMENTED;
 }
 
 #ifdef INLINE_IS_PRAGMA
@@ -93,7 +99,9 @@ static INLINE PVRSRV_ERROR OSConnectionPrivateDataDeInit(IMG_HANDLE hOsPrivateDa
 {
        PVR_UNREFERENCED_PARAMETER(hOsPrivateData);
 
-       return PVRSRV_OK;
+       OSCONNECTION_SERVER_NOT_IMPLEMENTED_ASSERT();
+
+       return PVRSRV_ERROR_NOT_IMPLEMENTED;
 }
 
 #ifdef INLINE_IS_PRAGMA
@@ -103,7 +111,9 @@ static INLINE PVRSRV_ERROR OSConnectionSetHandleOptions(PVRSRV_HANDLE_BASE *psHa
 {
        PVR_UNREFERENCED_PARAMETER(psHandleBase);
 
-       return PVRSRV_OK;
+       OSCONNECTION_SERVER_NOT_IMPLEMENTED_ASSERT();
+
+       return PVRSRV_ERROR_NOT_IMPLEMENTED;
 }
 
 #ifdef INLINE_IS_PRAGMA
@@ -113,6 +123,8 @@ static INLINE PVRSRV_DEVICE_NODE* OSGetDevNode(CONNECTION_DATA *psConnection)
 {
        PVR_UNREFERENCED_PARAMETER(psConnection);
 
+       OSCONNECTION_SERVER_NOT_IMPLEMENTED_ASSERT();
+
        return NULL;
 }
 #endif /* defined(__linux__) || defined(__QNXNTO__) || defined(INTEGRITY_OS) */
index eddda39..aa39814 100644 (file)
@@ -52,6 +52,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * implementation handles. */
 typedef struct OSDI_IMPL_ENTRY_CB
 {
+    /*! @Function pfnWrite
+     *
+     * @Description
+     * Writes the binary data of the DI entry to the output sync, whatever that
+     * may be for the DI implementation.
+     *
+     * @Input pvNativeHandle native implementation handle
+     * @Input pvData data
+     * @Input uiSize pvData length
+     */
+    void (*pfnWrite)(void  *pvNativeHandle, const void *pvData,
+                     IMG_UINT32 uiSize);
+
     /*! @Function pfnVPrintf
      *
      * @Description
@@ -84,7 +97,7 @@ typedef struct OSDI_IMPL_ENTRY_CB
 } OSDI_IMPL_ENTRY_CB;
 
 /*! Debug Info entry specialisation. */
-typedef struct OSDI_IMPL_ENTRY
+struct OSDI_IMPL_ENTRY
 {
     /*! Pointer to the private data. The data originates from DICreateEntry()
      *  function. */
@@ -93,7 +106,7 @@ typedef struct OSDI_IMPL_ENTRY
     void *pvNative;
     /*! Implementation entry callbacks. */
     OSDI_IMPL_ENTRY_CB *psCb;
-} OSDI_IMPL_ENTRY;
+}; /* OSDI_IMPL_ENTRY is already typedef-ed in di_common.h */
 
 /*! Debug Info implementation callbacks. */
 typedef struct OSDI_IMPL_CB
index a546903..93a94c4 100644 (file)
@@ -644,8 +644,7 @@ IMG_INT OSMemCmp(void *pvBufA, void *pvBufB, size_t uiLen);
                 If allocations made by this function are CPU cached then
                 OSPhyContigPagesClean has to be implemented to write the
                 cached data to memory.
-@Input          psDevNode     the device for which the allocation is
-                              required
+@Input          psPhysHeap    the heap from which to allocate
 @Input          uiSize        the size of the required allocation (in bytes)
 @Output         psMemHandle   a returned handle to be used to refer to this
                               allocation
@@ -654,24 +653,24 @@ IMG_INT OSMemCmp(void *pvBufA, void *pvBufB, size_t uiLen);
                               be associated with
 @Return         PVRSRV_OK on success, a failure code otherwise.
 *****************************************************************************/
-PVRSRV_ERROR OSPhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
+PVRSRV_ERROR OSPhyContigPagesAlloc(PHYS_HEAP *psPhysHeap, size_t uiSize,
                                                        PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
                                                        IMG_PID uiPid);
 
 /*************************************************************************/ /*!
 @Function       OSPhyContigPagesFree
 @Description    Frees a previous allocation of contiguous physical pages
-@Input          psDevNode     the device on which the allocation was made
+@Input          psPhysHeap    the heap from which to allocate
 @Input          psMemHandle   the handle of the allocation to be freed
 @Return         None.
 *****************************************************************************/
-void OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle);
+void OSPhyContigPagesFree(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle);
 
 /*************************************************************************/ /*!
 @Function       OSPhyContigPagesMap
 @Description    Maps the specified allocation of contiguous physical pages
                 to a kernel virtual address
-@Input          psDevNode     the device on which the allocation was made
+@Input          psPhysHeap    the heap from which to allocate
 @Input          psMemHandle   the handle of the allocation to be mapped
 @Input          uiSize        the size of the allocation (in bytes)
 @Input          psDevPAddr    the physical address of the allocation
@@ -679,7 +678,7 @@ void OSPhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle)
                               allocation is now mapped
 @Return         PVRSRV_OK on success, a failure code otherwise.
 *****************************************************************************/
-PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
+PVRSRV_ERROR OSPhyContigPagesMap(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle,
                                                size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
                                                void **pvPtr);
 
@@ -687,13 +686,13 @@ PVRSRV_ERROR OSPhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMem
 @Function       OSPhyContigPagesUnmap
 @Description    Unmaps the kernel mapping for the specified allocation of
                 contiguous physical pages
-@Input          psDevNode     the device on which the allocation was made
+@Input          psPhysHeap    the heap from which to allocate
 @Input          psMemHandle   the handle of the allocation to be unmapped
 @Input          pvPtr         the virtual kernel address to which the
                               allocation is currently mapped
 @Return         None.
 *****************************************************************************/
-void OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle, void *pvPtr);
+void OSPhyContigPagesUnmap(PHYS_HEAP *psPhysHeap, PG_HANDLE *psMemHandle, void *pvPtr);
 
 /*************************************************************************/ /*!
 @Function       OSPhyContigPagesClean
@@ -704,14 +703,14 @@ void OSPhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle
                 (i.e. flush).
                 If allocations returned by OSPhyContigPagesAlloc are always
                 uncached this can be implemented as nop.
-@Input          psDevNode     device on which the allocation was made
+@Input          psPhysHeap    the heap from which to allocate
 @Input          psMemHandle   the handle of the allocation to be flushed
 @Input          uiOffset      the offset in bytes from the start of the
                               allocation from where to start flushing
 @Input          uiLength      the amount to flush from the offset in bytes
 @Return         PVRSRV_OK on success, a failure code otherwise.
 *****************************************************************************/
-PVRSRV_ERROR OSPhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
+PVRSRV_ERROR OSPhyContigPagesClean(PHYS_HEAP *psPhysHeap,
                                    PG_HANDLE *psMemHandle,
                                    IMG_UINT32 uiOffset,
                                    IMG_UINT32 uiLength);
@@ -967,20 +966,9 @@ void OSSleepms(IMG_UINT32 ui32Timems);
 void OSReleaseThreadQuanta(void);
 
 #if defined(__linux__) && defined(__KERNEL__)
-#define OSWriteMemoryBarrier() wmb()
 #define OSReadMemoryBarrier() rmb()
-#define OSMemoryBarrier() mb()
 #else
 /*************************************************************************/ /*!
-@Function       OSWriteMemoryBarrier
-@Description    Insert a write memory barrier.
-                The write memory barrier guarantees that all store operations
-                (writes) specified before the barrier will appear to happen
-                before all of the store operations specified after the barrier.
-@Return         PVRSRV_OK on success, a failure code otherwise.
-*/ /**************************************************************************/
-void OSWriteMemoryBarrier(void);
-/*************************************************************************/ /*!
 @Function       OSReadMemoryBarrier
 @Description    Insert a read memory barrier.
                 The read memory barrier guarantees that all load (read)
@@ -988,6 +976,7 @@ void OSWriteMemoryBarrier(void);
                 before all of the load operations specified after the barrier.
 */ /**************************************************************************/
 void OSReadMemoryBarrier(void);
+#endif
 /*************************************************************************/ /*!
 @Function       OSMemoryBarrier
 @Description    Insert a read/write memory barrier.
@@ -995,10 +984,24 @@ void OSReadMemoryBarrier(void);
                 (read) and all store (write) operations specified before the
                 barrier will appear to happen before all of the load/store
                 operations specified after the barrier.
+@Input          hReadback     Optional pointer to memory to read back, can be
+                useful for flushing queues in bus interconnects to RAM before
+                device (GPU) access the shared memory.
 @Return         None.
 */ /**************************************************************************/
-void OSMemoryBarrier(void);
-#endif
+void OSMemoryBarrier(volatile void *hReadback);
+/*************************************************************************/ /*!
+@Function       OSWriteMemoryBarrier
+@Description    Insert a write memory barrier.
+                The write memory barrier guarantees that all store operations
+                (writes) specified before the barrier will appear to happen
+                before all of the store operations specified after the barrier.
+@Input          hReadback     Optional pointer to memory to read back, can be
+                useful for flushing queues in bus interconnects to RAM before
+                device (GPU) access the shared memory.
+@Return         None.
+*/ /**************************************************************************/
+void OSWriteMemoryBarrier(volatile void *hReadback);
 
 /*************************************************************************/ /*!
 */ /**************************************************************************/
@@ -1008,14 +1011,14 @@ void OSMemoryBarrier(void);
  * macros may change in future to accommodate different access requirements.
  */
 /*! Performs a 32 bit word read from the device memory. */
-#define OSReadDeviceMem32(addr)        (*((volatile IMG_UINT32 __force *)(addr)))
+#define OSReadDeviceMem32(addr)        (*((volatile IMG_UINT32 __force *)((void*)addr)))
 /*! Performs a 32 bit word write to the device memory. */
-#define OSWriteDeviceMem32(addr, val)  (*((volatile IMG_UINT32 __force *)(addr)) = (IMG_UINT32)(val))
+#define OSWriteDeviceMem32(addr, val)  (*((volatile IMG_UINT32 __force *)((void*)addr)) = (IMG_UINT32)(val))
 /*! Performs a 32 bit word write to the device memory and issues a write memory barrier */
 #define OSWriteDeviceMem32WithWMB(addr, val) \
        do { \
-               *((volatile IMG_UINT32 __force *)(addr)) = (IMG_UINT32)(val); \
-               OSWriteMemoryBarrier(); \
+               *((volatile IMG_UINT32 __force *)((void*)addr)) = (IMG_UINT32)(val); \
+               OSWriteMemoryBarrier(addr); \
        } while (0)
 
 #if defined(__linux__) && defined(__KERNEL__) && !defined(NO_HARDWARE)
@@ -1051,14 +1054,14 @@ void OSMemoryBarrier(void);
 
 #elif defined(NO_HARDWARE)
        /* OSReadHWReg operations skipped in no hardware builds */
-       #define OSReadHWReg8(addr, off)  (0x4eU)
-       #define OSReadHWReg16(addr, off) (0x3a4eU)
-       #define OSReadHWReg32(addr, off) (0x30f73a4eU)
+       #define OSReadHWReg8(addr, off)  ((void)(addr), 0x4eU)
+       #define OSReadHWReg16(addr, off) ((void)(addr), 0x3a4eU)
+       #define OSReadHWReg32(addr, off) ((void)(addr), 0x30f73a4eU)
 #if defined(__QNXNTO__) && __SIZEOF_LONG__ == 8
        /* This is needed for 64-bit QNX builds where the size of a long is 64 bits */
-       #define OSReadHWReg64(addr, off) (0x5b376c9d30f73a4eUL)
+       #define OSReadHWReg64(addr, off) ((void)(addr), 0x5b376c9d30f73a4eUL)
 #else
-       #define OSReadHWReg64(addr, off) (0x5b376c9d30f73a4eULL)
+       #define OSReadHWReg64(addr, off) ((void)(addr), 0x5b376c9d30f73a4eULL)
 #endif
 
        #define OSWriteHWReg8(addr, off, val)
@@ -1350,9 +1353,8 @@ PVRSRV_ERROR OSPlatformBridgeInit(void);
 @Description    Called during device destruction to allow the OS port to
                 deregister its OS specific bridges and clean up other
                 related resources.
-@Return         PVRSRV_OK on success, a failure code otherwise.
 */ /**************************************************************************/
-PVRSRV_ERROR OSPlatformBridgeDeInit(void);
+void OSPlatformBridgeDeInit(void);
 
 /*************************************************************************/ /*!
 @Function       PVRSRVToNativeError
@@ -1382,6 +1384,7 @@ int PVRSRVToNativeError(PVRSRV_ERROR e);
 #define OSWRLockDestroy(psLock) ({OSFreeMem(psLock); PVRSRV_OK;})
 
 #define OSWRLockAcquireRead(psLock) ({down_read(psLock); PVRSRV_OK;})
+#define OSWRLockAcquireReadNested(psLock, subclass) ({down_read_nested((psLock), (subclass)); PVRSRV_OK;})
 #define OSWRLockReleaseRead(psLock) ({up_read(psLock); PVRSRV_OK;})
 #define OSWRLockAcquireWrite(psLock) ({down_write(psLock); PVRSRV_OK;})
 #define OSWRLockReleaseWrite(psLock) ({up_write(psLock); PVRSRV_OK;})
@@ -1392,12 +1395,18 @@ int PVRSRVToNativeError(PVRSRV_ERROR e);
 PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock);
 void OSWRLockDestroy(POSWR_LOCK psLock);
 void OSWRLockAcquireRead(POSWR_LOCK psLock);
+#define OSWRLockAcquireReadNested(psLock, subclass) OSWRLockAcquireRead((psLock))
 void OSWRLockReleaseRead(POSWR_LOCK psLock);
 void OSWRLockAcquireWrite(POSWR_LOCK psLock);
 void OSWRLockReleaseWrite(POSWR_LOCK psLock);
 
 #else
 
+/*! Function not implemented definition. */
+#define OSFUNC_NOT_IMPLEMENTED 0
+/*! Assert used for OSFUNC_NOT_IMPLEMENTED. */
+#define OSFUNC_NOT_IMPLEMENTED_ASSERT() PVR_ASSERT(OSFUNC_NOT_IMPLEMENTED)
+
 /*************************************************************************/ /*!
 @Function       OSWRLockCreate
 @Description    Create a writer/reader lock.
@@ -1409,7 +1418,10 @@ void OSWRLockReleaseWrite(POSWR_LOCK psLock);
 static INLINE PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock)
 {
        PVR_UNREFERENCED_PARAMETER(ppsLock);
-       return PVRSRV_OK;
+
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
+
+       return PVRSRV_ERROR_NOT_IMPLEMENTED;
 }
 
 /*************************************************************************/ /*!
@@ -1421,6 +1433,7 @@ static INLINE PVRSRV_ERROR OSWRLockCreate(POSWR_LOCK *ppsLock)
 static INLINE void OSWRLockDestroy(POSWR_LOCK psLock)
 {
        PVR_UNREFERENCED_PARAMETER(psLock);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
 }
 
 /*************************************************************************/ /*!
@@ -1435,6 +1448,31 @@ static INLINE void OSWRLockDestroy(POSWR_LOCK psLock)
 static INLINE void OSWRLockAcquireRead(POSWR_LOCK psLock)
 {
        PVR_UNREFERENCED_PARAMETER(psLock);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
+}
+
+/*************************************************************************/ /*!
+@Function       OSWRLockAcquireReadNested
+@Description    Acquire a nested writer/reader read lock.
+                If the write lock is already acquired, the caller will
+                block until it is released.
+                For operating systems other than Linux, this equates to an
+                OSWRLockAcquireRead() call. On Linux, this function wraps a call
+                to down_read_nested(). This recognises the scenario where
+                there may be multiple subclasses within a particular class
+                of lock. In such cases, the order in which the locks belonging
+                these various subclasses are acquired is important and must be
+                validated.
+@Input          psLock     The handle of the WR lock to be acquired for
+                           reading.
+@Input          iSubclass  The subclass of the lock.
+@Return         None.
+*/ /**************************************************************************/
+static INLINE void OSWRLockAcquireReadNested(POSWR_LOCK psLock, IMG_INT iSubclass)
+{
+       PVR_UNREFERENCED_PARAMETER(psLock);
+       PVR_UNREFERENCED_PARAMETER(iSubclass);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
 }
 
 /*************************************************************************/ /*!
@@ -1447,6 +1485,7 @@ static INLINE void OSWRLockAcquireRead(POSWR_LOCK psLock)
 static INLINE void OSWRLockReleaseRead(POSWR_LOCK psLock)
 {
        PVR_UNREFERENCED_PARAMETER(psLock);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
 }
 
 /*************************************************************************/ /*!
@@ -1461,6 +1500,7 @@ static INLINE void OSWRLockReleaseRead(POSWR_LOCK psLock)
 static INLINE void OSWRLockAcquireWrite(POSWR_LOCK psLock)
 {
        PVR_UNREFERENCED_PARAMETER(psLock);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
 }
 
 /*************************************************************************/ /*!
@@ -1473,6 +1513,7 @@ static INLINE void OSWRLockAcquireWrite(POSWR_LOCK psLock)
 static INLINE void OSWRLockReleaseWrite(POSWR_LOCK psLock)
 {
        PVR_UNREFERENCED_PARAMETER(psLock);
+       OSFUNC_NOT_IMPLEMENTED_ASSERT();
 }
 #endif
 
index 4ae5686..78d4040 100644 (file)
@@ -42,38 +42,44 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "img_defs.h"
 #if defined(__linux__)
 #include "km_apphint.h"
+#include "device.h"
 #else
 #include "services_client_porting.h"
 #endif
 #if !defined(OSKM_APPHINT_H)
 #define OSKM_APPHINT_H
 
+/*! Supplied to os_get_km_apphint_XXX() functions when the param/AppHint is
+ * applicable to all devices and not a specific device. Typically used
+ * for server-wide build and module AppHints.
+ */
+#define APPHINT_NO_DEVICE (NULL)
 
 #if defined(__linux__) && !defined(DOXYGEN)
-static INLINE IMG_UINT os_get_km_apphint_UINT32(void *state, APPHINT_ID id, const IMG_UINT32 *pAppHintDefault, IMG_UINT32 *pVal) {
-       return !pvr_apphint_get_uint32(id, pVal);
+static INLINE IMG_UINT os_get_km_apphint_UINT32(PVRSRV_DEVICE_NODE *device, void *state, APPHINT_ID id, const IMG_UINT32 *pAppHintDefault, IMG_UINT32 *pVal) {
+       return !pvr_apphint_get_uint32(device, id, pVal);
 }
-static INLINE IMG_UINT os_get_km_apphint_UINT64(void *state, APPHINT_ID id, const IMG_UINT64 *pAppHintDefault, IMG_UINT64 *pVal) {
-       return !pvr_apphint_get_uint64(id, pVal);
+static INLINE IMG_UINT os_get_km_apphint_UINT64(PVRSRV_DEVICE_NODE *device, void *state, APPHINT_ID id, const IMG_UINT64 *pAppHintDefault, IMG_UINT64 *pVal) {
+       return !pvr_apphint_get_uint64(device, id, pVal);
 }
-static INLINE IMG_UINT os_get_km_apphint_BOOL(void *state, APPHINT_ID id, const IMG_BOOL *pAppHintDefault, IMG_BOOL *pVal) {
-       return !pvr_apphint_get_bool(id, pVal);
+static INLINE IMG_UINT os_get_km_apphint_BOOL(PVRSRV_DEVICE_NODE *device, void *state, APPHINT_ID id, const IMG_BOOL *pAppHintDefault, IMG_BOOL *pVal) {
+       return !pvr_apphint_get_bool(device, id, pVal);
 }
-static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, const IMG_CHAR *pAppHintDefault, IMG_CHAR *buffer, size_t size) {
-       return !pvr_apphint_get_string(id, buffer, size);
+static INLINE IMG_UINT os_get_km_apphint_STRING(PVRSRV_DEVICE_NODE *device, void *state, APPHINT_ID id, const IMG_CHAR *pAppHintDefault, IMG_CHAR *buffer, size_t size) {
+       return !pvr_apphint_get_string(device, id, buffer, size);
 }
 
-#define OSGetKMAppHintUINT32(state, name, appHintDefault, value) \
-       os_get_km_apphint_UINT32(state, APPHINT_ID_ ## name, appHintDefault, value)
+#define OSGetKMAppHintUINT32(device, state, name, appHintDefault, value) \
+       os_get_km_apphint_UINT32(device, state, APPHINT_ID_ ## name, appHintDefault, value)
 
-#define OSGetKMAppHintUINT64(state, name, appHintDefault, value) \
-       os_get_km_apphint_UINT64(state, APPHINT_ID_ ## name, appHintDefault, value)
+#define OSGetKMAppHintUINT64(device, state, name, appHintDefault, value) \
+       os_get_km_apphint_UINT64(device, state, APPHINT_ID_ ## name, appHintDefault, value)
 
-#define OSGetKMAppHintBOOL(state, name, appHintDefault, value) \
-       os_get_km_apphint_BOOL(state, APPHINT_ID_ ## name, appHintDefault, value)
+#define OSGetKMAppHintBOOL(device, state, name, appHintDefault, value) \
+       os_get_km_apphint_BOOL(device, state, APPHINT_ID_ ## name, appHintDefault, value)
 
-#define OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size) \
-       os_get_km_apphint_STRING(state, APPHINT_ID_ ## name, appHintDefault, buffer, size)
+#define OSGetKMAppHintSTRING(device, state, name, appHintDefault, buffer, size) \
+       os_get_km_apphint_STRING(device, state, APPHINT_ID_ ## name, appHintDefault, buffer, size)
 
 
 #define OSCreateKMAppHintState(state) \
@@ -90,13 +96,14 @@ static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, cons
                                For non-linux operating systems, this macro implements a call
                                from server code to PVRSRVGetAppHint() declared in
                                services_client_porting.h, effectively making it 'shared' code.
+@Input          device            Device node
 @Input          state             App hint state
 @Input          name              Name used to identify app hint
 @Input          appHintDefault    Default value to be returned if no
                                                                  app hint is found.
 @Output         value             Pointer to returned app hint value.
  */ /**************************************************************************/
-#define OSGetKMAppHintUINT32(state, name, appHintDefault, value) \
+#define OSGetKMAppHintUINT32(device, state, name, appHintDefault, value) \
        PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
 
 /**************************************************************************/ /*!
@@ -105,13 +112,14 @@ static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, cons
                                For non-linux operating systems, this macro implements a call
                                from server code to PVRSRVGetAppHint() declared in
                                services_client_porting.h, effectively making it 'shared' code.
+@Input          device            Device node
 @Input          state             App hint state
 @Input          name              Name used to identify app hint
 @Input          appHintDefault    Default value to be returned if no
                                                                  app hint is found.
 @Output         value             Pointer to returned app hint value.
  */ /**************************************************************************/
-#define OSGetKMAppHintUINT64(state, name, appHintDefault, value) \
+#define OSGetKMAppHintUINT64(device, state, name, appHintDefault, value) \
        PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
 
 /**************************************************************************/ /*!
@@ -120,13 +128,14 @@ static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, cons
                                For non-linux operating systems, this macro implements a call
                                from server code to PVRSRVGetAppHint() declared in
                                services_client_porting.h, effectively making it 'shared' code.
+@Input          device            Device node
 @Input          state             App hint state
 @Input          name              Name used to identify app hint
 @Input          appHintDefault    Default value to be returned if no
                                                                  app hint is found.
 @Output         value             Pointer to returned app hint value.
  */ /**************************************************************************/
-#define OSGetKMAppHintBOOL(state, name, appHintDefault, value) \
+#define OSGetKMAppHintBOOL(device, state, name, appHintDefault, value) \
        PVRSRVGetAppHint(state, # name, IMG_UINT_TYPE, appHintDefault, value)
 
 /**************************************************************************/ /*!
@@ -135,6 +144,7 @@ static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, cons
                                For non-linux operating systems, this macro implements a call
                                from server code to PVRSRVGetAppHint() declared in
                                services_client_porting.h, effectively making it 'shared' code.
+@Input          device            Device node
 @Input          state             App hint state
 @Input          name              Name used to identify app hint
 @Input          appHintDefault    Default value to be returned if no
@@ -142,7 +152,7 @@ static INLINE IMG_UINT os_get_km_apphint_STRING(void *state, APPHINT_ID id, cons
 @Output         buffer            Buffer used to return app hint string.
 @Input                 size                      Size of the buffer.
  */ /**************************************************************************/
-#define OSGetKMAppHintSTRING(state, name, appHintDefault, buffer, size) \
+#define OSGetKMAppHintSTRING(device, state, name, appHintDefault, buffer, size) \
        (PVR_UNREFERENCED_PARAMETER(size), PVRSRVGetAppHint(state, # name, IMG_STRING_TYPE, appHintDefault, buffer))
 
 /**************************************************************************/ /*!
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/include/ossecure_export.h b/drivers/gpu/drm/img/img-rogue/services/server/include/ossecure_export.h
new file mode 100644 (file)
index 0000000..020f5f5
--- /dev/null
@@ -0,0 +1,81 @@
+/*************************************************************************/ /*!
+@File
+@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.
+*/ /**************************************************************************/
+
+#include "img_types.h"
+#include "pvrsrv_error.h"
+#include "connection_server.h"
+
+/*************************************************************************/ /*!
+@Function       OSSecureExport
+@Description    Assigns an OS-specific 'token' to allow a resource
+                to be securely referenced by another process.
+                A process wishing to reference the exported resource
+                should call OSSecureImport(), passing its OS-specific
+                reference to the same resource.
+                For the export/import to be deemed 'secure', the
+                implementation should ensure that the OS-specific
+                reference can only be meaningfully used by a process
+                which is permitted to do so.
+@Input          pszName        name of the "class" of new secure file
+@Input          pfnReleaseFunc  pointer to the function to be called
+                               while closing secure file
+@Input          pvData         pointer to the actual resource that
+                               is being exported
+@Output         phSecure       the returned secure token
+@Return         PVRSRV_OK      on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSSecureExport(const IMG_CHAR *pszName,
+                            PVRSRV_ERROR (*pfnReleaseFunc)(void *),
+                            void *pvData,
+                            IMG_SECURE_TYPE *phSecure);
+
+/*************************************************************************/ /*!
+@Function       OSSecureImport
+@Description    Imports an OS-specific 'token' that allows a resource
+                allocated by another process to be securely referenced by
+                the current process.
+@Input          hSecure             the secure token for the resource to
+                                    be imported
+@Output         ppvData             pointer to the actual resource that
+                                    is being referenced
+@Return         PVRSRV_OK on success, a failure code otherwise.
+*/ /**************************************************************************/
+PVRSRV_ERROR OSSecureImport(IMG_SECURE_TYPE hSecure, void **ppvData);
index 26ff769..b9cb5f6 100644 (file)
@@ -45,11 +45,17 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PDUMP_KM_H
 
 #if defined(PDUMP)
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
-
-#endif
+ #if defined(__linux__)
+  #include <linux/version.h>
+  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+   #include <linux/stdarg.h>
+  #else
+   #include <stdarg.h>
+  #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+ #else
+  #include <stdarg.h>
+ #endif /* __linux__ */
+#endif /* PDUMP */
 
 /* services/srvkm/include/ */
 #include "device.h"
@@ -100,23 +106,23 @@ typedef enum _PDUMP_TRANSITION_EVENT_
 } PDUMP_TRANSITION_EVENT;
 
 typedef PVRSRV_ERROR (*PFN_PDUMP_TRANSITION)(void *pvData, void *pvDevice, PDUMP_TRANSITION_EVENT eEvent, IMG_UINT32 ui32PDumpFlags);
-typedef void (*PFN_PDUMP_SYNCBLOCKS)(void *pvData, PDUMP_TRANSITION_EVENT eEvent);
+typedef void (*PFN_PDUMP_SYNCBLOCKS)(PVRSRV_DEVICE_NODE *psDevNode, void *pvData, PDUMP_TRANSITION_EVENT eEvent);
 
 typedef PVRSRV_ERROR (*PFN_PDUMP_TRANSITION_FENCE_SYNC)(void *pvData, PDUMP_TRANSITION_EVENT eEvent);
 
 #ifdef PDUMP
 
 /*! Macro used to record a panic in the PDump script stream */
-#define PDUMP_PANIC(_id, _msg) do \
+#define PDUMP_PANIC(_dev, _id, _msg) do \
                { PVRSRV_ERROR _eE;\
-                       _eE = PDumpPanic(((RGX_PDUMP_PANIC_ ## _id) & 0xFFFF), _msg, __func__, __LINE__);       \
+                       _eE = PDumpPanic((_dev), ((RGX_PDUMP_PANIC_ ## _id) & 0xFFFF), _msg, __func__, __LINE__);       \
                        PVR_LOG_IF_ERROR(_eE, "PDumpPanic");\
                MSC_SUPPRESS_4127\
                } while (0)
 
 /*! Macro used to record a driver error in the PDump script stream to invalidate the capture */
-#define PDUMP_ERROR(_err, _msg) \
-       (void)PDumpCaptureError(_err, _msg, __func__, __LINE__)
+#define PDUMP_ERROR(_dev, _err, _msg) \
+       (void)PDumpCaptureError((_dev), _err, _msg, __func__, __LINE__)
 
 #define SZ_MSG_SIZE_MAX                        PVRSRV_PDUMP_MAX_COMMENT_SIZE
 #define SZ_SCRIPT_SIZE_MAX             PVRSRV_PDUMP_MAX_COMMENT_SIZE
@@ -212,41 +218,51 @@ void PDumpGetParameterZeroPageInfo(PDUMP_FILEOFFSET_T *puiZeroPageOffset,
                                    size_t *puiZeroPageSize,
                                    const IMG_CHAR **ppszZeroPageFilename);
 
-void PDumpConnectionNotify(void);
-void PDumpDisconnectionNotify(void);
+void PDumpConnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode);
+void PDumpDisconnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode);
 
-void PDumpStopInitPhase(void);
+void PDumpStopInitPhase(PVRSRV_DEVICE_NODE *psDeviceNode);
 PVRSRV_ERROR PDumpSetFrameKM(CONNECTION_DATA *psConnection,
-                             PVRSRV_DEVICE_NODE * psDeviceNode,
+                             PVRSRV_DEVICE_NODE *psDeviceNode,
                              IMG_UINT32 ui32Frame);
 PVRSRV_ERROR PDumpGetFrameKM(CONNECTION_DATA *psConnection,
                              PVRSRV_DEVICE_NODE * psDeviceNode,
                              IMG_UINT32* pui32Frame);
-PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
+PVRSRV_ERROR PDumpCommentKM(CONNECTION_DATA *psConnection,
+                            PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_UINT32 ui32CommentSize,
+                            IMG_CHAR *pszComment,
+                            IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
+PVRSRV_ERROR PDumpSetDefaultCaptureParamsKM(CONNECTION_DATA *psConnection,
+                                            PVRSRV_DEVICE_NODE *psDeviceNode,
+                                            IMG_UINT32 ui32Mode,
                                             IMG_UINT32 ui32Start,
                                             IMG_UINT32 ui32End,
                                             IMG_UINT32 ui32Interval,
                                             IMG_UINT32 ui32MaxParamFileSize);
 
 
-PVRSRV_ERROR PDumpReg32(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpReg32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                        IMG_CHAR *pszPDumpRegName,
                         IMG_UINT32 ui32RegAddr,
                         IMG_UINT32 ui32RegValue,
                         IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpReg64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                        IMG_CHAR *pszPDumpRegName,
                         IMG_UINT32 ui32RegAddr,
                         IMG_UINT64 ui64RegValue,
                         IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpRegLabelToReg64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegLabelToReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  IMG_CHAR *pszPDumpRegName,
                                   IMG_UINT32 ui32RegDst,
                                   IMG_UINT32 ui32RegSrc,
                                   IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpPhysHandleToInternalVar64(IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpPhysHandleToInternalVar64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                            IMG_CHAR *pszInternalVar,
                                             IMG_HANDLE hPdumpPages,
                                             IMG_UINT32 ui32Flags);
 
@@ -260,32 +276,39 @@ PVRSRV_ERROR PDumpInternalVarToMemLabel(PMR *psPMR,
                                         IMG_CHAR *pszInternalVar,
                                         IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpWriteVarORValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarORValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                    const IMG_CHAR *pszInternalVariable,
                                     const IMG_UINT64 ui64Value,
                                     const IMG_UINT32 ui32PDumpFlags);
 
-PVRSRV_ERROR PDumpWriteVarANDValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarANDValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     const IMG_CHAR *pszInternalVariable,
                                      const IMG_UINT64 ui64Value,
                                      const IMG_UINT32 ui32PDumpFlags);
 
-PVRSRV_ERROR PDumpWriteVarSHRValueOp(const IMG_CHAR *pszInternalVariable,
+PVRSRV_ERROR PDumpWriteVarSHRValueOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     const IMG_CHAR *pszInternalVariable,
                                      const IMG_UINT64 ui64Value,
                                      const IMG_UINT32 ui32PDumpFlags);
 
-PVRSRV_ERROR PDumpWriteVarORVarOp(const IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpWriteVarORVarOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                  const IMG_CHAR *pszInternalVar,
                                   const IMG_CHAR *pszInternalVar2,
                                   const IMG_UINT32 ui32PDumpFlags);
 
-PVRSRV_ERROR PDumpWriteVarANDVarOp(const IMG_CHAR *pszInternalVar,
+PVRSRV_ERROR PDumpWriteVarANDVarOp(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   const IMG_CHAR *pszInternalVar,
                                    const IMG_CHAR *pszInternalVar2,
                                    const IMG_UINT32 ui32PDumpFlags);
 
-PVRSRV_ERROR PDumpInternalVarToReg32(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpInternalVarToReg32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_CHAR *pszPDumpRegName,
                                      IMG_UINT32 ui32Reg,
                                      IMG_CHAR *pszInternalVar,
                                      IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpInternalVarToReg64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpInternalVarToReg64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_CHAR *pszPDumpRegName,
                                      IMG_UINT32 ui32Reg,
                                      IMG_CHAR *pszInternalVar,
                                      IMG_UINT32 ui32Flags);
@@ -314,38 +337,28 @@ PVRSRV_ERROR PDumpRegLabelToMem64(IMG_CHAR *pszPDumpRegName,
                                   IMG_DEVMEM_OFFSET_T uiLogicalOffset,
                                   IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpRegLabelToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegLabelToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                        IMG_CHAR *pszPDumpRegName,
                                         IMG_UINT32 ui32Reg,
                                         IMG_CHAR *pszInternalVar,
                                         IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpSAW(IMG_CHAR      *pszDevSpaceName,
+PVRSRV_ERROR PDumpSAW(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_CHAR      *pszDevSpaceName,
                       IMG_UINT32    ui32HPOffsetBytes,
                       IMG_UINT32    ui32NumSaveBytes,
                       IMG_CHAR      *pszOutfileName,
                       IMG_UINT32    ui32OutfileOffsetByte,
                       PDUMP_FLAGS_T uiPDumpFlags);
 
-PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR            *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegPolKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                           IMG_CHAR            *pszPDumpRegName,
                            IMG_UINT32          ui32RegAddr,
                            IMG_UINT32          ui32RegValue,
                            IMG_UINT32          ui32Mask,
                            IMG_UINT32          ui32Flags,
                            PDUMP_POLL_OPERATOR eOperator);
 
-PVRSRV_ERROR PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
-                           IMG_CHAR *pszFileName,
-                           IMG_UINT32 ui32FileOffset,
-                           IMG_UINT32 ui32Width,
-                           IMG_UINT32 ui32Height,
-                           IMG_UINT32 ui32StrideInBytes,
-                           IMG_DEV_VIRTADDR sDevBaseAddr,
-                           IMG_UINT32 ui32MMUContextID,
-                           IMG_UINT32 ui32Size,
-                           PDUMP_PIXEL_FORMAT ePixelFormat,
-                           IMG_UINT32 ui32AddrMode,
-                           IMG_UINT32 ui32PDumpFlags);
-
 
 /**************************************************************************/ /*!
 @Function       PDumpImageDescriptor
@@ -416,91 +429,82 @@ PVRSRV_ERROR PDumpDataDescriptor(PVRSRV_DEVICE_NODE *psDeviceNode,
                                  IMG_UINT32 ui32PDumpFlags);
 
 
-PVRSRV_ERROR PDumpReadRegKM(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpReadRegKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_CHAR *pszPDumpRegName,
                             IMG_CHAR *pszFileName,
                             IMG_UINT32 ui32FileOffset,
                             IMG_UINT32 ui32Address,
                             IMG_UINT32 ui32Size,
                             IMG_UINT32 ui32PDumpFlags);
 
-__printf(2, 3)
-PVRSRV_ERROR PDumpCommentWithFlagsNoLock(IMG_UINT32 ui32Flags,
-                                         IMG_CHAR* pszFormat,
-                                         ...);
-
-PVRSRV_ERROR PDumpCommentWithFlagsNoLockVA(IMG_UINT32 ui32Flags,
-                                           const IMG_CHAR * pszFormat,
-                                           va_list args);
-
-__printf(2, 3)
-PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags,
+__printf(3, 4)
+PVRSRV_ERROR PDumpCommentWithFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   IMG_UINT32 ui32Flags,
                                    IMG_CHAR* pszFormat,
                                    ...);
 
-PVRSRV_ERROR PDumpCommentWithFlagsVA(IMG_UINT32 ui32Flags,
+PVRSRV_ERROR PDumpCommentWithFlagsVA(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                     IMG_UINT32 ui32Flags,
                                      const IMG_CHAR * pszFormat,
                                      va_list args);
 
-PVRSRV_ERROR PDumpPanic(IMG_UINT32      ui32PanicNo,
+PVRSRV_ERROR PDumpPanic(PVRSRV_DEVICE_NODE *psDeviceNode,
+                        IMG_UINT32      ui32PanicNo,
                         IMG_CHAR*       pszPanicMsg,
                         const IMG_CHAR* pszPPFunc,
                         IMG_UINT32      ui32PPline);
 
-PVRSRV_ERROR PDumpCaptureError(PVRSRV_ERROR    ui32ErrorNo,
+PVRSRV_ERROR PDumpCaptureError(PVRSRV_DEVICE_NODE *psDeviceNode,
+                               PVRSRV_ERROR    ui32ErrorNo,
                                IMG_CHAR*       pszErrorMsg,
                                const IMG_CHAR* pszPPFunc,
                                IMG_UINT32      ui32PPline);
 
-PVRSRV_ERROR PDumpPDReg(PDUMP_MMU_ATTRIB *psMMUAttrib,
-                        IMG_UINT32       ui32Reg,
-                        IMG_UINT32       ui32dwData,
-                        IMG_HANDLE       hUniqueTag);
-
-PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
-                                 IMG_UINT32       ui32Reg,
-                                 IMG_UINT32       ui32Data,
-                                 IMG_UINT32       ui32Flags,
-                                 IMG_HANDLE       hUniqueTag);
-
 PVRSRV_ERROR PDumpIsLastCaptureFrameKM(IMG_BOOL *pbIsLastCaptureFrame);
 
 PVRSRV_ERROR PDumpGetStateKM(IMG_UINT64 *ui64State);
 
-PVRSRV_ERROR PDumpGetCurrentBlockKM(IMG_UINT32 *pui32CurrentBlock);
-
-PVRSRV_ERROR PDumpForceCaptureStopKM(void);
+PVRSRV_ERROR PDumpForceCaptureStopKM(CONNECTION_DATA *psConnection,
+                                     PVRSRV_DEVICE_NODE *psDeviceNode);
 
-PVRSRV_ERROR PDumpIsCaptureFrameKM(IMG_BOOL *bIsCaptureRange);
-
-PVRSRV_ERROR PDumpRegRead32ToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead32ToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                         IMG_CHAR *pszPDumpRegName,
                                          IMG_UINT32 ui32RegOffset,
                                          IMG_CHAR *pszInternalVar,
                                          IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpRegRead32(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead32(PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_CHAR *pszPDumpRegName,
                             const IMG_UINT32 dwRegOffset,
                             IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpRegRead64(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead64(PVRSRV_DEVICE_NODE *psDeviceNode,
+                            IMG_CHAR *pszPDumpRegName,
                             const IMG_UINT32 dwRegOffset,
                             IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpRegRead64ToInternalVar(IMG_CHAR *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegRead64ToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                         IMG_CHAR *pszPDumpRegName,
                                          IMG_CHAR *pszInternalVar,
                                          const IMG_UINT32 dwRegOffset,
                                          IMG_UINT32    ui32Flags);
 
-PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags);
-PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks);
+PVRSRV_ERROR PDumpIDLWithFlags(PVRSRV_DEVICE_NODE *psDeviceNode,
+                               IMG_UINT32 ui32Clocks,
+                               IMG_UINT32 ui32Flags);
+PVRSRV_ERROR PDumpIDL(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_UINT32 ui32Clocks);
 
-PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR   *pszPDumpRegName,
+PVRSRV_ERROR PDumpRegBasedCBP(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              IMG_CHAR   *pszPDumpRegName,
                               IMG_UINT32 ui32RegOffset,
                               IMG_UINT32 ui32WPosVal,
                               IMG_UINT32 ui32PacketSize,
                               IMG_UINT32 ui32BufferSize,
                               IMG_UINT32 ui32Flags);
 
-PVRSRV_ERROR PDumpTRG(IMG_CHAR *pszMemSpace,
+PVRSRV_ERROR PDumpTRG(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      IMG_CHAR *pszMemSpace,
                       IMG_UINT32 ui32MMUCtxID,
                       IMG_UINT32 ui32RegionID,
                       IMG_BOOL bEnable,
@@ -527,17 +531,25 @@ PVRSRV_ERROR PDumpInternalValCondStr(IMG_CHAR            **ppszPDumpCond,
                                      IMG_UINT32          ui32Flags,
                                      PDUMP_POLL_OPERATOR eOperator);
 
-PVRSRV_ERROR PDumpIfKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
-PVRSRV_ERROR PDumpElseKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
-PVRSRV_ERROR PDumpFiKM(IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
-PVRSRV_ERROR PDumpStartDoLoopKM(IMG_UINT32 ui32PDumpFlags);
-PVRSRV_ERROR PDumpEndDoWhileLoopKM(IMG_CHAR *pszPDumpWhileCond, IMG_UINT32 ui32PDumpFlags);
-PVRSRV_ERROR PDumpCOMCommand(IMG_UINT32 ui32PDumpFlags, const IMG_CHAR *pszPDump);
-
-void PDumpPowerTransitionStart(void);
-void PDumpPowerTransitionEnd(void);
-IMG_BOOL PDumpInPowerTransition(void);
-IMG_BOOL PDumpIsContCaptureOn(void);
+PVRSRV_ERROR PDumpIfKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
+PVRSRV_ERROR PDumpElseKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                         IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
+PVRSRV_ERROR PDumpFiKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                       IMG_CHAR *pszPDumpCond, IMG_UINT32 ui32PDumpFlags);
+PVRSRV_ERROR PDumpStartDoLoopKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                IMG_UINT32 ui32PDumpFlags);
+PVRSRV_ERROR PDumpEndDoWhileLoopKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                   IMG_CHAR *pszPDumpWhileCond,
+                                   IMG_UINT32 ui32PDumpFlags);
+PVRSRV_ERROR PDumpCOMCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             IMG_UINT32 ui32PDumpFlags,
+                             const IMG_CHAR *pszPDump);
+
+void PDumpPowerTransitionStart(PVRSRV_DEVICE_NODE *psDeviceNode);
+void PDumpPowerTransitionEnd(PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL PDumpCheckFlagsWrite(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              IMG_UINT32 ui32Flags);
 
 /*!
  * @name       PDumpWriteParameter
@@ -545,6 +557,7 @@ IMG_BOOL PDumpIsContCaptureOn(void);
  *          mainly for memory dumps to parameter stream.
  *          Usually more convenient to use PDumpWriteScript below
  *          for the script stream.
+ * @param      psDeviceNode - device PDump pertains to
  * @param      psui8Data - data to write
  * @param      ui32Size - size of write
  * @param      ui32Flags - PDump flags
@@ -554,18 +567,21 @@ IMG_BOOL PDumpIsContCaptureOn(void);
  *                           return the parameter filename
  * @return     error
  */
-PVRSRV_ERROR PDumpWriteParameter(IMG_UINT8 *psui8Data, IMG_UINT32 ui32Size,
+PVRSRV_ERROR PDumpWriteParameter(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 IMG_UINT8 *psui8Data, IMG_UINT32 ui32Size,
                                  IMG_UINT32 ui32Flags, IMG_UINT32* pui32FileOffset,
                                  IMG_CHAR* aszFilenameStr);
 
 /*!
  * @name       PDumpWriteScript
  * @brief      Write an PDumpOS created string to the "script" output stream
+ * @param      psDeviceNode - device PDump pertains to
  * @param      hString - PDump OS layer handle of string buffer to write
  * @param      ui32Flags - PDump flags
  * @return     IMG_TRUE on success.
  */
-IMG_BOOL PDumpWriteScript(IMG_HANDLE hString, IMG_UINT32 ui32Flags);
+IMG_BOOL PDumpWriteScript(PVRSRV_DEVICE_NODE *psDeviceNode,
+                          IMG_HANDLE hString, IMG_UINT32 ui32Flags);
 
 /**************************************************************************/ /*!
 @Function       PDumpSNPrintf
@@ -594,7 +610,8 @@ PVRSRV_ERROR PDumpSNPrintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CH
         dest = ((&ref) >> SHRamount << SHLamount) & MASK
 */
 PVRSRV_ERROR
-PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
+PDumpWriteShiftedMaskedValue(PVRSRV_DEVICE_NODE *psDeviceNode,
+                             const IMG_CHAR *pszDestRegspaceName,
                              const IMG_CHAR *pszDestSymbolicName,
                              IMG_DEVMEM_OFFSET_T uiDestOffset,
                              const IMG_CHAR *pszRefRegspaceName,
@@ -611,7 +628,8 @@ PDumpWriteShiftedMaskedValue(const IMG_CHAR *pszDestRegspaceName,
        writes the address of the "reference" to the offset given
 */
 PVRSRV_ERROR
-PDumpWriteSymbAddress(const IMG_CHAR *pszDestSpaceName,
+PDumpWriteSymbAddress(PVRSRV_DEVICE_NODE *psDeviceNode,
+                      const IMG_CHAR *pszDestSpaceName,
                       IMG_DEVMEM_OFFSET_T uiDestOffset,
                       const IMG_CHAR *pszRefSymbolicName,
                       IMG_DEVMEM_OFFSET_T uiRefOffset,
@@ -653,10 +671,14 @@ PDumpUnregisterTransitionCallbackFenceSync(void *pvHandle);
 
 /* Notify PDump of a Transition into/out of capture range */
 PVRSRV_ERROR
-PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+PDumpTransition(PVRSRV_DEVICE_NODE *psDeviceNode,
+                PDUMP_CONNECTION_DATA *psPDumpConnectionData,
                 PDUMP_TRANSITION_EVENT eEvent,
                 IMG_UINT32 ui32PDumpFlags);
 
+/* Check if writing to a PDump file is permitted for the given device */
+IMG_BOOL PDumpIsDevicePermitted(PVRSRV_DEVICE_NODE *psDeviceNode);
+
 /* _ui32PDumpFlags must be a variable in the local scope */
 #define PDUMP_LOCK(_ui32PDumpFlags) do \
        { if ((_ui32PDumpFlags & PDUMP_FLAGS_PDUMP_LOCK_HELD) == 0)\
@@ -681,18 +703,15 @@ PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
 #define PDUMPREG64                             PDumpReg64
 #define PDUMPREGREAD32                 PDumpRegRead32
 #define PDUMPREGREAD64                 PDumpRegRead64
-#define PDUMPCOMMENT(...)              PDumpCommentWithFlags(PDUMP_FLAGS_CONTINUOUS, __VA_ARGS__)
+#define PDUMPCOMMENT(d, ...)   PDumpCommentWithFlags(d, PDUMP_FLAGS_CONTINUOUS, __VA_ARGS__)
 #define PDUMPCOMMENTWITHFLAGS  PDumpCommentWithFlags
 #define PDUMPREGPOL                            PDumpRegPolKM
-#define PDUMPPDREG                             PDumpPDReg
-#define PDUMPPDREGWITHFLAGS            PDumpPDRegWithFlags
 #define PDUMPREGBASEDCBP               PDumpRegBasedCBP
 #define PDUMPENDINITPHASE              PDumpStopInitPhase
 #define PDUMPIDLWITHFLAGS              PDumpIDLWithFlags
 #define PDUMPIDL                               PDumpIDL
 #define PDUMPPOWCMDSTART               PDumpPowerTransitionStart
 #define PDUMPPOWCMDEND                 PDumpPowerTransitionEnd
-#define PDUMPPOWCMDINTRANS             PDumpInPowerTransition
 #define PDUMPCOM                               PDumpCOMCommand
 
 /* _ui32PDumpFlags must be a variable in the local scope */
@@ -710,17 +729,17 @@ PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
        } while (0)
 
 /* _ui32PDumpFlags must be a variable in the local scope */
-#define PDUMPIF(_msg,_ui32PDumpFlags) do \
+#define PDUMPIF(_dev,_msg,_ui32PDumpFlags) do \
        {PDUMP_BLKSTART(_ui32PDumpFlags);\
-       PDumpIfKM(_msg,_ui32PDumpFlags);\
+       PDumpIfKM(_dev,_msg,_ui32PDumpFlags);\
        MSC_SUPPRESS_4127\
        } while (0)
 
 #define PDUMPELSE                              PDumpElseKM
 
 /* _ui32PDumpFlags must be a variable in the local scope */
-#define PDUMPFI(_msg,_ui32PDumpFlags) do \
-       { PDumpFiKM(_msg,_ui32PDumpFlags);\
+#define PDUMPFI(_dev,_msg,_ui32PDumpFlags) do \
+       { PDumpFiKM(_dev,_msg,_ui32PDumpFlags);\
        PDUMP_BLKEND(_ui32PDumpFlags);\
        MSC_SUPPRESS_4127\
        } while (0)
@@ -732,10 +751,10 @@ PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
 */
 
 /*! Macro used to record a panic in the PDump script stream */
-#define PDUMP_PANIC(_id, _msg)  ((void)0)
+#define PDUMP_PANIC(_dev, _id, _msg)  ((void)0)
 
 /*! Macro used to record a driver error in the PDump script stream to invalidate the capture */
-#define PDUMP_ERROR(_err, _msg) ((void)0)
+#define PDUMP_ERROR(_dev, _err, _msg) ((void)0)
 
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(PDumpInitCommon)
@@ -750,16 +769,18 @@ PDumpInitCommon(void)
 #pragma inline(PDumpConnectionNotify)
 #endif
 static INLINE void
-PDumpConnectionNotify(void)
+PDumpConnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 }
 
 #ifdef INLINE_IS_PRAGMA
 #pragma inline(PDumpDisconnectionNotify)
 #endif
 static INLINE void
-PDumpDisconnectionNotify(void)
+PDumpDisconnectionNotify(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 }
 
 #ifdef INLINE_IS_PRAGMA
@@ -782,8 +803,9 @@ PDumpUnlock(void)
 #pragma inline(PDumpStopInitPhase)
 #endif
 static INLINE void
-PDumpStopInitPhase(void)
+PDumpStopInitPhase(PVRSRV_DEVICE_NODE *psDeviceNode)
 {
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
 }
 
 #ifdef INLINE_IS_PRAGMA
@@ -816,8 +838,15 @@ PDumpGetFrameKM(CONNECTION_DATA *psConnection,
 #pragma inline(PDumpCommentKM)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
+PDumpCommentKM(CONNECTION_DATA *psConnection,
+               PVRSRV_DEVICE_NODE *psDeviceNode,
+               IMG_UINT32 ui32CommentSize,
+               IMG_CHAR *pszComment,
+               IMG_UINT32 ui32Flags)
 {
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+    PVR_UNREFERENCED_PARAMETER(ui32CommentSize);
        PVR_UNREFERENCED_PARAMETER(pszComment);
        PVR_UNREFERENCED_PARAMETER(ui32Flags);
        return PVRSRV_OK;
@@ -828,12 +857,16 @@ PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
 #pragma inline(PDumpSetDefaultCaptureParamsKM)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpSetDefaultCaptureParamsKM(IMG_UINT32 ui32Mode,
+PDumpSetDefaultCaptureParamsKM(CONNECTION_DATA *psConnection,
+                               PVRSRV_DEVICE_NODE *psDeviceNode,
+                               IMG_UINT32 ui32Mode,
                                IMG_UINT32 ui32Start,
                                IMG_UINT32 ui32End,
                                IMG_UINT32 ui32Interval,
                                IMG_UINT32 ui32MaxParamFileSize)
 {
+       PVR_UNREFERENCED_PARAMETER(psConnection);
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
        PVR_UNREFERENCED_PARAMETER(ui32Mode);
        PVR_UNREFERENCED_PARAMETER(ui32Start);
        PVR_UNREFERENCED_PARAMETER(ui32End);
@@ -897,63 +930,14 @@ PDumpGetStateKM(IMG_UINT64 *ui64State)
 }
 
 #ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpIsCaptureFrameKM)
-#endif
-static INLINE PVRSRV_ERROR
-PDumpIsCaptureFrameKM(IMG_BOOL *bIsCapturing)
-{
-       *bIsCapturing = IMG_FALSE;
-       return PVRSRV_OK;
-}
-
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpGetCurrentBlockKM)
-#endif
-static INLINE PVRSRV_ERROR
-PDumpGetCurrentBlockKM(IMG_UINT32 *pui32BlockNum)
-{
-       *pui32BlockNum = PDUMP_BLOCKNUM_INVALID;
-       return PVRSRV_OK;
-}
-
-#ifdef INLINE_IS_PRAGMA
 #pragma inline(PDumpForceCaptureStopKM)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpForceCaptureStopKM(void)
-{
-       return PVRSRV_OK;
-}
-
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpBitmapKM)
-#endif
-static INLINE PVRSRV_ERROR
-PDumpBitmapKM(PVRSRV_DEVICE_NODE *psDeviceNode,
-              IMG_CHAR *pszFileName,
-              IMG_UINT32 ui32FileOffset,
-              IMG_UINT32 ui32Width,
-              IMG_UINT32 ui32Height,
-              IMG_UINT32 ui32StrideInBytes,
-              IMG_DEV_VIRTADDR sDevBaseAddr,
-              IMG_UINT32 ui32MMUContextID,
-              IMG_UINT32 ui32Size,
-              PDUMP_PIXEL_FORMAT ePixelFormat,
-              IMG_UINT32 ui32AddrMode,
-              IMG_UINT32 ui32PDumpFlags)
+PDumpForceCaptureStopKM(CONNECTION_DATA *psConnection,
+                        PVRSRV_DEVICE_NODE *psDeviceNode)
 {
+       PVR_UNREFERENCED_PARAMETER(psConnection);
        PVR_UNREFERENCED_PARAMETER(psDeviceNode);
-       PVR_UNREFERENCED_PARAMETER(pszFileName);
-       PVR_UNREFERENCED_PARAMETER(ui32FileOffset);
-       PVR_UNREFERENCED_PARAMETER(ui32Width);
-       PVR_UNREFERENCED_PARAMETER(ui32Height);
-       PVR_UNREFERENCED_PARAMETER(ui32StrideInBytes);
-       PVR_UNREFERENCED_PARAMETER(sDevBaseAddr);
-       PVR_UNREFERENCED_PARAMETER(ui32MMUContextID);
-       PVR_UNREFERENCED_PARAMETER(ui32Size);
-       PVR_UNREFERENCED_PARAMETER(ePixelFormat);
-       PVR_UNREFERENCED_PARAMETER(ui32AddrMode);
-       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
        return PVRSRV_OK;
 }
 
@@ -1103,10 +1087,12 @@ PDumpUnregisterTransitionCallbackFenceSync(void *pvHandle)
 #pragma inline(PDumpTransition)
 #endif
 static INLINE PVRSRV_ERROR
-PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
+PDumpTransition(PVRSRV_DEVICE_NODE *psDeviceNode,
+                PDUMP_CONNECTION_DATA *psPDumpConnectionData,
                 PDUMP_TRANSITION_EVENT eEvent,
                 IMG_UINT32 ui32PDumpFlags)
 {
+       PVR_UNREFERENCED_PARAMETER(psDeviceNode);
        PVR_UNREFERENCED_PARAMETER(psPDumpConnectionData);
        PVR_UNREFERENCED_PARAMETER(eEvent);
        PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
@@ -1122,8 +1108,6 @@ PDumpTransition(PDUMP_CONNECTION_DATA *psPDumpConnectionData,
        #define PDUMPREGREAD64(args...)
        #define PDUMPCOMMENT(args...)
        #define PDUMPREGPOL(args...)
-       #define PDUMPPDREG(args...)
-       #define PDUMPPDREGWITHFLAGS(args...)
        #define PDUMPSYNC(args...)
        #define PDUMPCOPYTOMEM(args...)
        #define PDUMPWRITE(args...)
index a533639..b67a402 100644 (file)
@@ -52,6 +52,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #include "mmu_common.h"
 
+#include "opaque_types.h"
+
 /*
  * PDUMP MMU attributes
  */
@@ -87,7 +89,8 @@ typedef struct _PDUMP_MMU_ATTRIB_
 
 #if defined(PDUMP)
 PVRSRV_ERROR
-PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
+PDumpMMUMalloc(PPVRSRV_DEVICE_NODE psDeviceNode,
+               const IMG_CHAR *pszPDumpDevName,
                MMU_LEVEL eMMULevel,
                IMG_DEV_PHYADDR *psDevPAddr,
                IMG_UINT32 ui32Size,
@@ -95,7 +98,8 @@ PDumpMMUMalloc(const IMG_CHAR *pszPDumpDevName,
                PDUMP_MMU_TYPE eMMUType);
 
 PVRSRV_ERROR
-PDumpMMUFree(const IMG_CHAR *pszPDumpDevName,
+PDumpMMUFree(PPVRSRV_DEVICE_NODE psDeviceNode,
+             const IMG_CHAR *pszPDumpDevName,
              MMU_LEVEL eMMULevel,
              IMG_DEV_PHYADDR *psDevPAddr,
              PDUMP_MMU_TYPE eMMUType);
@@ -111,7 +115,8 @@ PDumpPTBaseObjectToMem64(const IMG_CHAR *pszPDumpDevName,
                          IMG_UINT64 ui64PxOffset);
 
 PVRSRV_ERROR
-PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
+PDumpMMUDumpPxEntries(PPVRSRV_DEVICE_NODE psDeviceNode,
+                      MMU_LEVEL eMMULevel,
                       const IMG_CHAR *pszPDumpDevName,
                       void *pvPxMem,
                       IMG_DEV_PHYADDR sPxDevPAddr,
@@ -130,19 +135,22 @@ PDumpMMUDumpPxEntries(MMU_LEVEL eMMULevel,
                       PDUMP_MMU_TYPE eMMUType);
 
 PVRSRV_ERROR
-PDumpMMUAllocMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+PDumpMMUAllocMMUContext(PPVRSRV_DEVICE_NODE psDeviceNode,
+                        const IMG_CHAR *pszPDumpMemSpaceName,
                         IMG_DEV_PHYADDR sPCDevPAddr,
                         PDUMP_MMU_TYPE eMMUType,
                         IMG_UINT32 *pui32MMUContextID,
                         IMG_UINT32 ui32PDumpFlags);
 
 PVRSRV_ERROR
-PDumpMMUFreeMMUContext(const IMG_CHAR *pszPDumpMemSpaceName,
+PDumpMMUFreeMMUContext(PPVRSRV_DEVICE_NODE psDeviceNode,
+                       const IMG_CHAR *pszPDumpMemSpaceName,
                        IMG_UINT32 ui32MMUContextID,
                        IMG_UINT32 ui32PDumpFlags);
 
 PVRSRV_ERROR
-PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
+PDumpMMUSAB(PPVRSRV_DEVICE_NODE psDeviceNode,
+            const IMG_CHAR *pszPDumpMemNamespace,
             IMG_UINT32 uiPDumpMMUCtx,
             IMG_DEV_VIRTADDR sDevAddrStart,
             IMG_DEVMEM_SIZE_T uiSize,
@@ -150,20 +158,21 @@ PDumpMMUSAB(const IMG_CHAR *pszPDumpMemNamespace,
             IMG_UINT32 uiFileOffset,
             IMG_UINT32 ui32PDumpFlags);
 
-#define PDUMP_MMU_ALLOC_MMUCONTEXT(pszPDumpMemDevName, sPCDevPAddr, eMMUType, puiPDumpCtxID, ui32PDumpFlags) \
-        PDumpMMUAllocMMUContext(pszPDumpMemDevName,                     \
+#define PDUMP_MMU_ALLOC_MMUCONTEXT(psDevNode, pszPDumpMemDevName, sPCDevPAddr, eMMUType, puiPDumpCtxID, ui32PDumpFlags) \
+        PDumpMMUAllocMMUContext(psDevNode,                              \
+                                pszPDumpMemDevName,                     \
                                 sPCDevPAddr,                            \
                                 eMMUType,                               \
                                 puiPDumpCtxID,                          \
                                 ui32PDumpFlags)
 
-#define PDUMP_MMU_FREE_MMUCONTEXT(pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags) \
-        PDumpMMUFreeMMUContext(pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags)
+#define PDUMP_MMU_FREE_MMUCONTEXT(psDevNode, pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags) \
+        PDumpMMUFreeMMUContext(psDevNode, pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags)
 #else /* PDUMP */
 
 #define PDUMP_MMU_ALLOC_MMUCONTEXT(pszPDumpMemDevName, sPCDevPAddr, eMMUType, puiPDumpCtxID, ui32PDumpFlags) \
         ((void)0)
-#define PDUMP_MMU_FREE_MMUCONTEXT(pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags) \
+#define PDUMP_MMU_FREE_MMUCONTEXT(psDevNode, pszPDumpMemDevName, uiPDumpCtxID, ui32PDumpFlags) \
         ((void)0)
 
 #endif /* PDUMP */
index d2fc563..a5a6f37 100644 (file)
@@ -48,6 +48,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "img_defs.h"
 #include "pvrsrv_error.h"
 #include "pmr.h"
+#include "device.h" /* For device node */
 
 #define PHYSMEM_PDUMP_MEMSPACE_MAX_LENGTH 40
 #define PHYSMEM_PDUMP_SYMNAME_MAX_LENGTH 60
@@ -61,7 +62,8 @@ PDumpGetSymbolicAddr(const IMG_HANDLE hPhysmemPDumpHandle,
                      IMG_CHAR **ppszSymbolicAddress);
 
 PVRSRV_ERROR
-PDumpMalloc(const IMG_CHAR *pszDevSpace,
+PDumpMalloc(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszDevSpace,
             const IMG_CHAR *pszSymbolicAddress,
             IMG_UINT64 ui64Size,
             /* alignment is alignment of start of buffer _and_
@@ -74,7 +76,8 @@ PDumpMalloc(const IMG_CHAR *pszDevSpace,
             IMG_UINT32 ui32PDumpFlags);
 
 PVRSRV_ERROR
-PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle);
+PDumpFree(PVRSRV_DEVICE_NODE *psDeviceNode,
+          IMG_HANDLE hPDumpAllocationInfoHandle);
 
 void
 PDumpMakeStringValid(IMG_CHAR *pszString,
@@ -140,49 +143,56 @@ PDumpFree(IMG_HANDLE hPDumpAllocationInfoHandle)
 #endif /* PDUMP */
 
 PVRSRV_ERROR
-PDumpPMRWRW32(const IMG_CHAR *pszDevSpace,
-            const IMG_CHAR *pszSymbolicName,
-            IMG_DEVMEM_OFFSET_T uiOffset,
-            IMG_UINT32 ui32Value,
-            PDUMP_FLAGS_T uiPDumpFlags);
+PDumpPMRWRW32(PVRSRV_DEVICE_NODE *psDeviceNode,
+              const IMG_CHAR *pszDevSpace,
+              const IMG_CHAR *pszSymbolicName,
+              IMG_DEVMEM_OFFSET_T uiOffset,
+              IMG_UINT32 ui32Value,
+              PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRWRW32InternalVarToMem(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW32InternalVarToMem(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               const IMG_CHAR *pszInternalVar,
                               PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRRDW32MemToInternalVar(const IMG_CHAR *pszInternalVar,
+PDumpPMRRDW32MemToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszInternalVar,
                               const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRWRW64(const IMG_CHAR *pszDevSpace,
-            const IMG_CHAR *pszSymbolicName,
-            IMG_DEVMEM_OFFSET_T uiOffset,
-            IMG_UINT64 ui64Value,
-            PDUMP_FLAGS_T uiPDumpFlags);
+PDumpPMRWRW64(PVRSRV_DEVICE_NODE *psDeviceNode,
+              const IMG_CHAR *pszDevSpace,
+              const IMG_CHAR *pszSymbolicName,
+              IMG_DEVMEM_OFFSET_T uiOffset,
+              IMG_UINT64 ui64Value,
+              PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRWRW64InternalVarToMem(const IMG_CHAR *pszDevSpace,
+PDumpPMRWRW64InternalVarToMem(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               const IMG_CHAR *pszInternalVar,
                               PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRRDW64MemToInternalVar(const IMG_CHAR *pszInternalVar,
+PDumpPMRRDW64MemToInternalVar(PVRSRV_DEVICE_NODE *psDeviceNode,
+                              const IMG_CHAR *pszInternalVar,
                               const IMG_CHAR *pszDevSpace,
                               const IMG_CHAR *pszSymbolicName,
                               IMG_DEVMEM_OFFSET_T uiOffset,
                               PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
+PDumpPMRLDB(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszDevSpace,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiOffset,
             IMG_DEVMEM_SIZE_T uiSize,
@@ -191,7 +201,8 @@ PDumpPMRLDB(const IMG_CHAR *pszDevSpace,
             PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
+PDumpPMRSAB(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszDevSpace,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiOffset,
             IMG_DEVMEM_SIZE_T uiSize,
@@ -204,7 +215,8 @@ PDumpPMRSAB(const IMG_CHAR *pszDevSpace,
   Emits a POL to the PDUMP.
 */
 PVRSRV_ERROR
-PDumpPMRPOL(const IMG_CHAR *pszMempaceName,
+PDumpPMRPOL(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszMempaceName,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiOffset,
             IMG_UINT32 ui32Value,
@@ -215,7 +227,8 @@ PDumpPMRPOL(const IMG_CHAR *pszMempaceName,
             PDUMP_FLAGS_T uiPDumpFlags);
 
 PVRSRV_ERROR
-PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
+PDumpPMRCBP(PVRSRV_DEVICE_NODE *psDeviceNode,
+            const IMG_CHAR *pszMemspaceName,
             const IMG_CHAR *pszSymbolicName,
             IMG_DEVMEM_OFFSET_T uiReadOffset,
             IMG_DEVMEM_OFFSET_T uiWriteOffset,
@@ -233,7 +246,8 @@ PDumpPMRCBP(const IMG_CHAR *pszMemspaceName,
  * that buffer.
  */
 PVRSRV_ERROR
-PDumpWriteParameterBlob(IMG_UINT8 *pcBuffer,
+PDumpWriteParameterBlob(PVRSRV_DEVICE_NODE *psDeviceNode,
+                        IMG_UINT8 *pcBuffer,
                         size_t uiNumBytes,
                         PDUMP_FLAGS_T uiPDumpFlags,
                         IMG_CHAR *pszFilenameOut,
index 1f271ee..ca293e9 100644 (file)
@@ -159,7 +159,8 @@ PhysmemNewRamBackedPMR(CONNECTION_DATA * psConnection,
                        const IMG_CHAR *pszAnnotation,
                        IMG_PID uiPid,
                        PMR **ppsPMROut,
-                       IMG_UINT32 ui32PDumpFlags);
+                       IMG_UINT32 ui32PDumpFlags,
+                       PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags);
 
 PVRSRV_ERROR
 PhysmemNewRamBackedPMR_direct(CONNECTION_DATA * psConnection,
@@ -175,7 +176,8 @@ PhysmemNewRamBackedPMR_direct(CONNECTION_DATA * psConnection,
                                                          const IMG_CHAR *pszAnnotation,
                                                          IMG_PID uiPid,
                                                          PMR **ppsPMROut,
-                                                         IMG_UINT32 ui32PDumpFlags);
+                                                         IMG_UINT32 ui32PDumpFlags,
+                                                         PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags);
 
 /*
  * PhysmemNewRamBackedLockedPMR
@@ -206,7 +208,8 @@ PhysmemNewRamBackedLockedPMR(CONNECTION_DATA * psConnection,
                              const IMG_CHAR *pszAnnotation,
                              IMG_PID uiPid,
                              PMR **ppsPMRPtr,
-                             IMG_UINT32 ui32PDumpFlags);
+                             IMG_UINT32 ui32PDumpFlags,
+                             PVRSRV_MEMALLOCFLAGS_T *puiPMRFlags);
 
 /*************************************************************************/ /*!
 @Function       PhysmemImportPMR
@@ -234,16 +237,85 @@ PhysmemImportPMR(CONNECTION_DATA *psConnection,
                  PMR **ppsPMR);
 
 /*************************************************************************/ /*!
-@Function       PVRSRVGetMaxDevMemSizeKM
-@Description    Get the amount of device memory on current platform
-@Output         puiLMASize             LMA memory size
-@Output         puiUMASize             UMA memory size
-@Return         None
+@Function       PVRSRVGetMaxPhysHeapCountKM
+@Description    Get the user accessible physical heap count
+@Output         puiPhysHeapCount   user accessible physical heap count
+@Return         PVRSRV_OK if successful
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVGetMaxPhysHeapCountKM(CONNECTION_DATA *psConnection,
+                           PVRSRV_DEVICE_NODE *psDevNode,
+                           IMG_UINT32 *puiPhysHeapCount);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVGetDefaultPhysicalHeapKM
+@Description    For the specified device, get the physical heap used for
+                allocations when the PVRSRV_PHYS_HEAP_DEFAULT
+                physical heap hint is set in memalloc flags.
+@Output         peHeap                 Default Heap return value
+@Return         PVRSRV_OK if successful
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVGetDefaultPhysicalHeapKM(CONNECTION_DATA *psConnection,
+                         PVRSRV_DEVICE_NODE *psDevNode,
+                         PVRSRV_PHYS_HEAP *peHeap);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVGetHeapPhysMemUsageKM
+@Description    Get the memory usage statistics for all user accessible
+                physical heaps
+@Input          ui32PhysHeapCount      Total user accessible physical heaps
+@Output         apPhysHeapMemStats     Buffer to hold the memory statistics
+@Return         PVRSRV_OK if successful
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVGetHeapPhysMemUsageKM(CONNECTION_DATA *psConnection,
+                           PVRSRV_DEVICE_NODE *psDevNode,
+                           IMG_UINT32 ui32PhysHeapCount,
+                           PHYS_HEAP_MEM_STATS *apPhysHeapMemStats);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVGetHeapPhysMemUsagePkdKM
+@Description    Get the memory usage statistics for all user accessible
+                physical heaps
+@Input          ui32PhysHeapCount      Total user accessible physical heaps
+@Output         apPhysHeapMemStats     Buffer to hold the memory statistics
+@Return         PVRSRV_OK if successful
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVGetHeapPhysMemUsagePkdKM(CONNECTION_DATA *psConnection,
+                           PVRSRV_DEVICE_NODE *psDevNode,
+                           IMG_UINT32 ui32PhysHeapCount,
+                           PHYS_HEAP_MEM_STATS_PKD *apPhysHeapMemStats);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVPhysHeapGetMemInfoKM
+@Description    Get the memory usage statistics for a given physical heap ID
+@Input          ui32PhysHeapCount      Physical Heap count
+@Input          paePhysHeapID          Array of Physical Heap ID's
+@Output         paPhysHeapMemStats     Buffer to hold the memory statistics
+@Return         PVRSRV_OK if successful
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVPhysHeapGetMemInfoKM(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_UINT32 ui32PhysHeapCount,
+                          PVRSRV_PHYS_HEAP *paePhysHeapID,
+                          PHYS_HEAP_MEM_STATS *paPhysHeapMemStats);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVPhysHeapGetMemInfoPkdKM
+@Description    Get the memory usage statistics for a given physical heap ID
+@Input          ui32PhysHeapCount      Physical Heap count
+@Input          paePhysHeapID          Array of Physical Heap ID's
+@Output         paPhysHeapMemStats     Buffer to hold the memory statistics
+@Return         PVRSRV_OK if successful
 */ /**************************************************************************/
 PVRSRV_ERROR
-PVRSRVGetMaxDevMemSizeKM(CONNECTION_DATA * psConnection,
-                         PVRSRV_DEVICE_NODE *psDevNode,
-                         IMG_DEVMEM_SIZE_T *puiLMASize,
-                         IMG_DEVMEM_SIZE_T *puiUMASize);
+PVRSRVPhysHeapGetMemInfoPkdKM(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_UINT32 ui32PhysHeapCount,
+                          PVRSRV_PHYS_HEAP *paePhysHeapID,
+                          PHYS_HEAP_MEM_STATS_PKD *paPhysHeapMemStats);
 
 #endif /* SRVSRV_PHYSMEM_H */
index 4a32824..99b5c33 100644 (file)
@@ -96,6 +96,17 @@ PhysmemImportDmaBuf(CONNECTION_DATA *psConnection,
                     IMG_DEVMEM_ALIGN_T *puiAlign);
 
 PVRSRV_ERROR
+PhysmemImportDmaBufLocked(CONNECTION_DATA *psConnection,
+                          PVRSRV_DEVICE_NODE *psDevNode,
+                          IMG_INT fd,
+                          PVRSRV_MEMALLOCFLAGS_T uiFlags,
+                          IMG_UINT32 ui32NameSize,
+                          const IMG_CHAR pszName[DEVMEM_ANNOTATION_MAX_LEN],
+                          PMR **ppsPMRPtr,
+                          IMG_DEVMEM_SIZE_T *puiSize,
+                          IMG_DEVMEM_ALIGN_T *puiAlign);
+
+PVRSRV_ERROR
 PhysmemImportSparseDmaBuf(CONNECTION_DATA *psConnection,
                           PVRSRV_DEVICE_NODE *psDevNode,
                           IMG_INT fd,
index 2988730..51f4257 100644 (file)
@@ -69,10 +69,6 @@ PhysmemCreateHeapLMA(PVRSRV_DEVICE_NODE *psDevNode,
                                         IMG_CHAR *pszLabel,
                                         PHYS_HEAP **ppsPhysHeap);
 
-PVRSRV_ERROR
-PhysmemGetArenaLMA(PHYS_HEAP *psPhysHeap,
-                                  RA_ARENA **ppsArena);
-
 /*
  * PhysmemNewLocalRamBackedPMR
  *
index ceb2ed2..1eb7565 100644 (file)
@@ -60,6 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pmr.h"
 #include "pmr_impl.h"
 #include "connection_server.h"
+#include "physheap.h"
 
 /*************************************************************************/ /*!
 @Function       PhysmemNewOSRamBackedPMR
@@ -113,7 +114,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */ /**************************************************************************/
 PVRSRV_ERROR
 PhysmemNewOSRamBackedPMR(PHYS_HEAP *psPhysHeap,
-                                                CONNECTION_DATA *psConnection,
+                         CONNECTION_DATA *psConnection,
                          IMG_DEVMEM_SIZE_T uiSize,
                          IMG_DEVMEM_SIZE_T uiChunkSize,
                          IMG_UINT32 ui32NumPhysChunks,
@@ -126,4 +127,16 @@ PhysmemNewOSRamBackedPMR(PHYS_HEAP *psPhysHeap,
                          PMR **ppsPMROut,
                          IMG_UINT32 ui32PDumpFlags);
 
+/*************************************************************************/ /*!
+@Function       PhysmemGetOSRamMemStats
+@Description    Function that gets the OS memory usage statistics
+@Input          pvImplData     Physical heap private data.
+@Output         pui64TotalSize Buffer that holds the total OS memory size
+@Output         pui64FreeSize  Buffer that holds the free OS memory size
+@Return         None.
+*/ /**************************************************************************/
+void PhysmemGetOSRamMemStats(PHEAP_IMPL_DATA pvImplData,
+                            IMG_UINT64 *pui64TotalSize,
+                            IMG_UINT64 *pui64FreeSize);
+
 #endif /* PHYSMEM_OSMEM_H */
index 231dfd7..6a1f0e8 100644 (file)
@@ -423,17 +423,6 @@ PVRSRV_ERROR
 PMRReleaseKernelMappingData(PMR *psPMR,
                             IMG_HANDLE hPriv);
 
-#if defined(INTEGRITY_OS)
-PVRSRV_ERROR
-PMRMapMemoryObject(PMR *psPMR,
-                   IMG_HANDLE *phMemObj,
-                   void **pvClientAddr,
-                   IMG_HANDLE *phPrivOut);
-PVRSRV_ERROR
-PMRUnmapMemoryObject(PMR *psPMR,
-                     IMG_HANDLE hPriv);
-#endif
-
 /*
  * PMR_ReadBytes()
  *
@@ -548,7 +537,7 @@ PMR_IsSparse(const PMR *psPMR);
 IMG_BOOL
 PMR_IsUnpinned(const PMR *psPMR);
 
-PVRSRV_ERROR
+void
 PMR_LogicalSize(const PMR *psPMR,
                                IMG_DEVMEM_SIZE_T *puiLogicalSize);
 
@@ -667,38 +656,6 @@ PVRSRV_ERROR PMR_ChangeSparseMemCPUMap(PMR *psPMR,
 
 #if defined(PDUMP)
 
-void
-PDumpPMRMallocPMR(PMR *psPMR,
-                  IMG_DEVMEM_SIZE_T uiSize,
-                  IMG_DEVMEM_ALIGN_T uiBlockSize,
-                  IMG_UINT32 ui32ChunkSize,
-                  IMG_UINT32 ui32NumPhysChunks,
-                  IMG_UINT32 ui32NumVirtChunks,
-                  IMG_UINT32 *puiMappingTable,
-                  IMG_UINT32 uiLog2Contiguity,
-                  IMG_BOOL bInitialise,
-                  IMG_UINT32 ui32InitValue,
-                  IMG_HANDLE *phPDumpAllocInfoPtr,
-                  IMG_UINT32 ui32PDumpFlags);
-
-void
-PDumpPMRFreePMR(PMR *psPMR,
-                IMG_DEVMEM_SIZE_T uiSize,
-                IMG_DEVMEM_ALIGN_T uiBlockSize,
-                IMG_UINT32 uiLog2Contiguity,
-                IMG_HANDLE hPDumpAllocationInfoHandle);
-
-void
-PDumpPMRChangeSparsePMR(PMR *psPMR,
-                        IMG_UINT32 uiBlockSize,
-                        IMG_UINT32 ui32AllocPageCount,
-                        IMG_UINT32 *pai32AllocIndices,
-                        IMG_UINT32 ui32FreePageCount,
-                        IMG_UINT32 *pai32FreeIndices,
-                        IMG_BOOL bInitialise,
-                        IMG_UINT32 ui32InitValue,
-                        IMG_HANDLE *phPDumpAllocInfoOut);
-
 /*
  * PMR_PDumpSymbolicAddr()
  *
@@ -820,77 +777,6 @@ PMRPDumpSaveToFile(const PMR *psPMR,
 #else /* PDUMP */
 
 #ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpPMRMallocPMR)
-#endif
-static INLINE void
-PDumpPMRMallocPMR(PMR *psPMR,
-                  IMG_DEVMEM_SIZE_T uiSize,
-                  IMG_DEVMEM_ALIGN_T uiBlockSize,
-                  IMG_UINT32 ui32NumPhysChunks,
-                  IMG_UINT32 ui32NumVirtChunks,
-                  IMG_UINT32 *puiMappingTable,
-                  IMG_UINT32 uiLog2Contiguity,
-                  IMG_BOOL bInitialise,
-                  IMG_UINT32 ui32InitValue,
-                  IMG_HANDLE *phPDumpAllocInfoPtr,
-                  IMG_UINT32 ui32PDumpFlags)
-{
-       PVR_UNREFERENCED_PARAMETER(psPMR);
-       PVR_UNREFERENCED_PARAMETER(uiSize);
-       PVR_UNREFERENCED_PARAMETER(uiBlockSize);
-       PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
-       PVR_UNREFERENCED_PARAMETER(ui32NumVirtChunks);
-       PVR_UNREFERENCED_PARAMETER(puiMappingTable);
-       PVR_UNREFERENCED_PARAMETER(uiLog2Contiguity);
-       PVR_UNREFERENCED_PARAMETER(bInitialise);
-       PVR_UNREFERENCED_PARAMETER(ui32InitValue);
-       PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoPtr);
-       PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
-}
-
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpPMRFreePMR)
-#endif
-static INLINE void
-PDumpPMRFreePMR(PMR *psPMR,
-                IMG_DEVMEM_SIZE_T uiSize,
-                IMG_DEVMEM_ALIGN_T uiBlockSize,
-                IMG_UINT32 uiLog2Contiguity,
-                IMG_HANDLE hPDumpAllocationInfoHandle)
-{
-       PVR_UNREFERENCED_PARAMETER(psPMR);
-       PVR_UNREFERENCED_PARAMETER(uiSize);
-       PVR_UNREFERENCED_PARAMETER(uiBlockSize);
-       PVR_UNREFERENCED_PARAMETER(uiLog2Contiguity);
-       PVR_UNREFERENCED_PARAMETER(hPDumpAllocationInfoHandle);
-}
-
-#ifdef INLINE_IS_PRAGMA
-#pragma inline(PDumpPMRChangeSparsePMR)
-#endif
-static INLINE void
-PDumpPMRChangeSparsePMR(PMR *psPMR,
-                        IMG_UINT32 uiBlockSize,
-                        IMG_UINT32 ui32AllocPageCount,
-                        IMG_UINT32 *pai32AllocIndices,
-                        IMG_UINT32 ui32FreePageCount,
-                        IMG_UINT32 *pai32FreeIndices,
-                        IMG_BOOL bInitialise,
-                        IMG_UINT32 ui32InitValue,
-                        IMG_HANDLE *phPDumpAllocInfoOut)
-{
-       PVR_UNREFERENCED_PARAMETER(psPMR);
-       PVR_UNREFERENCED_PARAMETER(uiBlockSize);
-       PVR_UNREFERENCED_PARAMETER(ui32AllocPageCount);
-       PVR_UNREFERENCED_PARAMETER(pai32AllocIndices);
-       PVR_UNREFERENCED_PARAMETER(ui32FreePageCount);
-       PVR_UNREFERENCED_PARAMETER(pai32FreeIndices);
-       PVR_UNREFERENCED_PARAMETER(bInitialise);
-       PVR_UNREFERENCED_PARAMETER(ui32InitValue);
-       PVR_UNREFERENCED_PARAMETER(phPDumpAllocInfoOut);
-}
-
-#ifdef INLINE_IS_PRAGMA
 #pragma inline(PMR_PDumpSymbolicAddr)
 #endif
 static INLINE PVRSRV_ERROR
@@ -1129,9 +1015,6 @@ PMRInit(void);
 PVRSRV_ERROR
 PMRDeInit(void);
 
-extern void show_pmr_info(PMR *psPMR);
-extern size_t pmr_size(PMR *psPMR);
-
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
 PVRSRV_ERROR
 PMRStoreRIHandle(PMR *psPMR, void *hRIHandle);
index c36776d..cae0b7e 100644 (file)
@@ -51,9 +51,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "img_defs.h"
 #include "pvrsrv_error.h"
 
-
-//#define  CACHE_TEST
-
 /*! Physical Memory Resource type.
  */
 typedef struct _PMR_ PMR;
@@ -205,24 +202,12 @@ typedef PVRSRV_ERROR (*PFN_DEV_PHYS_ADDR_FN)(PMR_IMPL_PRIVDATA pvPriv,
 @Return         PVRSRV_OK if the mapping was successful, an error code
                 otherwise.
 */ /**************************************************************************/
-
-#ifdef CACHE_TEST
 typedef PVRSRV_ERROR (*PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvPriv,
                       size_t uiOffset,
                       size_t uiSize,
-                      size_t uilogicSize,
                       void **ppvKernelAddressOut,
                       IMG_HANDLE *phHandleOut,
                       PMR_FLAGS_T ulFlags);
-#else
-
-typedef PVRSRV_ERROR (*PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvPriv,
-                      size_t uiOffset,
-                      size_t uiSize,
-                      void **ppvKernelAddressOut,
-                      IMG_HANDLE *phHandleOut,
-                      PMR_FLAGS_T ulFlags);
-#endif
 
 /*************************************************************************/ /*!
 @Brief          Callback function type PFN_RELEASE_KERNEL_MAPPING_DATA_FN
@@ -241,7 +226,7 @@ typedef PVRSRV_ERROR (*PFN_ACQUIRE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvP
 @Return         None
 */ /**************************************************************************/
 typedef void (*PFN_RELEASE_KERNEL_MAPPING_DATA_FN)(PMR_IMPL_PRIVDATA pvPriv,
-              IMG_HANDLE hHandle, PMR *psPMR);
+              IMG_HANDLE hHandle);
 
 /*************************************************************************/ /*!
 @Brief          Callback function type PFN_READ_BYTES_FN
@@ -519,20 +504,6 @@ struct _PMR_IMPL_FUNCTAB_ {
     /*! Callback function pointer, see ::PFN_RELEASE_KERNEL_MAPPING_DATA_FN */
     PFN_RELEASE_KERNEL_MAPPING_DATA_FN pfnReleaseKernelMappingData;
 
-#if defined(INTEGRITY_OS)
-    /*
-     * MapMemoryObject()/UnmapMemoryObject()
-     *
-     * called to map/unmap memory objects in Integrity OS
-     */
-
-    PVRSRV_ERROR (*pfnMapMemoryObject)(PMR_IMPL_PRIVDATA pvPriv,
-                  IMG_HANDLE *phMemObj,
-                  void **pvClientAddr,
-                  IMG_HANDLE *phHandleOut);
-    PVRSRV_ERROR (*pfnUnmapMemoryObject)(PMR_IMPL_PRIVDATA pvPriv);
-#endif
-
     /*! Callback function pointer, see ::PFN_READ_BYTES_FN */
     PFN_READ_BYTES_FN pfnReadBytes;
     /*! Callback function pointer, see ::PFN_WRITE_BYTES_FN */
index 32a4638..333e799 100644 (file)
@@ -59,6 +59,24 @@ typedef struct _PVRSRV_POWER_DEV_TAG_ PVRSRV_POWER_DEV;
 
 typedef IMG_BOOL (*PFN_SYS_DEV_IS_DEFAULT_STATE_OFF)(PVRSRV_POWER_DEV *psPowerDevice);
 
+/* Power transition handler prototypes */
+
+/*!
+  Typedef for a pointer to a Function that will be called before a transition
+  from one power state to another. See also PFN_POST_POWER.
+ */
+typedef PVRSRV_ERROR (*PFN_PRE_POWER) (IMG_HANDLE                              hDevHandle,
+                                                                          PVRSRV_DEV_POWER_STATE       eNewPowerState,
+                                                                          PVRSRV_DEV_POWER_STATE       eCurrentPowerState,
+                                                                          PVRSRV_POWER_FLAGS           ePwrFlags);
+/*!
+  Typedef for a pointer to a Function that will be called after a transition
+  from one power state to another. See also PFN_PRE_POWER.
+ */
+typedef PVRSRV_ERROR (*PFN_POST_POWER) (IMG_HANDLE                             hDevHandle,
+                                                                               PVRSRV_DEV_POWER_STATE  eNewPowerState,
+                                                                               PVRSRV_DEV_POWER_STATE  eCurrentPowerState,
+                                                                               PVRSRV_POWER_FLAGS              ePwrFlags);
 
 PVRSRV_ERROR PVRSRVPowerLockInit(PPVRSRV_DEVICE_NODE psDeviceNode);
 void PVRSRVPowerLockDeInit(PPVRSRV_DEVICE_NODE psDeviceNode);
@@ -124,25 +142,27 @@ IMG_BOOL PVRSRVDeviceIsDefaultStateOFF(PVRSRV_POWER_DEV *psPowerDevice);
 
  @Input                psDeviceNode : Device node
  @Input                eNewPowerState : New power state
- @Input                bForced : TRUE if the transition should not fail (e.g. OS request)
+ @Input                ePwrFlags : Power state change flags
 
  @Return       PVRSRV_ERROR
 
 ******************************************************************************/
 PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(PPVRSRV_DEVICE_NODE   psDeviceNode,
                                                                                 PVRSRV_DEV_POWER_STATE eNewPowerState,
-                                                                                IMG_BOOL                               bForced);
+                                                                                PVRSRV_POWER_FLAGS             ePwrFlags);
 
 /*************************************************************************/ /*!
 @Function     PVRSRVSetDeviceSystemPowerState
 @Description  Set the device into a new power state based on the systems power
               state
-@Input        psDeviceNode          Device node
+@Input        psDeviceNode       Device node
 @Input        eNewSysPowerState  New system power state
+@Input        ePwrFlags          Power state change flags
 @Return       PVRSRV_ERROR       PVRSRV_OK on success or an error otherwise
 */ /**************************************************************************/
 PVRSRV_ERROR PVRSRVSetDeviceSystemPowerState(PPVRSRV_DEVICE_NODE psDeviceNode,
-                                                                                        PVRSRV_SYS_POWER_STATE eNewSysPowerState);
+                                                                                        PVRSRV_SYS_POWER_STATE eNewSysPowerState,
+                                                                                        PVRSRV_POWER_FLAGS ePwrFlags);
 
 /*!
 ******************************************************************************
@@ -232,10 +252,8 @@ PVRSRV_ERROR PVRSRVRegisterPowerDevice(PPVRSRV_DEVICE_NODE                         psDeviceNode,
 
  @Input                psDeviceNode : Device node
 
- @Return       PVRSRV_ERROR
-
 ******************************************************************************/
-PVRSRV_ERROR PVRSRVRemovePowerDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
+void PVRSRVRemovePowerDevice(PPVRSRV_DEVICE_NODE psDeviceNode);
 
 /*!
 ******************************************************************************
index 023ea0d..4003997 100644 (file)
@@ -46,6 +46,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <powervr/mem_types.h>
 
 #include "pvrsrv_error.h"
+#include "allocmem.h"
 #include "cache_ops.h"
 
 /*
@@ -95,35 +96,6 @@ void PVRSRVStatsDeregisterProcess(IMG_HANDLE hProcessStats);
  * Functions for recording the statistics...
  */
 
-/*
- * PVRSRV_ENABLE_PROCESS_STATS enables process statistics regarding events,
- *     resources and memory across all processes
- * PVRSRV_ENABLE_MEMORY_STATS enables recording of Linux kernel memory
- *     allocations, provided that PVRSRV_ENABLE_PROCESS_STATS is enabled
- *   - Output can be found in:
- *     /sys/kernel/debug/pvr/proc_stats/[live|retired]_pids_stats/mem_area
- * PVRSRV_DEBUG_LINUX_MEMORY_STATS provides more details about memory
- *     statistics in conjunction with PVRSRV_ENABLE_MEMORY_STATS
- * PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON is defined to encompass both memory
- *     allocation statistics functionalities described above in a single macro
- */
-#if defined(PVRSRV_ENABLE_PROCESS_STATS) && defined(PVRSRV_ENABLE_MEMORY_STATS) && defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) && defined(DEBUG)
-#define PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
-#endif
-
-/*
- * When using detailed memory allocation statistics, the line number and
- * file name where the allocation happened are also provided.
- * When this feature is not used, these parameters are not needed.
- */
-#if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON)
-#define DEBUG_MEMSTATS_PARAMS ,void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine
-#define DEBUG_MEMSTATS_VALUES ,__FILE__, __LINE__
-#else
-#define DEBUG_MEMSTATS_PARAMS
-#define DEBUG_MEMSTATS_VALUES
-#endif
-
 void PVRSRVStatsAddMemAllocRecord(PVRSRV_MEM_ALLOC_TYPE eAllocType,
                                                                  void *pvCpuVAddr,
                                                                  IMG_CPU_PHYADDR sCpuPAddr,
@@ -198,17 +170,14 @@ void PVRSRVStatsUpdateFreelistStats(IMG_UINT32 ui32NumGrowReqByApp,
                                                                        IMG_PID    ownerPid);
 #if defined(PVRSRV_ENABLE_CACHEOP_STATS)
 void PVRSRVStatsUpdateCacheOpStats(PVRSRV_CACHE_OP uiCacheOp,
-                                                                  IMG_UINT32 ui32OpSeqNum,
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO) && defined(DEBUG)
                                                                   IMG_DEV_VIRTADDR sDevVAddr,
                                                                   IMG_DEV_PHYADDR sDevPAddr,
-                                                                  IMG_UINT32 eFenceOpType,
 #endif
                                                                   IMG_DEVMEM_SIZE_T uiOffset,
                                                                   IMG_DEVMEM_SIZE_T uiSize,
                                                                   IMG_UINT64 ui64ExecuteTimeMs,
                                                                   IMG_BOOL bUserModeFlush,
-                                                                  IMG_BOOL bIsFence,
                                                                   IMG_PID ownerPid);
 #endif
 
index 57ad117..b99b8f5 100644 (file)
@@ -113,6 +113,8 @@ typedef struct _IMG_DVFS_DEVICE_
        struct dev_pm_opp               *psOPP;
 #endif
        struct devfreq                  *psDevFreq;
+       IMG_BOOL                        bInitPending;
+       IMG_BOOL                        bReady;
        IMG_BOOL                        bEnabled;
        IMG_HANDLE                      hGpuUtilUserDVFS;
        struct devfreq_simple_ondemand_data data;
index 1eb3f39..5717236 100644 (file)
@@ -138,13 +138,15 @@ Debug Notifier Interface
 
 #define DEBUG_REQUEST_DC                0
 #define DEBUG_REQUEST_SYNCTRACKING      1
-#define DEBUG_REQUEST_SYS               2
-#define DEBUG_REQUEST_ANDROIDSYNC       3
-#define DEBUG_REQUEST_LINUXFENCE        4
-#define DEBUG_REQUEST_SYNCCHECKPOINT    5
-#define DEBUG_REQUEST_HTB               6
-#define DEBUG_REQUEST_APPHINT           7
-#define DEBUG_REQUEST_FALLBACKSYNC      8
+#define DEBUG_REQUEST_SRV               2
+#define DEBUG_REQUEST_SYS               3
+#define DEBUG_REQUEST_RGX               4
+#define DEBUG_REQUEST_ANDROIDSYNC       5
+#define DEBUG_REQUEST_LINUXFENCE        6
+#define DEBUG_REQUEST_SYNCCHECKPOINT    7
+#define DEBUG_REQUEST_HTB               8
+#define DEBUG_REQUEST_APPHINT           9
+#define DEBUG_REQUEST_FALLBACKSYNC      10
 
 #define DEBUG_REQUEST_VERBOSITY_LOW     0
 #define DEBUG_REQUEST_VERBOSITY_MEDIUM  1
@@ -183,35 +185,82 @@ typedef void (*PFN_DBGREQ_NOTIFY)(PVRSRV_DBGREQ_HANDLE hDebugRequestHandle,
 #endif
 
 /*************************************************************************/ /*!
-@Function       PVRSRVRegisterDbgTable
+@Function       PVRSRVRegisterDeviceDbgTable
 @Description    Registers a debug requester table for the given device. The
-                order in which the debug requester IDs appear in the given
+                order in which the debug requester IDs appear in the
                 table determine the order in which a set of notifier callbacks
                 will be called. In other words, the requester ID that appears
                 first will have all of its associated debug notifier callbacks
                 called first. This will then be followed by all the callbacks
                 associated with the next requester ID in the table and so on.
+                The order table is handled internally.
 @Input          psDevNode     Device node to register requester table with
-@Input          paui32Table   Array of requester IDs
-@Input          ui32Length    Number of elements in paui32Table
 @Return         PVRSRV_ERROR  PVRSRV_OK on success otherwise an error
 */ /**************************************************************************/
 PVRSRV_ERROR
-PVRSRVRegisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-                       const IMG_UINT32 *paui32Table, IMG_UINT32 ui32Length);
+PVRSRVRegisterDeviceDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
 
 /*************************************************************************/ /*!
-@Function       PVRSRVUnregisterDbgTable
+@Function       PVRSRVRegisterDriverDbgTable
+@Description    Registers a debug requester table for the driver. The
+                order in which the debug requester IDs appear in the
+                table determine the order in which a set of notifier callbacks
+                will be called. In other words, the requester ID that appears
+                first will have all of its associated debug notifier callbacks
+                called first. This will then be followed by all the callbacks
+                associated with the next requester ID in the table and so on.
+                The order table is handled internally.
+@Return         PVRSRV_ERROR  PVRSRV_OK on success otherwise an error
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVRegisterDriverDbgTable(void);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVUnregisterDeviceDbgTable
 @Description    Unregisters a debug requester table.
 @Input          psDevNode     Device node for which the requester table should
                               be unregistered
 @Return         void
 */ /**************************************************************************/
 void
-PVRSRVUnregisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+PVRSRVUnregisterDeviceDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVUnregisterDriverDbgTable
+@Description    Unregisters the driver debug requester table.
+@Return         void
+*/ /**************************************************************************/
+void
+PVRSRVUnregisterDriverDbgTable(void);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVRegisterDeviceDbgRequestNotify
+@Description    Register a callback function on a given device that is called
+                when a debug request is made via a call PVRSRVDebugRequest.
+                There are a number of verbosity levels ranging from
+                DEBUG_REQUEST_VERBOSITY_LOW up to
+                DEBUG_REQUEST_VERBOSITY_MAX. The callback will be called once
+                for each level up to the highest level specified to
+                PVRSRVDebugRequest.
+@Output         phNotify             Points to debug notifier handle on success
+@Input          psDevNode            Device node for which the debug callback
+                                     should be registered
+@Input          pfnDbgRequestNotify  Function callback
+@Input          ui32RequesterID      Requester ID. This is used to determine
+                                     the order in which callbacks are called
+@Input          hDbgReqeustHandle    Data to be passed back to the caller via
+                                     the callback function
+@Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVRegisterDeviceDbgRequestNotify(IMG_HANDLE *phNotify,
+                                     struct _PVRSRV_DEVICE_NODE_ *psDevNode,
+                                     PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+                                     IMG_UINT32 ui32RequesterID,
+                                     PVRSRV_DBGREQ_HANDLE hDbgReqeustHandle);
 
 /*************************************************************************/ /*!
-@Function       PVRSRVRegisterDbgRequestNotify
+@Function       PVRSRVRegisterDriverDbgRequestNotify
 @Description    Register a callback function that is called when a debug request
                 is made via a call PVRSRVDebugRequest. There are a number of
                 verbosity levels ranging from DEBUG_REQUEST_VERBOSITY_LOW up to
@@ -219,8 +268,6 @@ PVRSRVUnregisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
                 for each level up to the highest level specified to
                 PVRSRVDebugRequest.
 @Output         phNotify             Points to debug notifier handle on success
-@Input          psDevNode            Device node for which the debug callback
-                                     should be registered
 @Input          pfnDbgRequestNotify  Function callback
 @Input          ui32RequesterID      Requester ID. This is used to determine
                                      the order in which callbacks are called
@@ -229,20 +276,30 @@ PVRSRVUnregisterDbgTable(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
 @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
 */ /**************************************************************************/
 PVRSRV_ERROR
-PVRSRVRegisterDbgRequestNotify(IMG_HANDLE *phNotify,
-                               struct _PVRSRV_DEVICE_NODE_ *psDevNode,
-                               PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
-                               IMG_UINT32 ui32RequesterID,
-                               PVRSRV_DBGREQ_HANDLE hDbgReqeustHandle);
+PVRSRVRegisterDriverDbgRequestNotify(IMG_HANDLE *phNotify,
+                                                                        PFN_DBGREQ_NOTIFY pfnDbgRequestNotify,
+                                                                        IMG_UINT32 ui32RequesterID,
+                                                                        PVRSRV_DBGREQ_HANDLE hDbgRequestHandle);
 
 /*************************************************************************/ /*!
-@Function       PVRSRVUnregisterDbgRequestNotify
-@Description    Unregister a previously registered callback function.
+@Function       PVRSRVUnregisterDeviceDbgRequestNotify
+@Description    Unregister a previously registered (device context) callback
+                function.
+@Input          hNotify              Debug notifier handle.
+@Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
+*/ /**************************************************************************/
+PVRSRV_ERROR
+PVRSRVUnregisterDeviceDbgRequestNotify(IMG_HANDLE hNotify);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVUnregisterDriverDbgRequestNotify
+@Description    Unregister a previously registered (driver context) callback
+                function.
 @Input          hNotify              Debug notifier handle.
 @Return         PVRSRV_ERROR         PVRSRV_OK on success otherwise an error
 */ /**************************************************************************/
 PVRSRV_ERROR
-PVRSRVUnregisterDbgRequestNotify(IMG_HANDLE hNotify);
+PVRSRVUnregisterDriverDbgRequestNotify(IMG_HANDLE hNotify);
 
 /*************************************************************************/ /*!
 @Function       PVRSRVDebugRequest
index 2a76704..5292bcf 100644 (file)
@@ -122,19 +122,16 @@ typedef struct PVRSRV_DATA_TAG
        PVRSRV_DRIVER_MODE    eDriverMode;                    /*!< Driver mode (i.e. native, host or guest) */
        IMG_BOOL              bForceApphintDriverMode;        /*!< Indicate if driver mode is forced via apphint */
        DRIVER_INFO           sDriverInfo;
-       IMG_UINT32            ui32RegisteredDevices;
        IMG_UINT32            ui32DPFErrorCount;                 /*!< Number of Fatal/Error DPFs */
 
+       POSWR_LOCK            hDeviceNodeListLock;            /*!< Read-Write lock to protect the list of devices */
        PVRSRV_DEVICE_NODE    *psDeviceNodeList;              /*!< List head of device nodes */
+       IMG_UINT32            ui32RegisteredDevices;
        PVRSRV_DEVICE_NODE    *psHostMemDeviceNode;           /*!< DeviceNode to be used for device independent
                                                                host based memory allocations where the DevMem
                                                                framework is to be used e.g. TL */
        PVRSRV_SERVICES_STATE eServicesState;                 /*!< global driver state */
 
-       HASH_TABLE            *psProcessHandleBase_Table;     /*!< Hash table with process handle bases */
-       POS_LOCK              hProcessHandleBase_Lock;        /*!< Lock for the process handle base table */
-       PVRSRV_HANDLE_BASE    *psProcessHandleBaseBeingFreed; /*!< Pointer to process handle base currently being freed */
-
        IMG_HANDLE            hGlobalEventObject;             /*!< OS Global Event Object */
        IMG_UINT32            ui32GEOConsecutiveTimeouts;     /*!< OS Global Event Object Timeouts */
 
@@ -143,7 +140,10 @@ typedef struct PVRSRV_DATA_TAG
        POS_SPINLOCK          hCleanupThreadWorkListLock;     /*!< Lock protecting the cleanup thread work list */
        DLLIST_NODE           sCleanupThreadWorkList;         /*!< List of work for the cleanup thread */
        IMG_PID               cleanupThreadPid;               /*!< Cleanup thread process id */
-       ATOMIC_T              i32NumCleanupItems;             /*!< Number of items in cleanup thread work list */
+       uintptr_t             cleanupThreadTid;               /*!< Cleanup thread id */
+       ATOMIC_T              i32NumCleanupItemsQueued;       /*!< Number of items in cleanup thread work list */
+       ATOMIC_T              i32NumCleanupItemsNotCompleted; /*!< Number of items dropped from cleanup thread work list
+                                                                  after retry limit reached */
 
        IMG_HANDLE            hDevicesWatchdogThread;         /*!< Devices watchdog thread */
        IMG_HANDLE            hDevicesWatchdogEvObj;          /*! Event object to drive devices watchdog thread */
@@ -186,6 +186,9 @@ typedef struct PVRSRV_DATA_TAG
 #if defined(SUPPORT_VALIDATION) && defined(__linux__)
        MEM_LEAK_INTERVALS    sMemLeakIntervals;              /*!< How often certain memory leak types will trigger */
 #endif
+       IMG_HANDLE            hThreadsDbgReqNotify;
+
+       IMG_UINT32            ui32PDumpBoundDevice;           /*!< PDump is bound to the device first connected to */
 } PVRSRV_DATA;
 
 
@@ -225,34 +228,85 @@ PVRSRV_DATA *PVRSRVGetPVRSRVData(void);
                        ((IMG_UINT32)((IMG_UINT32)(_expr)&(IMG_UINT)0x7FFFFFFF)==(IMG_UINT32)0x1) ? DRIVER_MODE_GUEST : \
                                ((IMG_UINT32)(_expr)&(IMG_UINT32)0x7FFFFFFF))
 
+typedef struct _PHYS_HEAP_ITERATOR_ PHYS_HEAP_ITERATOR;
+
 /*!
 ******************************************************************************
+ @Function LMA_HeapIteratorCreate
 
- @Function     LMA memory management API
+ @Description
+ Creates iterator for traversing physical heap requested by ui32Flags. The
+ iterator will go through all of the segments (a segment is physically
+ contiguous) of the physical heap and return their CPU physical address and
+ size.
 
+ @Input psDevNode: Pointer to device node struct.
+ @Input ui32Flags: Find heap that matches flags.
+ @Output ppsIter: Pointer to the iterator object.
+
+ @Return PVRSRV_OK upon success and PVRSRV_ERROR otherwise.
 ******************************************************************************/
-#if defined(SUPPORT_GPUVIRT_VALIDATION)
-PVRSRV_ERROR LMA_PhyContigPagesAllocGPV(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
-                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       IMG_UINT32 ui32OSid, IMG_PID uiPid);
-#endif
-PVRSRV_ERROR LMA_PhyContigPagesAlloc(PVRSRV_DEVICE_NODE *psDevNode, size_t uiSize,
-                                                       PG_HANDLE *psMemHandle, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       IMG_PID uiPid);
+PVRSRV_ERROR LMA_HeapIteratorCreate(PVRSRV_DEVICE_NODE *psDevNode,
+                                    PHYS_HEAP_USAGE_FLAGS ui32Flags,
+                                    PHYS_HEAP_ITERATOR **ppsIter);
+
+/*!
+******************************************************************************
+ @Function LMA_HeapIteratorDestroy
 
-void LMA_PhyContigPagesFree(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle);
+ @Description
+ Frees the iterator object created with LMA_HeapIteratorCreate.
 
-PVRSRV_ERROR LMA_PhyContigPagesMap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-                                                       size_t uiSize, IMG_DEV_PHYADDR *psDevPAddr,
-                                                       void **pvPtr);
+ @Input psIter: Pointer to the iterator object.
+******************************************************************************/
+void LMA_HeapIteratorDestroy(PHYS_HEAP_ITERATOR *psIter);
 
-void LMA_PhyContigPagesUnmap(PVRSRV_DEVICE_NODE *psDevNode, PG_HANDLE *psMemHandle,
-                                       void *pvPtr);
+/*!
+******************************************************************************
+ @Function LMA_HeapIteratorReset
 
-PVRSRV_ERROR LMA_PhyContigPagesClean(PVRSRV_DEVICE_NODE *psDevNode,
-                                     PG_HANDLE *psMemHandle,
-                                     IMG_UINT32 uiOffset,
-                                     IMG_UINT32 uiLength);
+ @Description
+ Resets the iterator the first segment of the physical heap.
+
+ @Input psIter: Pointer to the iterator object.
+******************************************************************************/
+PVRSRV_ERROR LMA_HeapIteratorReset(PHYS_HEAP_ITERATOR *psIter);
+
+/*!
+******************************************************************************
+ @Function LMA_HeapIteratorNext
+
+ @Description
+ Retrieves current segment's physical device address and size and moves the
+ iterator to the next element (if exists). If the iterator reached an end of
+ the heap and no segment was retrieved, this function returns IMG_FALSE.
+
+ @Input psIter: Pointer to the iterator object.
+ @Output psDevPAddr: Device physical address of the current segment.
+ @Output puiSize: Size of the current segment.
+
+ @Return IMG TRUE if a segment was found and retrieved, IMG_FALSE otherwise.
+******************************************************************************/
+IMG_BOOL LMA_HeapIteratorNext(PHYS_HEAP_ITERATOR *psIter,
+                              IMG_DEV_PHYADDR *psDevPAddr,
+                              IMG_UINT64 *puiSize);
+
+/*!
+******************************************************************************
+ @Function LMA_HeapIteratorGetHeapStats
+
+ @Description
+ Retrieves phys heap's usage statistics.
+
+ @Input psPhysHeap: Pointer to the physical heap object.
+ @Output puiTotalSize: Total size of the physical heap.
+ @Output puiInUseSize: Used space in the physical heap.
+
+ @Return PVRSRV_OK upon success and PVRSRV_otherwise.
+******************************************************************************/
+PVRSRV_ERROR LMA_HeapIteratorGetHeapStats(PHYS_HEAP_ITERATOR *psIter,
+                                          IMG_UINT64 *puiTotalSize,
+                                          IMG_UINT64 *puiInUseSize);
 
 /*!
 ******************************************************************************
@@ -394,7 +448,7 @@ static inline IMG_BOOL PVRSRVIsBridgeEnabled(IMG_HANDLE hServices, IMG_UINT32 ui
                ui32Offset = PVRSRV_BRIDGE_FIRST;
        }
 
-       return ((1U << (ui32BridgeGroup - ui32Offset)) & ui32Bridges) != 0;
+       return (IMG_BOOL)(((1U << (ui32BridgeGroup - ui32Offset)) & ui32Bridges) != 0);
 }
 
 
@@ -468,4 +522,21 @@ PHYS_HEAP_CONFIG* FindPhysHeapConfig(PVRSRV_DEVICE_CONFIG *psDevConfig,
 @Return         PVRSRV_DEVICE_NODE*  Return a device node, or NULL if not found.
 */ /**************************************************************************/
 PVRSRV_DEVICE_NODE* PVRSRVGetDeviceInstance(IMG_UINT32 ui32Instance);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVGetDeviceInstanceByOSId
+@Description    Return the specified device instance by OS Id.
+@Input          i32OSInstance        OS device Id to find
+@Return         PVRSRV_DEVICE_NODE*  Return a device node, or NULL if not found.
+*/ /**************************************************************************/
+PVRSRV_DEVICE_NODE *PVRSRVGetDeviceInstanceByOSId(IMG_INT32 i32OSInstance);
+
+/*************************************************************************/ /*!
+@Function       PVRSRVDefaultDomainPower
+@Description    Returns psDevNode->eCurrentSysPowerState
+@Input          PVRSRV_DEVICE_NODE*     Device node
+@Return         PVRSRV_SYS_POWER_STATE  System power state tracked internally
+*/ /**************************************************************************/
+PVRSRV_SYS_POWER_STATE PVRSRVDefaultDomainPower(PVRSRV_DEVICE_NODE *psDevNode);
+
 #endif /* PVRSRV_H */
index c49c95a..e354266 100644 (file)
@@ -52,7 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #if defined(__linux__)
 
 #include "km_apphint.h"
-#define PVRSRVAppHintDumpState() pvr_apphint_dump_state()
+#define PVRSRVAppHintDumpState(d) pvr_apphint_dump_state(d)
 #define PVRSRVAppHintRegisterHandlersUINT64(i,q,s,d,p) pvr_apphint_register_handlers_uint64(i,q,s,d,p)
 #define PVRSRVAppHintRegisterHandlersUINT32(i,q,s,d,p) pvr_apphint_register_handlers_uint32(i,q,s,d,p)
 #define PVRSRVAppHintRegisterHandlersBOOL(i,q,s,d,p) pvr_apphint_register_handlers_bool(i,q,s,d,p)
@@ -60,7 +60,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #else
 
-#define PVRSRVAppHintDumpState()
+#define PVRSRVAppHintDumpState(d)
 #define PVRSRVAppHintRegisterHandlersUINT64(i,q,s,d,p)
 #define PVRSRVAppHintRegisterHandlersUINT32(i,q,s,d,p)
 #define PVRSRVAppHintRegisterHandlersBOOL(i,q,s,d,p)
index d444001..750c981 100644 (file)
@@ -48,10 +48,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv_error.h"
 
 PVRSRV_ERROR ServerBridgeInit(void);
-PVRSRV_ERROR DeviceDepBridgeInit(IMG_UINT64 ui64Features);
-
-PVRSRV_ERROR ServerBridgeDeInit(void);
-PVRSRV_ERROR DeviceDepBridgeDeInit(IMG_UINT64 ui64Features);
-
+void ServerBridgeDeInit(void);
 
 #endif  /* PVRSRV_BRIDGE_INIT_H */
index 3d1b1c9..9eb454f 100644 (file)
@@ -156,4 +156,22 @@ typedef struct _PVRSRV_CLEANUP_THREAD_WORK_
 */ /***************************************************************************/
 void PVRSRVCleanupThreadAddWork(PVRSRV_CLEANUP_THREAD_WORK *psData);
 
+/**************************************************************************/ /*!
+@Function       PVRSRVCleanupThreadGetPid
+
+@Description    Returns Cleanup Thread's PID.
+
+@Return         PID of the Cleanup Thread
+*/ /***************************************************************************/
+IMG_PID PVRSRVCleanupThreadGetPid(void);
+
+/**************************************************************************/ /*!
+@Function       PVRSRVCleanupThreadGetTid
+
+@Description    Returns Cleanup Thread's TID.
+
+@Return         TID of the Cleanup Thread
+*/ /***************************************************************************/
+uintptr_t PVRSRVCleanupThreadGetTid(void);
+
 #endif /* PVRSRV_CLEANUP_H */
index 1a6b375..b97e015 100644 (file)
@@ -46,6 +46,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "physheap.h"
 #include "pvrsrv_error.h"
 #include "pvrsrv_memalloc_physheap.h"
+#include "pvrsrv_firmware_boot.h"
 #include "rgx_fwif_km.h"
 #include "servicesext.h"
 #include "cache_ops.h"
@@ -58,10 +59,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "virt_validation_defs.h"
 #endif
 
-
-#define IMG_GPU_DEBUG
-
-
 typedef struct _PVRSRV_DEVICE_CONFIG_ PVRSRV_DEVICE_CONFIG;
 typedef enum _DRIVER_MODE_
 {
@@ -108,13 +105,36 @@ typedef PVRSRV_ERROR
 (*PFN_SYS_PRE_POWER)(IMG_HANDLE hSysData,
                                                 PVRSRV_SYS_POWER_STATE eNewPowerState,
                                                 PVRSRV_SYS_POWER_STATE eCurrentPowerState,
-                                                IMG_BOOL bForced);
+                                                PVRSRV_POWER_FLAGS ePwrFlags);
 
 typedef PVRSRV_ERROR
 (*PFN_SYS_POST_POWER)(IMG_HANDLE hSysData,
                                                  PVRSRV_SYS_POWER_STATE eNewPowerState,
                                                  PVRSRV_SYS_POWER_STATE eCurrentPowerState,
-                                                 IMG_BOOL bForced);
+                                                 PVRSRV_POWER_FLAGS ePwrFlags);
+
+/*************************************************************************/ /*!
+@Brief          Callback function type PFN_SYS_GET_POWER
+
+@Description    This function queries the SoC power registers to determine
+                if the power domain on which the GPU resides is powered on.
+
+   Implementation of this callback is optional - where it is not provided,
+   the driver will assume the domain power state depending on driver type:
+   regular drivers assume it is unpowered at startup, while drivers with
+   AutoVz support expect the GPU domain to be powered on initially. The power
+   state will be then tracked internally according to the pfnPrePowerState
+   and pfnPostPowerState calls using a fallback function.
+
+@Input          psDevNode                  Pointer to node struct of the
+                                           device being initialised
+
+@Return         PVRSRV_SYS_POWER_STATE_ON  if the respective device's hardware
+                                           domain is powered on
+                PVRSRV_SYS_POWER_STATE_OFF if the domain is powered off
+*/ /**************************************************************************/
+typedef PVRSRV_SYS_POWER_STATE
+(*PFN_SYS_GET_POWER)(struct _PVRSRV_DEVICE_NODE_ *psDevNode);
 
 typedef void
 (*PFN_SYS_DEV_INTERRUPT_HANDLED)(PVRSRV_DEVICE_CONFIG *psDevConfig);
@@ -148,40 +168,14 @@ typedef void
                                                           IMG_UINT32,
                                                           IMG_BOOL);
 
-#if defined(SUPPORT_TRUSTED_DEVICE)
 
-#define TD_MAX_NUM_MIPS_PAGETABLE_PAGES (4U)
+#if defined(SUPPORT_TRUSTED_DEVICE)
 
 typedef struct _PVRSRV_TD_FW_PARAMS_
 {
        const void *pvFirmware;
        IMG_UINT32 ui32FirmwareSize;
-
-       union
-       {
-               struct
-               {
-                       /* META-only parameters */
-                       IMG_DEV_VIRTADDR sFWCodeDevVAddr;
-                       IMG_DEV_VIRTADDR sFWDataDevVAddr;
-                       IMG_DEV_VIRTADDR sFWCorememCodeDevVAddr;
-                       RGXFWIF_DEV_VIRTADDR sFWCorememCodeFWAddr;
-                       IMG_DEVMEM_SIZE_T uiFWCorememCodeSize;
-                       IMG_DEV_VIRTADDR sFWCorememDataDevVAddr;
-                       RGXFWIF_DEV_VIRTADDR sFWCorememDataFWAddr;
-                       IMG_UINT32 ui32NumThreads;
-               } sMeta;
-
-               struct
-               {
-                       /* MIPS-only parameters */
-                       IMG_DEV_PHYADDR sGPURegAddr;
-                       IMG_DEV_PHYADDR asFWPageTableAddr[TD_MAX_NUM_MIPS_PAGETABLE_PAGES];
-                       IMG_DEV_PHYADDR sFWStackAddr;
-                       IMG_UINT32 ui32FWPageTableLog2PageSize;
-                       IMG_UINT32 ui32FWPageTableNumPages;
-               } sMips;
-       } uFWP;
+       PVRSRV_FW_BOOT_PARAMS uFWP;
 } PVRSRV_TD_FW_PARAMS;
 
 typedef PVRSRV_ERROR
@@ -286,6 +280,12 @@ struct _PVRSRV_DEVICE_CONFIG_
        /*! Indicates if system supports FBCDC v3.1 */
        IMG_BOOL bHasFBCDCVersion31;
 
+       /*! Physical Heap definitions for this device.
+        * eDefaultHeap must be set to GPU_LOCAL or CPU_LOCAL. Specifying any other value
+        *    (e.g. DEFAULT) will lead to an error at device discovery.
+        * pasPhysHeap array must contain at least one PhysHeap, the declared default heap.
+        */
+       PVRSRV_PHYS_HEAP  eDefaultHeap;
        PHYS_HEAP_CONFIG *pasPhysHeaps;
        IMG_UINT32 ui32PhysHeapCount;
 
@@ -295,6 +295,7 @@ struct _PVRSRV_DEVICE_CONFIG_
         */
        PFN_SYS_PRE_POWER pfnPrePowerState;
        PFN_SYS_POST_POWER pfnPostPowerState;
+       PFN_SYS_GET_POWER  pfnGpuDomainPower;
 
        /*! Callback to obtain the clock frequency from the device (optional). */
        PFN_SYS_DEV_CLK_FREQ_GET pfnClockFreqGet;
diff --git a/drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_firmware_boot.h b/drivers/gpu/drm/img/img-rogue/services/server/include/pvrsrv_firmware_boot.h
new file mode 100644 (file)
index 0000000..14a196d
--- /dev/null
@@ -0,0 +1,87 @@
+/**************************************************************************/ /*!
+@File
+@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.
+*/ /***************************************************************************/
+
+#ifndef PVRSRV_FIRMWARE_BOOT_H
+#define PVRSRV_FIRMWARE_BOOT_H
+
+#include "img_types.h"
+#include "rgx_fwif_shared.h"
+
+#define TD_MAX_NUM_MIPS_PAGETABLE_PAGES (4U)
+
+typedef union _PVRSRV_FW_BOOT_PARAMS_
+{
+       struct
+       {
+               IMG_DEV_VIRTADDR sFWCodeDevVAddr;
+               IMG_DEV_VIRTADDR sFWDataDevVAddr;
+               IMG_DEV_VIRTADDR sFWCorememCodeDevVAddr;
+               RGXFWIF_DEV_VIRTADDR sFWCorememCodeFWAddr;
+               IMG_DEVMEM_SIZE_T uiFWCorememCodeSize;
+               IMG_DEV_VIRTADDR sFWCorememDataDevVAddr;
+               RGXFWIF_DEV_VIRTADDR sFWCorememDataFWAddr;
+               IMG_UINT32 ui32NumThreads;
+       } sMeta;
+
+       struct
+       {
+               IMG_DEV_PHYADDR sGPURegAddr;
+               IMG_DEV_PHYADDR asFWPageTableAddr[TD_MAX_NUM_MIPS_PAGETABLE_PAGES];
+               IMG_DEV_PHYADDR sFWStackAddr;
+               IMG_UINT32 ui32FWPageTableLog2PageSize;
+               IMG_UINT32 ui32FWPageTableNumPages;
+       } sMips;
+
+       struct
+       {
+               IMG_DEV_VIRTADDR sFWCorememCodeDevVAddr;
+               RGXFWIF_DEV_VIRTADDR sFWCorememCodeFWAddr;
+               IMG_DEVMEM_SIZE_T uiFWCorememCodeSize;
+
+               IMG_DEV_VIRTADDR sFWCorememDataDevVAddr;
+               RGXFWIF_DEV_VIRTADDR sFWCorememDataFWAddr;
+               IMG_DEVMEM_SIZE_T uiFWCorememDataSize;
+       } sRISCV;
+
+} PVRSRV_FW_BOOT_PARAMS;
+
+
+#endif /* PVRSRV_FIRMWARE_BOOT_H */
index c7fb25c..5d1a10c 100644 (file)
@@ -79,7 +79,7 @@ static inline void SyncClearTimelineObj(SYNC_TIMELINE_OBJ *psSTO)
 
 static inline IMG_BOOL SyncIsTimelineObjValid(const SYNC_TIMELINE_OBJ *psSTO)
 {
-       return psSTO->pvTlObj != NULL;
+       return (IMG_BOOL)(psSTO->pvTlObj != NULL);
 }
 
 static inline void SyncClearFenceObj(SYNC_FENCE_OBJ *psSFO)
@@ -90,7 +90,7 @@ static inline void SyncClearFenceObj(SYNC_FENCE_OBJ *psSFO)
 
 static inline IMG_BOOL SyncIsFenceObjValid(const SYNC_FENCE_OBJ *psSFO)
 {
-       return psSFO->pvFenceObj != NULL;
+       return (IMG_BOOL)(psSFO->pvFenceObj != NULL);
 }
 
 
@@ -211,7 +211,8 @@ SyncSWTimelineFenceCreateKM(PVRSRV_DEVICE_NODE *psDevNode,
 {
        IMG_UINT64 ui64SyncPtIdx;
        PVRSRV_ERROR eError;
-       eError = SyncSWTimelineFenceCreateKM_(hSWTimeline,
+       eError = SyncSWTimelineFenceCreateKM_(psDevNode,
+                                             hSWTimeline,
                                              pszFenceName,
                                              phOutFence,
                                              &ui64SyncPtIdx);
index 443aa24..0483b0a 100644 (file)
@@ -72,6 +72,8 @@ DummyBW(IMG_UINT32 ui32DispatchTableEntry,
         IMG_UINT8 *psBridgeOut,
         CONNECTION_DATA *psConnection);
 
+typedef PVRSRV_ERROR (*ServerResourceDestroyFunction)(IMG_HANDLE, IMG_HANDLE);
+
 typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32DispatchTableEntry,
                                                                         IMG_UINT8 *psBridgeIn,
                                                                         IMG_UINT8 *psBridgeOut,
@@ -144,7 +146,7 @@ void BridgeGlobalStatsUnlock(void);
 
 /* OS specific code may want to report the stats held here and within the
  * BRIDGE_DISPATCH_TABLE_ENTRYs (E.g. on Linux we report these via a
- * debugfs entry /sys/kernel/debug/pvr/bridge_stats) */
+ * debugfs entry /(sys/kernel/debug|proc)/pvr/bridge_stats) */
 extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
 #endif
 
@@ -209,6 +211,17 @@ PVRSRV_ERROR PVRSRVFindProcessMemStatsKM(IMG_PID pid,
                                          IMG_BOOL bAllProcessStats,
                                          IMG_UINT32 *ui32MemoryStats);
 
+static INLINE
+PVRSRV_ERROR DestroyServerResource(const SHARED_DEV_CONNECTION hConnection,
+                                   IMG_HANDLE hEvent,
+                                   ServerResourceDestroyFunction pfnDestroyCall,
+                                   IMG_HANDLE hResource)
+{
+    PVR_UNREFERENCED_PARAMETER(hEvent);
+
+    return pfnDestroyCall(GetBridgeHandle(hConnection), hResource);
+}
+
 #endif /* SRVCORE_H */
 
 /******************************************************************************
index 9ca79cf..33c26f4 100644 (file)
@@ -56,9 +56,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #ifndef CHECKPOINT_TYPES
 #define CHECKPOINT_TYPES
-typedef struct _SYNC_CHECKPOINT_CONTEXT *PSYNC_CHECKPOINT_CONTEXT;
+typedef struct SYNC_CHECKPOINT_CONTEXT_TAG *PSYNC_CHECKPOINT_CONTEXT;
 
-typedef struct _SYNC_CHECKPOINT *PSYNC_CHECKPOINT;
+typedef struct SYNC_CHECKPOINT_TAG *PSYNC_CHECKPOINT;
 #endif
 
 /* definitions for functions to be implemented by OS-specific sync - the OS-specific sync code
@@ -71,7 +71,8 @@ typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_RESOLVE_FN)(PSYNC_CHECKPOINT_CO
                                                              IMG_UINT32 *nr_checkpoints,
                                                              PSYNC_CHECKPOINT **checkpoint_handles,
                                                              IMG_UINT64 *pui64FenceUID);
-typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN)(const IMG_CHAR *fence_name,
+typedef PVRSRV_ERROR (*PFN_SYNC_CHECKPOINT_FENCE_CREATE_FN)(PPVRSRV_DEVICE_NODE device,
+                                                            const IMG_CHAR *fence_name,
                                                             PVRSRV_TIMELINE timeline,
                                                             PSYNC_CHECKPOINT_CONTEXT psSyncCheckpointContext,
                                                             PVRSRV_FENCE *new_fence,
index 88a56ef..ac6bd47 100644 (file)
@@ -68,12 +68,15 @@ PVRSRV_ERROR SyncFbTimelineCreateSW(IMG_UINT32 uiTimelineNameSize,
                                     const IMG_CHAR *pszTimelineName,
                                     PVRSRV_TIMELINE_SERVER **ppsTimeline);
 
-PVRSRV_ERROR SyncFbFenceCreateSW(PVRSRV_TIMELINE_SERVER *psTimeline,
+PVRSRV_ERROR SyncFbFenceCreateSW(CONNECTION_DATA *psConnection,
+                                 PVRSRV_DEVICE_NODE *psDeviceNode,
+                                 PVRSRV_TIMELINE_SERVER *psTimeline,
                                  IMG_UINT32 uiFenceNameSize,
                                  const IMG_CHAR *pszFenceName,
                                  PVRSRV_FENCE_SERVER **ppsOutputFence,
                                  IMG_UINT64 *pui64SyncPtIdx);
-PVRSRV_ERROR SyncFbSWTimelineFenceCreateKM(PVRSRV_TIMELINE iSWTimeline,
+PVRSRV_ERROR SyncFbSWTimelineFenceCreateKM(PVRSRV_DEVICE_NODE *psDeviceNode,
+                                           PVRSRV_TIMELINE iSWTimeline,
                                            const IMG_CHAR *pszFenceName,
                                            PVRSRV_FENCE *piOutputFence,
                                            IMG_UINT64* pui64SyncPtIdx);
@@ -93,7 +96,8 @@ PVRSRV_ERROR SyncFbTimelineCreatePVR(IMG_UINT32 uiTimelineNameSize,
                                      const IMG_CHAR *pszTimelineName,
                                      PVRSRV_TIMELINE_SERVER **ppsTimeline);
 
-PVRSRV_ERROR SyncFbFenceCreatePVR(const IMG_CHAR *pszName,
+PVRSRV_ERROR SyncFbFenceCreatePVR(PPVRSRV_DEVICE_NODE psDeviceNode,
+                                  const IMG_CHAR *pszName,
                                   PVRSRV_TIMELINE iTl,
                                   PSYNC_CHECKPOINT_CONTEXT hSyncCheckpointContext,
                                   PVRSRV_FENCE *piOutFence,
index 5394dba..e356829 100644 (file)
@@ -153,11 +153,9 @@ PVRSRVSyncRecordRemoveByHandleKM(
 void SyncRecordLookup(PVRSRV_DEVICE_NODE *psDevNode, IMG_UINT32 ui32FwAddr,
                                          IMG_CHAR * pszSyncInfo, size_t len);
 
-void ServerSyncDumpPending(void);
-
 PVRSRV_ERROR SyncRegisterConnection(SYNC_CONNECTION_DATA **ppsSyncConnectionData);
 void SyncUnregisterConnection(SYNC_CONNECTION_DATA *ppsSyncConnectionData);
-void SyncConnectionPDumpSyncBlocks(void *hSyncPrivData, PDUMP_TRANSITION_EVENT eEvent);
+void SyncConnectionPDumpSyncBlocks(PVRSRV_DEVICE_NODE *psDevNode, void *hSyncPrivData, PDUMP_TRANSITION_EVENT eEvent);
 
 /*!
 ******************************************************************************
@@ -169,21 +167,6 @@ PVRSRV_ERROR SyncServerInit(PVRSRV_DEVICE_NODE *psDevNode);
 void SyncServerDeinit(PVRSRV_DEVICE_NODE *psDevNode);
 
 
-/*!
-******************************************************************************
-@Function      PVRSRVLockServerSync
-
-@Description   Acquire a global lock to maintain server sync consistency
-******************************************************************************/
-void PVRSRVLockServerSync(void);
-/*!
-******************************************************************************
-@Function      PVRSRVUnlockServerSync
-
-@Description   Release the global server sync lock
-******************************************************************************/
-void PVRSRVUnlockServerSync(void);
-
 #if defined(PDUMP)
 PVRSRV_ERROR
 PVRSRVSyncPrimPDumpKM(SYNC_PRIMITIVE_BLOCK *psSyncBlk, IMG_UINT32 ui32Offset);
index 752c5dc..d39c070 100644 (file)
@@ -150,4 +150,23 @@ PVRSRV_ERROR TestIOCTLSyncCheckpointCreateFenceKM(CONNECTION_DATA *psConnection,
 PVRSRV_ERROR TestIOCTLWriteByteKM(IMG_BYTE ui8WriteData);
 
 PVRSRV_ERROR TestIOCTLReadByteKM(IMG_BYTE *pui8ReadData);
+
+typedef IMG_UINT32 DI_CONTEXT;
+PVRSRV_ERROR TestIOCTLHandleArray2CreateKM(DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleArray10CreateKM(DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleCleanupDestroy(DI_CONTEXT *psTestResource);
+PVRSRV_ERROR TestIOCTLHandleArray2CreateCPKM(DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleCleanupDestroyCP(DI_CONTEXT *psTestResource);
+PVRSRV_ERROR TestIOCTLHandleArray2CreatePPKM(CONNECTION_DATA    *psConnection,
+                                             PVRSRV_DEVICE_NODE *psDeviceNode,
+                                             DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleArray2CreateLUKM(DI_CONTEXT *psLookedup,
+                                             DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleArrayNCreate(IMG_UINT32 ui32NumResourcesRequested,
+                                         IMG_UINT32 *pui32NumResourcesCreated,
+                                         DI_CONTEXT **ppsTestResources);
+PVRSRV_ERROR TestIOCTLHandleArrayNCreateCP(IMG_UINT32 ui32NumResourcesRequested,
+                                           IMG_UINT32 *pui32NumResourcesCreated,
+                                           DI_CONTEXT **ppsTestResources);
+
 #endif /* TUTILS_KM_H */
index 520f391..9ad5ade 100644 (file)
@@ -121,7 +121,7 @@ typedef struct _VMM_PVZ_CONNECTION_
                   for allocating the physical heap that backs its firmware
                   allocations, this is the default configuration. The physical
                   heap is allocated within the guest VM IPA space and this
-                  IPA Addr/Size must be re-expressed as PA space Addr/Size
+                  IPA Addr/Size must be translated into the host's IPA space
                   by the VM manager before forwarding request to host.
                   If not implemented, return PVRSRV_ERROR_NOT_IMPLEMENTED.
                 */
index 5aa84db..1516b94 100644 (file)
@@ -81,10 +81,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvr_ricommon.h"
 #include "pvrsrv_apphint.h"
 #include "oskm_apphint.h"
+#include "srvcore.h"
 #if defined(__linux__)
 #include "linux/kernel.h"
 #endif
 #else
+#include "srvcore_intern.h"
 #include "rgxdefs.h"
 #endif
 
@@ -108,8 +110,7 @@ IMG_UINT64 _GetPremappedVA(PMR *psPMR, PVRSRV_DEVICE_NODE *psDevNode)
 
        IMG_DEV_PHYADDR sDevAddr;
        IMG_BOOL bValid;
-       PVRSRV_PHYS_HEAP eFirstHeap = (PVRSRV_VZ_MODE_IS(GUEST) ? PVRSRV_PHYS_HEAP_FW_CONFIG : PVRSRV_PHYS_HEAP_FW_MAIN);
-       PHYS_HEAP *psPhysHeap = psDevNode->apsPhysHeap[eFirstHeap];
+       PHYS_HEAP *psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_PHYS_HEAP_FW_MAIN];
        IMG_DEV_PHYADDR sHeapAddr;
 
        eError = PhysHeapGetDevPAddr(psPhysHeap, &sHeapAddr);
@@ -233,7 +234,7 @@ AllocateDeviceMemory(SHARED_DEV_CONNECTION hDevConnection,
                DEVMEM_IMPORT **ppsImport)
 {
        DEVMEM_IMPORT *psImport;
-       PVRSRV_MEMALLOCFLAGS_T uiPMRFlags;
+       PVRSRV_MEMALLOCFLAGS_T uiOutFlags;
        IMG_HANDLE hPMR;
        PVRSRV_ERROR eError;
 
@@ -249,7 +250,7 @@ AllocateDeviceMemory(SHARED_DEV_CONNECTION hDevConnection,
        CheckAnnotationLength(pszAnnotation);
 
        /* Pass only the PMR flags down */
-       uiPMRFlags = uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK;
+       uiOutFlags = uiFlags & PVRSRV_MEMALLOCFLAGS_PMRFLAGSMASK;
        eError = BridgePhysmemNewRamBackedPMR(GetBridgeHandle(hDevConnection),
                        uiSize,
                        uiChunkSize,
@@ -257,12 +258,13 @@ AllocateDeviceMemory(SHARED_DEV_CONNECTION hDevConnection,
                        ui32NumVirtChunks,
                        pui32MappingTable,
                        uiLog2Quantum,
-                       uiPMRFlags,
+                       uiOutFlags,
                        OSStringNLength(pszAnnotation, DEVMEM_ANNOTATION_MAX_LEN - 1) + 1,
                        pszAnnotation,
                        OSGetCurrentProcessID(),
                        &hPMR,
-                       PDUMP_NONE);
+                       PDUMP_NONE,
+                       &uiOutFlags);
 
        if (eError != PVRSRV_OK)
        {
@@ -274,6 +276,9 @@ AllocateDeviceMemory(SHARED_DEV_CONNECTION hDevConnection,
                goto failPMR;
        }
 
+       uiFlags &= ~PVRSRV_PHYS_HEAP_HINT_MASK;
+       uiFlags |= (uiOutFlags & PVRSRV_PHYS_HEAP_HINT_MASK);
+
        DevmemImportStructInit(psImport,
                        uiSize,
                        uiAlign,
@@ -494,7 +499,7 @@ SubAllocImportAlloc(RA_PERARENA_HANDLE hArena,
 
 #if defined(PDUMP) && defined(DEBUG)
 #if defined(__KERNEL__)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_CONT,
+       PDUMPCOMMENTWITHFLAGS(PMR_DeviceNode((PMR*)psImport->hPMR), PDUMP_CONT,
                        "Created PMR for sub-allocations with handle ID: 0x%p Annotation: \"%s\" (PID %u)",
                        psImport->hPMR, pszAnnotation, OSGetCurrentProcessID());
 #else
@@ -877,8 +882,10 @@ DevmemDestroyContext(DEVMEM_CONTEXT *psCtx)
                goto e1;
        }
 
-       eError = BridgeDevmemIntCtxDestroy(GetBridgeHandle(psCtx->hDevConnection),
-                       psCtx->hDevMemServerContext);
+       eError = DestroyServerResource(psCtx->hDevConnection,
+                                      NULL,
+                                      BridgeDevmemIntCtxDestroy,
+                                      psCtx->hDevMemServerContext);
        if (bDoCheck)
        {
                PVR_LOG_GOTO_IF_ERROR(eError, "BridgeDevMemIntCtxDestroy", e1);
@@ -1050,7 +1057,7 @@ DevmemCreateHeap(DEVMEM_CONTEXT *psCtx,
                void *pvAppHintState = NULL;
                IMG_UINT32 ui32FirmwarePolicydefault = 0, ui32FirmwarePolicy=0;
                OSCreateKMAppHintState(&pvAppHintState);
-               OSGetKMAppHintUINT32(pvAppHintState, DevMemFWHeapPolicy,
+               OSGetKMAppHintUINT32(APPHINT_NO_DEVICE, pvAppHintState, DevMemFWHeapPolicy,
                                                &ui32FirmwarePolicydefault, &ui32FirmwarePolicy);
                ui32PolicyVMRA = ui32Policy = ui32FirmwarePolicy;
                OSFreeKMAppHintState(pvAppHintState);
@@ -1289,8 +1296,11 @@ DevmemDestroyHeap(DEVMEM_HEAP *psHeap)
                }
        }
 
-       eError = BridgeDevmemIntHeapDestroy(GetBridgeHandle(psHeap->psCtx->hDevConnection),
-                       psHeap->hDevMemServerHeap);
+       eError = DestroyServerResource(psHeap->psCtx->hDevConnection,
+                                      NULL,
+                                      BridgeDevmemIntHeapDestroy,
+                                      psHeap->hDevMemServerHeap);
+
 #if defined(PVRSRV_FORCE_UNLOAD_IF_BAD_STATE)
        if (bDoCheck)
 #endif
@@ -1357,27 +1367,12 @@ DevmemSubAllocateAndMap(IMG_UINT8 uiPreAllocMultiplier,
 fail_map:
        DevmemFree(*ppsMemDescPtr);
 fail_alloc:
-       ppsMemDescPtr = NULL;
+       *ppsMemDescPtr = NULL;
+       PVR_ASSERT(eError != PVRSRV_OK);
        return eError;
 
 }
 
-static INLINE void _MemSet(void *pvMem,
-                           IMG_UINT8 uiPattern,
-                           IMG_DEVMEM_SIZE_T uiSize,
-                           PVRSRV_MEMALLOCFLAGS_T uiFlags)
-{
-       if (PVRSRV_CHECK_CPU_UNCACHED(uiFlags))
-       {
-               OSDeviceMemSet(pvMem, uiPattern, uiSize);
-       }
-       else
-       {
-               /* it's safe to use OSCachedMemSet() for cached and wc memory */
-               OSCachedMemSet(pvMem, uiPattern, uiSize);
-       }
-}
-
 IMG_INTERNAL PVRSRV_ERROR
 DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
                DEVMEM_HEAP *psHeap,
@@ -1387,9 +1382,6 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
                const IMG_CHAR *pszText,
                DEVMEM_MEMDESC **ppsMemDescPtr)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        RA_BASE_T uiAllocatedAddr = 0;
        RA_LENGTH_T uiAllocatedSize;
        RA_PERISPAN_HANDLE hImport; /* the "import" from which this sub-allocation came */
@@ -1505,7 +1497,7 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
 
 #if defined(PDUMP) && defined(DEBUG)
 #if defined(__KERNEL__)
-       PDUMPCOMMENTWITHFLAGS(PDUMP_CONT,
+       PDUMPCOMMENTWITHFLAGS(PMR_DeviceNode((PMR*)psImport->hPMR), PDUMP_CONT,
                        "Suballocated %u Byte for \"%s\" from PMR with handle ID: 0x%p (PID %u)",
                        (IMG_UINT32) uiSize, pszText, psImport->hPMR, OSGetCurrentProcessID());
 #else
@@ -1523,6 +1515,10 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
                        psImport,
                        uiSize);
 
+#if defined(DEBUG)
+       DevmemMemDescSetPoF(psMemDesc, uiFlags);
+#endif
+
        bImportClean = ((uiProperties & DEVMEM_PROPERTIES_IMPORT_IS_CLEAN) != 0);
 
        /* Zero the memory */
@@ -1545,7 +1541,7 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
                         */
                        PVR_ASSERT(uiSize < IMG_UINT32_MAX);
 
-                       _MemSet(pvAddr, 0, uiSize, uiFlags);
+                       DevmemCPUMemSet(pvAddr, 0, uiSize, uiFlags);
 
 #if defined(PDUMP)
                        DevmemPDumpLoadZeroMem(psMemDesc, 0, uiSize, PDUMP_FLAGS_CONTINUOUS);
@@ -1564,7 +1560,7 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
                        eError = DevmemAcquireCpuVirtAddr(psMemDesc, &pvAddr);
                        PVR_GOTO_IF_ERROR(eError, failMaintenance);
 
-                       _MemSet(pvAddr, PVRSRV_POISON_ON_ALLOC_VALUE, uiSize, uiFlags);
+                       DevmemCPUMemSet(pvAddr, PVRSRV_POISON_ON_ALLOC_VALUE, uiSize, uiFlags);
 
                        bPoisonOnAlloc = IMG_TRUE;
                }
@@ -1573,8 +1569,6 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
        /* Flush or invalidate */
        if (bCPUCached && !bImportClean && (bZero || bCPUCleanFlag || bPoisonOnAlloc))
        {
-               /* BridgeCacheOpQueue _may_ be deferred so use BridgeCacheOpExec
-                  to ensure this cache maintenance is actioned immediately */
                eError = BridgeCacheOpExec (GetBridgeHandle(psMemDesc->psImport->hDevConnection),
                                psMemDesc->psImport->hPMR,
                                (IMG_UINT64)(uintptr_t)
@@ -1587,16 +1581,6 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
 
        if (pvAddr)
        {
-
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psMemDesc);
                pvAddr = NULL;
        }
@@ -1635,16 +1619,6 @@ DevmemSubAllocate(IMG_UINT8 uiPreAllocMultiplier,
 failMaintenance:
        if (pvAddr)
        {
-
-#ifdef CACHE_TEST
-               pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psMemDesc;
-               printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-               if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-               {
-                   printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_FLUSH);
-                   BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)pvAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_FLUSH);
-               }
-#endif
                DevmemReleaseCpuVirtAddr(psMemDesc);
                pvAddr = NULL;
        }
@@ -1714,6 +1688,10 @@ DevmemAllocateExportable(SHARED_DEV_CONNECTION hDevConnection,
                        psImport,
                        uiSize);
 
+#if defined(DEBUG)
+       DevmemMemDescSetPoF(psMemDesc, uiFlags);
+#endif
+
        *ppsMemDescPtr = psMemDesc;
 
        /* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
@@ -1814,6 +1792,10 @@ DevmemAllocateSparse(SHARED_DEV_CONNECTION hDevConnection,
                        psImport,
                        uiSize);
 
+#if defined(DEBUG)
+       DevmemMemDescSetPoF(psMemDesc, uiFlags);
+#endif
+
        /* copy the allocation descriptive name and size so it can be passed to DevicememHistory when
         * the allocation gets mapped/unmapped
         */
@@ -1877,7 +1859,10 @@ IMG_INTERNAL PVRSRV_ERROR
 DevmemUnmakeLocalImportHandle(SHARED_DEV_CONNECTION hDevConnection,
                IMG_HANDLE hLocalImportHandle)
 {
-       return BridgePMRUnmakeLocalImportHandle(GetBridgeHandle(hDevConnection), hLocalImportHandle);
+       return DestroyServerResource(hDevConnection,
+                                    NULL,
+                                    BridgePMRUnmakeLocalImportHandle,
+                                    hLocalImportHandle);
 }
 
 /*****************************************************************************
@@ -1944,8 +1929,10 @@ _Mapping_Unexport(DEVMEM_IMPORT *psImport,
 
        PVR_ASSERT (psImport != NULL);
 
-       eError = BridgePMRUnexportPMR(GetBridgeHandle(psImport->hDevConnection),
-                       hPMRExportHandle);
+       eError = DestroyServerResource(psImport->hDevConnection,
+                                      NULL,
+                                      BridgePMRUnexportPMR,
+                                      hPMRExportHandle);
        PVR_ASSERT(eError == PVRSRV_OK);
 }
 
@@ -2572,45 +2559,12 @@ DevmemAcquireCpuVirtAddr(DEVMEM_MEMDESC *psMemDesc,
                void **ppvCpuVirtAddr)
 {
        PVRSRV_ERROR eError;
-       DEVMEM_PROPERTIES_T uiProperties;
 
        PVR_ASSERT(psMemDesc != NULL);
        PVR_ASSERT(ppvCpuVirtAddr != NULL);
 
-       uiProperties = GetImportProperties(psMemDesc->psImport);
-
-       if (uiProperties &
-                       (DEVMEM_PROPERTIES_UNPINNED | DEVMEM_PROPERTIES_SECURE))
-       {
-#if defined(SUPPORT_SECURITY_VALIDATION)
-               if (uiProperties & DEVMEM_PROPERTIES_SECURE)
-               {
-                       PVR_DPF((PVR_DBG_WARNING,
-                                       "%s: Allocation is a secure buffer. "
-                                       "It should not be possible to map to CPU, but for security "
-                                       "validation this will be allowed for testing purposes, "
-                                       "as long as the buffer is pinned.",
-                                       __func__));
-               }
-
-               if (uiProperties & DEVMEM_PROPERTIES_UNPINNED)
-#endif
-               {
-                       PVR_DPF((PVR_DBG_ERROR,
-                                       "%s: Allocation is currently unpinned or a secure buffer. "
-                                       "Not possible to map to CPU!",
-                                       __func__));
-                       return PVRSRV_ERROR_INVALID_MAP_REQUEST;
-               }
-       }
-
-       if (uiProperties & DEVMEM_PROPERTIES_NO_CPU_MAPPING)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                               "%s: CPU Mapping is not possible on this allocation!",
-                               __func__));
-               return PVRSRV_ERROR_INVALID_MAP_REQUEST;
-       }
+       eError = DevmemCPUMapCheckImportProperties(psMemDesc);
+       PVR_LOG_RETURN_IF_ERROR(eError, "DevmemCPUMapCheckImportProperties");
 
        OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
        DEVMEM_REFCOUNT_PRINT("%s (%p) %d->%d",
@@ -2777,7 +2731,7 @@ DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
  * memdescs of buffers allocated in the FW memory context
  * that is created in the Server
  */
-PVRSRV_ERROR
+void
 DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
                IMG_HANDLE *phPMR,
                IMG_DEVMEM_OFFSET_T *puiPMROffset)
@@ -2790,8 +2744,6 @@ DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
 
        PVR_ASSERT(psImport);
        *phPMR = psImport->hPMR;
-
-       return PVRSRV_OK;
 }
 
 #if defined(__KERNEL__)
@@ -2958,6 +2910,12 @@ DevmemGetHeapLog2PageSize(DEVMEM_HEAP *psHeap)
        return psHeap->uiLog2Quantum;
 }
 
+IMG_INTERNAL PVRSRV_MEMALLOCFLAGS_T
+DevmemGetMemAllocFlags(DEVMEM_MEMDESC *psMemDesc)
+{
+       return psMemDesc->psImport->uiFlags;
+}
+
 IMG_INTERNAL IMG_DEVMEM_SIZE_T
 DevmemGetHeapReservedSize(DEVMEM_HEAP *psHeap)
 {
index ea0dd32..639f93a 100644 (file)
@@ -76,7 +76,11 @@ DevmemPDumpLoadMem(DEVMEM_MEMDESC *psMemDesc,
                                       IMG_FALSE);
 
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpLoadMem");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL void
@@ -97,7 +101,11 @@ DevmemPDumpLoadZeroMem(DEVMEM_MEMDESC *psMemDesc,
                                       IMG_TRUE);
 
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpLoadMem");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL void
@@ -115,7 +123,11 @@ DevmemPDumpLoadMemValue32(DEVMEM_MEMDESC *psMemDesc,
                                         uiPDumpFlags);
 
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpLoadMemValue32");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL void
@@ -132,7 +144,11 @@ DevmemPDumpLoadMemValue64(DEVMEM_MEMDESC *psMemDesc,
                                              ui64Value,
                                              uiPDumpFlags);
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpLoadMemValue64");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL PVRSRV_ERROR
@@ -159,7 +175,11 @@ DevmemPDumpPageCatBaseToSAddr(DEVMEM_MEMDESC               *psMemDesc,
                                            &uiNextSymName);
 
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpSymbolicAddr");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 
        OSSNPrintf(pszName, ui32Size, "%s:%s", &aszMemspaceName[0], &aszSymbolicName[0]);
        return eError;
@@ -183,7 +203,11 @@ DevmemPDumpSaveToFile(DEVMEM_MEMDESC *psMemDesc,
                                          uiFileOffset);
 
        PVR_LOG_IF_ERROR(eError, "BridgePMRPDumpSaveToFile");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL void
@@ -211,7 +235,11 @@ DevmemPDumpSaveToFileVirtual(DEVMEM_MEMDESC *psMemDesc,
                                                       ui32PdumpFlags);
 
        PVR_LOG_IF_ERROR(eError, "BridgeDevmemIntPDumpSaveToFileVirtual");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL void
@@ -243,7 +271,11 @@ DevmemPDumpDataDescriptor(DEVMEM_MEMDESC *psMemDesc,
                                           ui32PdumpFlags);
 
        PVR_LOG_IF_ERROR(eError, "BridgePDumpDataDescriptor");
-       PVR_ASSERT(eError == PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError == PVRSRV_OK);
+       }
 }
 
 IMG_INTERNAL PVRSRV_ERROR
@@ -280,8 +312,12 @@ DevmemPDumpDevmemPol32(const DEVMEM_MEMDESC *psMemDesc,
         */
 
 e0:
-        PVR_ASSERT(eError != PVRSRV_OK);
-        return eError;
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError != PVRSRV_OK);
+       }
+       return eError;
 }
 
 #if defined(__KERNEL__)
@@ -323,7 +359,11 @@ DevmemPDumpDevmemCheck32(const DEVMEM_MEMDESC *psMemDesc,
         */
 
 e0:
-       PVR_ASSERT(eError != PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError != PVRSRV_OK);
+       }
        return eError;
 }
 #endif /* defined(__KERNEL__) */
@@ -353,7 +393,11 @@ DevmemPDumpCBP(const DEVMEM_MEMDESC *psMemDesc,
        return PVRSRV_OK;
 
 e0:
-       PVR_ASSERT(eError != PVRSRV_OK);
+       /* If PDump was rejected for this device, suppress silently */
+       if (eError != PVRSRV_ERROR_PDUMP_CAPTURE_BOUND_TO_ANOTHER_DEVICE)
+       {
+               PVR_ASSERT(eError != PVRSRV_OK);
+       }
        return eError;
 }
 
index 44c9822..d4416ae 100644 (file)
@@ -49,6 +49,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "ra.h"
 #include "devicemem_utils.h"
 #include "client_mm_bridge.h"
+#include "client_cache_bridge.h"
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
 #include "client_ri_bridge.h"
 #if defined(__KERNEL__)
@@ -62,6 +63,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "proc_stats.h"
 #endif
 
+#if defined(__KERNEL__)
+#include "srvcore.h"
+#else
+#include "srvcore_intern.h"
+#endif
+
 /*
        SVM heap management support functions for CPU (un)mapping
  */
@@ -371,8 +378,12 @@ IMG_BOOL DevmemImportStructRelease(DEVMEM_IMPORT *psImport)
 
        if (iRefCount == 0)
        {
-               BridgePMRUnrefPMR(GetBridgeHandle(psImport->hDevConnection),
-                               psImport->hPMR);
+               PVRSRV_ERROR eError = DestroyServerResource(psImport->hDevConnection,
+                                                           NULL,
+                                                           BridgePMRUnrefPMR,
+                                                           psImport->hPMR);
+               PVR_ASSERT(eError == PVRSRV_OK);
+
                OSLockDestroy(psImport->sCPUImport.hLock);
                OSLockDestroy(psImport->sDeviceImport.hLock);
                OSLockDestroy(psImport->hLock);
@@ -455,9 +466,24 @@ void DevmemMemDescInit(DEVMEM_MEMDESC *psMemDesc,
        psMemDesc->hPrivData = NULL;
        psMemDesc->ui32AllocationIndex = DEVICEMEM_HISTORY_ALLOC_INDEX_NONE;
 
+#if defined(DEBUG)
+       psMemDesc->bPoisonOnFree = IMG_FALSE;
+#endif
+
        OSAtomicWrite(&psMemDesc->hRefCount, 1);
 }
 
+#if defined(DEBUG)
+IMG_INTERNAL
+void DevmemMemDescSetPoF(DEVMEM_MEMDESC *psMemDesc, PVRSRV_MEMALLOCFLAGS_T uiFlags)
+{
+       if (PVRSRV_CHECK_POISON_ON_FREE(uiFlags))
+       {
+               psMemDesc->bPoisonOnFree = IMG_TRUE;
+       }
+}
+#endif
+
 IMG_INTERNAL
 void DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc)
 {
@@ -473,6 +499,48 @@ void DevmemMemDescAcquire(DEVMEM_MEMDESC *psMemDesc)
        PVR_UNREFERENCED_PARAMETER(iRefCount);
 }
 
+#if defined(DEBUG)
+static void _DevmemPoisonOnFree(DEVMEM_MEMDESC *psMemDesc)
+{
+       void *pvAddr = NULL;
+       IMG_UINT8 *pui8CPUVAddr;
+       PVRSRV_ERROR eError;
+
+       eError = DevmemCPUMapCheckImportProperties(psMemDesc);
+       PVR_LOG_RETURN_VOID_IF_ERROR(eError, "DevmemCPUMapCheckImportProperties");
+
+       OSLockAcquire(psMemDesc->sCPUMemDesc.hLock);
+       eError = DevmemImportStructCPUMap(psMemDesc->psImport);
+       OSLockRelease(psMemDesc->sCPUMemDesc.hLock);
+       PVR_LOG_RETURN_VOID_IF_ERROR(eError, "DevmemImportStructCPUMap");
+
+       pui8CPUVAddr = psMemDesc->psImport->sCPUImport.pvCPUVAddr;
+       pui8CPUVAddr += psMemDesc->uiOffset;
+       pvAddr = pui8CPUVAddr;
+
+       DevmemCPUMemSet(pvAddr,
+                       PVRSRV_POISON_ON_FREE_VALUE,
+                       psMemDesc->uiAllocSize,
+                       psMemDesc->psImport->uiFlags);
+
+       if (PVRSRV_CHECK_CPU_CACHE_COHERENT(psMemDesc->psImport->uiFlags) ||
+           PVRSRV_CHECK_CPU_CACHE_INCOHERENT(psMemDesc->psImport->uiFlags))
+       {
+               eError = BridgeCacheOpExec(GetBridgeHandle(psMemDesc->psImport->hDevConnection),
+                                                                  psMemDesc->psImport->hPMR,
+                                                                  (IMG_UINT64) (uintptr_t)
+                                                                  pvAddr - psMemDesc->uiOffset,
+                                                                  psMemDesc->uiOffset,
+                                                                  psMemDesc->uiAllocSize,
+                                                                  PVRSRV_CACHE_OP_FLUSH);
+               PVR_LOG_IF_ERROR(eError, "BridgeCacheOpExec");
+       }
+
+       DevmemImportStructCPUUnmap(psMemDesc->psImport);
+       pvAddr = NULL;
+}
+#endif
+
 IMG_INTERNAL
 IMG_BOOL DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
 {
@@ -496,8 +564,10 @@ IMG_BOOL DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
                {
                        PVRSRV_ERROR eError;
 
-                       eError = BridgeRIDeleteMEMDESCEntry(GetBridgeHandle(psMemDesc->psImport->hDevConnection),
-                                                           psMemDesc->hRIHandle);
+                       eError = DestroyServerResource(psMemDesc->psImport->hDevConnection,
+                                                      NULL,
+                                                      BridgeRIDeleteMEMDESCEntry,
+                                                      psMemDesc->hRIHandle);
                        PVR_LOG_IF_ERROR(eError, "BridgeRIDeleteMEMDESCEntry");
                }
 #endif
@@ -508,7 +578,6 @@ IMG_BOOL DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
                        /* As soon as the first sub-allocation on the psImport is freed
                         * we might get dirty memory when reusing it.
                         * We have to delete the ZEROED, CLEAN & POISONED flag */
-
                        psMemDesc->psImport->uiProperties &=
                                        ~(DEVMEM_PROPERTIES_IMPORT_IS_ZEROED |
                                                        DEVMEM_PROPERTIES_IMPORT_IS_CLEAN |
@@ -516,6 +585,13 @@ IMG_BOOL DevmemMemDescRelease(DEVMEM_MEMDESC *psMemDesc)
 
                        OSLockRelease(psMemDesc->psImport->hLock);
 
+#if defined(DEBUG)
+                       if (psMemDesc->bPoisonOnFree)
+                       {
+                               _DevmemPoisonOnFree(psMemDesc);
+                       }
+#endif
+
                        RA_Free(psMemDesc->psImport->sDeviceImport.psHeap->psSubAllocRA,
                                        psMemDesc->psImport->sDeviceImport.sDevVAddr.uiAddr +
                                        psMemDesc->uiOffset);
@@ -579,8 +655,13 @@ PVRSRV_ERROR DevmemValidateParams(IMG_DEVMEM_SIZE_T uiSize,
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
-       /* If zero flag is set we have to have write access to the page. */
-       if (PVRSRV_CHECK_ZERO_ON_ALLOC(*puiFlags) || PVRSRV_CHECK_CPU_WRITEABLE(*puiFlags))
+       /* If zero or poison flags are set we have to have write access to the page. */
+       if (PVRSRV_CHECK_ZERO_ON_ALLOC(*puiFlags) ||
+           PVRSRV_CHECK_POISON_ON_ALLOC(*puiFlags) ||
+#if defined(DEBUG)
+           PVRSRV_CHECK_POISON_ON_FREE(*puiFlags) ||
+#endif
+           PVRSRV_CHECK_CPU_WRITEABLE(*puiFlags))
        {
                (*puiFlags) |= PVRSRV_MEMALLOCFLAG_CPU_WRITEABLE |
                                PVRSRV_MEMALLOCFLAG_CPU_READABLE;
@@ -1035,13 +1116,17 @@ IMG_BOOL DevmemImportStructDevUnmap(DEVMEM_IMPORT *psImport)
                {
                        if (psDeviceImport->bMapped)
                        {
-                               eError = BridgeDevmemIntUnmapPMR(GetBridgeHandle(psImport->hDevConnection),
-                                               psDeviceImport->hMapping);
+                               eError = DestroyServerResource(psImport->hDevConnection,
+                                                              NULL,
+                                                              BridgeDevmemIntUnmapPMR,
+                                                              psDeviceImport->hMapping);
                                PVR_ASSERT(eError == PVRSRV_OK);
                        }
 
-                       eError = BridgeDevmemIntUnreserveRange(GetBridgeHandle(psImport->hDevConnection),
-                                       psDeviceImport->hReservation);
+                       eError = DestroyServerResource(psImport->hDevConnection,
+                                                      NULL,
+                                                      BridgeDevmemIntUnreserveRange,
+                                                      psDeviceImport->hReservation);
                        PVR_ASSERT(eError == PVRSRV_OK);
                }
 
index 00f63ae..c326ae2 100644 (file)
@@ -45,9 +45,17 @@ 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 (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)) 
-#include <stdarg.h>
-#endif
+#if defined(__linux__)
+ #include <linux/version.h>
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
+  #include <linux/stdarg.h>
+ #else
+  #include <stdarg.h>
+ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) */
+#else
+ #include <stdarg.h>
+#endif /* __linux__ */
 
 #include "htbuffer.h"
 #include "osfunc.h"
index 3cc19b8..4c2981e 100644 (file)
@@ -197,6 +197,19 @@ struct _RA_ARENA_
         */
        IMG_UINT32 ui32LockClass;
 
+       /* Total Size of the Arena */
+       IMG_UINT64      ui64TotalArenaSize;
+
+       /* Size available for allocation in the arena */
+       IMG_UINT64      ui64FreeArenaSize;
+
+};
+
+struct _RA_ARENA_ITERATOR_
+{
+       RA_ARENA *pArena;
+       BT *pCurrent;
+       IMG_BOOL bIncludeFreeSegments;
 };
 
 /*************************************************************************/ /*!
@@ -214,12 +227,12 @@ struct _RA_ARENA_
 */ /**************************************************************************/
 static PVRSRV_ERROR
 _RequestAllocFail(RA_PERARENA_HANDLE _h,
-                                 RA_LENGTH_T _uSize,
-                                 RA_FLAGS_T _uFlags,
-                                 const IMG_CHAR *_pszAnnotation,
-                                 RA_BASE_T *_pBase,
-                                 RA_LENGTH_T *_pActualSize,
-                                 RA_PERISPAN_HANDLE *_phPriv)
+                  RA_LENGTH_T _uSize,
+                  RA_FLAGS_T _uFlags,
+                  const IMG_CHAR *_pszAnnotation,
+                  RA_BASE_T *_pBase,
+                  RA_LENGTH_T *_pActualSize,
+                  RA_PERISPAN_HANDLE *_phPriv)
 {
        PVR_UNREFERENCED_PARAMETER(_h);
        PVR_UNREFERENCED_PARAMETER(_uSize);
@@ -276,10 +289,10 @@ pvr_log2(RA_LENGTH_T n)
 
        PVR_ASSERT(n != 0); /* Log2 is not defined on 0 */
 
-       n>>=1;
-       while (n>0)
+       n >>= 1;
+       while (n > 0)
        {
-               n>>=1;
+               n >>= 1;
                l++;
        }
        return l;
@@ -433,7 +446,7 @@ static int is_arena_valid(struct _RA_ARENA_ *arena)
 */ /**************************************************************************/
 static INLINE void
 _SegmentListInsertAfter(BT *pInsertionPoint,
-                                           BT *pBT)
+                        BT *pBT)
 {
        PVR_ASSERT(pBT != NULL);
        PVR_ASSERT(pInsertionPoint != NULL);
@@ -589,7 +602,7 @@ _FreeListInsert(RA_ARENA *pArena, BT *pBT)
        /* Get the first node in the bucket */
        pBTTemp = pArena->per_flags_buckets->buckets[uIndex];
 
-       if (unlikely((pArena->ui32PolicyFlags & RA_POLICY_ALLOC_OPTIMAL_MASK) == RA_POLICY_ALLOC_OPTIMAL))
+       if (unlikely((pArena->ui32PolicyFlags & RA_POLICY_ALLOC_NODE_SELECT_MASK) == RA_POLICY_ALLOC_OPTIMAL))
        {
                /* Add the node to the start if the bucket is empty */
                if (NULL == pBTTemp)
@@ -717,7 +730,7 @@ _FreeListRemove(RA_ARENA *pArena, BT *pBT)
 */ /**************************************************************************/
 static BT *
 _InsertResource(RA_ARENA *pArena, RA_BASE_T base, RA_LENGTH_T uSize,
-                               RA_FLAGS_T uFlags)
+                RA_FLAGS_T uFlags)
 {
        BT *pBT;
        PVR_ASSERT(pArena!=NULL);
@@ -793,7 +806,6 @@ _RemoveResourceSpan(RA_ARENA *pArena, BT *pBT)
        return IMG_FALSE;
 }
 
-
 /*************************************************************************/ /*!
 @Function       _FreeBT
 @Description    Free a boundary tag taking care of the segment list and the
@@ -865,9 +877,9 @@ _FreeBT(RA_ARENA *pArena, BT *pBT)
  */
 static INLINE
 struct _BT_ *find_chunk_in_bucket(struct _BT_ * first_elt,
-                                                                 RA_LENGTH_T uSize,
-                                                                 RA_LENGTH_T uAlignment,
-                                                                 unsigned int nb_max_try)
+                                  RA_LENGTH_T uSize,
+                                  RA_LENGTH_T uAlignment,
+                                  unsigned int nb_max_try)
 {
        struct _BT_ *walker;
 
@@ -892,6 +904,93 @@ struct _BT_ *find_chunk_in_bucket(struct _BT_ * first_elt,
        return NULL;
 }
 
+/*************************************************************************/ /*!
+@Function       _AllocAlignSplit
+@Description    Given a valid BT, trim the start and end of the BT according
+                to alignment and size requirements. Also add the resulting
+                BT to the live hash table.
+@Input          pArena       The arena.
+@Input          pBT          The BT to trim and add to live hash table
+@Input          uSize        The requested allocation size.
+@Input          uAlignment   The alignment requirements of the allocation
+                             Required uAlignment, or 0.
+                             Must be a power of 2 if not 0
+@Output         pBase        Allocated, corrected, resource base
+                             (non-optional, must not be NULL)
+@Output         phPriv       The user references associated with
+                             the imported segment. (optional)
+@Return         IMG_FALSE failure
+                IMG_TRUE success
+*/ /**************************************************************************/
+static IMG_BOOL
+_AllocAlignSplit(RA_ARENA *pArena,
+                 BT *pBT,
+                 RA_LENGTH_T uSize,
+                 RA_LENGTH_T uAlignment,
+                 RA_BASE_T *pBase,
+                 RA_PERISPAN_HANDLE *phPriv)
+{
+       RA_BASE_T aligned_base;
+
+       aligned_base = (uAlignment > 1) ? (pBT->base + uAlignment - 1) & ~(uAlignment - 1) : pBT->base;
+
+       _FreeListRemove(pArena, pBT);
+
+       if ((pArena->ui32PolicyFlags & RA_POLICY_NO_SPLIT_MASK) == RA_POLICY_NO_SPLIT)
+       {
+               goto nosplit;
+       }
+
+       /* with uAlignment we might need to discard the front of this segment */
+       if (aligned_base > pBT->base)
+       {
+               BT *pNeighbour;
+               pNeighbour = _SegmentSplit(pBT, (RA_LENGTH_T)(aligned_base - pBT->base));
+               /* partition the buffer, create a new boundary tag */
+               if (pNeighbour == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Front split failed", __func__));
+                       /* Put pBT back in the list */
+                       _FreeListInsert(pArena, pBT);
+                       return IMG_FALSE;
+               }
+
+               _FreeListInsert(pArena, pBT);
+               pBT = pNeighbour;
+       }
+
+       /* the segment might be too big, if so, discard the back of the segment */
+       if (pBT->uSize > uSize)
+       {
+               BT *pNeighbour;
+               pNeighbour = _SegmentSplit(pBT, uSize);
+               /* partition the buffer, create a new boundary tag */
+               if (pNeighbour == NULL)
+               {
+                       PVR_DPF((PVR_DBG_ERROR, "%s: Back split failed", __func__));
+                       /* Put pBT back in the list */
+                       _FreeListInsert(pArena, pBT);
+                       return IMG_FALSE;
+               }
+
+               _FreeListInsert(pArena, pNeighbour);
+       }
+nosplit:
+       pBT->type = btt_live;
+
+       if (!HASH_Insert_Extended(pArena->pSegmentHash, &aligned_base, (uintptr_t)pBT))
+       {
+               _FreeBT(pArena, pBT);
+               return IMG_FALSE;
+       }
+
+       if (phPriv != NULL)
+               *phPriv = pBT->hPriv;
+
+       *pBase = aligned_base;
+
+       return IMG_TRUE;
+}
 
 /*************************************************************************/ /*!
 @Function       _AttemptAllocAligned
@@ -910,18 +1009,17 @@ struct _BT_ *find_chunk_in_bucket(struct _BT_ * first_elt,
 */ /**************************************************************************/
 static IMG_BOOL
 _AttemptAllocAligned(RA_ARENA *pArena,
-                                        RA_LENGTH_T uSize,
-                                        RA_FLAGS_T uFlags,
-                                        RA_LENGTH_T uAlignment,
-                                        RA_BASE_T *base,
-                                        RA_PERISPAN_HANDLE *phPriv) /* this is the "per-import" private data */
+                     RA_LENGTH_T uSize,
+                     RA_FLAGS_T uFlags,
+                     RA_LENGTH_T uAlignment,
+                     RA_BASE_T *base,
+                     RA_PERISPAN_HANDLE *phPriv) /* this is the "per-import" private data */
 {
 
        IMG_UINT32 index_low;
        IMG_UINT32 index_high;
        IMG_UINT32 i;
        struct _BT_ *pBT = NULL;
-       RA_BASE_T aligned_base;
 
        PVR_ASSERT(pArena!=NULL);
        PVR_ASSERT(base != NULL);
@@ -994,88 +1092,104 @@ _AttemptAllocAligned(RA_ARENA *pArena,
                return IMG_FALSE;
        }
 
-       aligned_base = (uAlignment > 1) ? (pBT->base + uAlignment - 1) & ~(uAlignment - 1) : pBT->base;
+       return _AllocAlignSplit(pArena, pBT, uSize, uAlignment, base, phPriv);
+}
 
-       _FreeListRemove(pArena, pBT);
+/*************************************************************************/ /*!
+@Function       _AttemptImportSpanAlloc
+@Description    Attempt to Import more memory and create a new span.
+                Function attempts to import more memory from the callback
+                provided at RA creation time, if successful the memory
+                will form a new span in the RA.
+@Input          pArena            The arena.
+@Input          uRequestSize      The requested allocation size.
+@Input          uImportMultiplier Import x-times more for future requests if
+                                  we have to import new memory.
+@Input          uImportFlags      Flags influencing allocation policy.
+@Input          uAlignment        The alignment requirements of the allocation
+                                  Required uAlignment, or 0.
+                                  Must be a power of 2 if not 0
+@Input          pszAnnotation     String to describe the allocation
+@Output         pImportBase       Allocated import base
+                                  (non-optional, must not be NULL)
+@Output         pImportSize       Allocated import size
+@Output         pImportBT         Allocated import BT
+@Return         PVRSRV_OK - success
+*/ /**************************************************************************/
+static PVRSRV_ERROR
+_AttemptImportSpanAlloc(RA_ARENA *pArena,
+                        RA_LENGTH_T uRequestSize,
+                        IMG_UINT8 uImportMultiplier,
+                        RA_FLAGS_T uImportFlags,
+                        RA_LENGTH_T uAlignment,
+                        const IMG_CHAR *pszAnnotation,
+                        RA_BASE_T *pImportBase,
+                        RA_LENGTH_T *pImportSize,
+                        BT **pImportBT)
+{
+       IMG_HANDLE hPriv;
+       RA_FLAGS_T uFlags = (uImportFlags & PVRSRV_MEMALLOCFLAGS_RA_DIFFERENTIATION_MASK);
+       BT *pBT;
+       PVRSRV_ERROR eError;
 
-       if ((pArena->ui32PolicyFlags & RA_POLICY_NO_SPLIT_MASK) == RA_POLICY_NO_SPLIT)
+       *pImportSize = uRequestSize;
+       /*
+               Ensure that we allocate sufficient space to meet the uAlignment
+               constraint
+        */
+       if (uAlignment > pArena->uQuantum)
        {
-               goto nosplit;
+               *pImportSize += (uAlignment - pArena->uQuantum);
        }
 
-       /* with uAlignment we might need to discard the front of this segment */
-       if (aligned_base > pBT->base)
-       {
-               BT *pNeighbour;
-               pNeighbour = _SegmentSplit(pBT, (RA_LENGTH_T)(aligned_base - pBT->base));
-               /* partition the buffer, create a new boundary tag */
-               if (pNeighbour == NULL)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: Front split failed", __func__));
-                       /* Put pBT back in the list */
-                       _FreeListInsert(pArena, pBT);
-                       return IMG_FALSE;
-               }
+       /* apply over-allocation multiplier after all alignment adjustments */
+       *pImportSize *= uImportMultiplier;
 
-               _FreeListInsert(pArena, pBT);
-               pBT = pNeighbour;
-       }
+       /* ensure that we import according to the quanta of this arena */
+       *pImportSize = (*pImportSize + pArena->uQuantum - 1) & ~(pArena->uQuantum - 1);
 
-       /* the segment might be too big, if so, discard the back of the segment */
-       if (pBT->uSize > uSize)
+       eError = pArena->pImportAlloc(pArena->pImportHandle,
+                                                                 *pImportSize, uImportFlags,
+                                                                 pszAnnotation,
+                                                                 pImportBase, pImportSize,
+                                                                 &hPriv);
+       if (PVRSRV_OK != eError)
        {
-               BT *pNeighbour;
-               pNeighbour = _SegmentSplit(pBT, uSize);
-               /* partition the buffer, create a new boundary tag */
-               if (pNeighbour == NULL)
-               {
-                       PVR_DPF((PVR_DBG_ERROR, "%s: Back split failed", __func__));
-                       /* Put pBT back in the list */
-                       _FreeListInsert(pArena, pBT);
-                       return IMG_FALSE;
-               }
-
-               _FreeListInsert(pArena, pNeighbour);
+               return eError;
        }
-nosplit:
-       pBT->type = btt_live;
 
-       if (!HASH_Insert_Extended(pArena->pSegmentHash, &aligned_base, (uintptr_t)pBT))
+       /* If we successfully import more resource, create a span to
+        * represent it else free the resource we imported.
+        */
+       pBT = _InsertResourceSpan(pArena, *pImportBase, *pImportSize, uFlags);
+       if (pBT == NULL)
        {
-               _FreeBT(pArena, pBT);
-               return IMG_FALSE;
-       }
-
-       if (phPriv != NULL)
-               *phPriv = pBT->hPriv;
+               /* insufficient resources to insert the newly acquired span,
+                  so free it back again */
+               pArena->pImportFree(pArena->pImportHandle, *pImportBase, hPriv);
 
-       *base = aligned_base;
+               PVR_DPF((PVR_DBG_MESSAGE, "%s: name='%s', "
+                       "size=0x%llx failed!", __func__, pArena->name,
+                       (unsigned long long)uRequestSize));
+               /* RA_Dump (arena); */
 
-       return IMG_TRUE;
-}
+               return PVRSRV_ERROR_RA_INSERT_RESOURCE_SPAN_FAILED;
+       }
 
+       pBT->hPriv = hPriv;
+       *pImportBT = pBT;
 
+       return eError;
+}
 
-/*************************************************************************/ /*!
-@Function       RA_Create
-@Description    To create a resource arena.
-@Input          name          The name of the arena for diagnostic purposes.
-@Input          ulog2Quantum  The arena allocation quantum.
-@Input          ui32LockClass the lock class level this arena uses
-@Input          imp_alloc     A resource allocation callback or 0.
-@Input          imp_free      A resource de-allocation callback or 0.
-@Input          arena_handle  Handle passed to alloc and free or 0.
-@Input          ui32PolicyFlags Policies that govern the arena.
-@Return         arena handle, or NULL.
-*/ /**************************************************************************/
 IMG_INTERNAL RA_ARENA *
 RA_Create(IMG_CHAR *name,
-                 RA_LOG2QUANTUM_T uLog2Quantum,
-                 IMG_UINT32 ui32LockClass,
-                 PFN_RA_ALLOC imp_alloc,
-                 PFN_RA_FREE imp_free,
-                 RA_PERARENA_HANDLE arena_handle,
-                 IMG_UINT32 ui32PolicyFlags)
+          RA_LOG2QUANTUM_T uLog2Quantum,
+          IMG_UINT32 ui32LockClass,
+          PFN_RA_ALLOC imp_alloc,
+          PFN_RA_FREE imp_free,
+          RA_PERARENA_HANDLE arena_handle,
+          IMG_UINT32 ui32PolicyFlags)
 {
        RA_ARENA *pArena;
        PVRSRV_ERROR eError;
@@ -1116,6 +1230,8 @@ RA_Create(IMG_CHAR *name,
        pArena->per_flags_buckets = NULL;
        pArena->ui32LockClass = ui32LockClass;
        pArena->ui32PolicyFlags = ui32PolicyFlags;
+       pArena->ui64TotalArenaSize = 0;
+       pArena->ui64FreeArenaSize = 0;
 
        PVR_ASSERT(is_arena_valid(pArena));
        return pArena;
@@ -1198,12 +1314,6 @@ return_:
        return NULL;
 }
 
-/*************************************************************************/ /*!
-@Function       RA_Delete
-@Description    To delete a resource arena. All resources allocated from
-                the arena must be freed before deleting the arena.
-@Input          pArena        The arena to delete.
-*/ /**************************************************************************/
 IMG_INTERNAL void
 RA_Delete(RA_ARENA *pArena)
 {
@@ -1265,25 +1375,12 @@ RA_Delete(RA_ARENA *pArena)
        /* not nulling pointer, copy on stack */
 }
 
-/*************************************************************************/ /*!
-@Function       RA_Add
-@Description    To add a resource span to an arena. The span must not
-                overlap with any span previously added to the arena.
-@Input          pArena     The arena to add a span into.
-@Input          base       The base of the span.
-@Input          uSize      The extent of the span.
-@Input          uFlags     the flags of the new import
-@Input          hPriv      a private handle associate to the span.
-                          (reserved for user)
-@Return         IMG_TRUE - Success
-                IMG_FALSE - failure
-*/ /**************************************************************************/
 IMG_INTERNAL IMG_BOOL
 RA_Add(RA_ARENA *pArena,
-          RA_BASE_T base,
-          RA_LENGTH_T uSize,
-          RA_FLAGS_T uFlags,
-          RA_PERISPAN_HANDLE hPriv)
+       RA_BASE_T base,
+       RA_LENGTH_T uSize,
+       RA_FLAGS_T uFlags,
+       RA_PERISPAN_HANDLE hPriv)
 {
        struct _BT_* bt;
        PVR_ASSERT(pArena != NULL);
@@ -1315,40 +1412,24 @@ RA_Add(RA_ARENA *pArena,
        }
 
        PVR_ASSERT(is_arena_valid(pArena));
+
+       pArena->ui64TotalArenaSize += uSize;
+       pArena->ui64FreeArenaSize += uSize;
        OSLockRelease(pArena->hLock);
 
        return bt != NULL;
 }
 
-/*************************************************************************/ /*!
-@Function       RA_Alloc
-@Description    To allocate resource from an arena.
-@Input          pArena            The arena
-@Input          uRequestSize      The size of resource segment requested.
-@Input          uImportMultiplier Import x-times more for future requests if
-                                  we have to import new memory.
-@Input          uImportFlags      Flags influencing allocation policy.
-@Input          uAlignment        The uAlignment constraint required for the
-                                  allocated segment, use 0 if uAlignment not
-                                  required, otherwise must be a power of 2.
-@Input          pszAnnotation     String to describe the allocation
-@Output         base              Allocated base resource
-@Output         pActualSize       The actual size of resource segment
-                                  allocated, typically rounded up by quantum.
-@Output         phPriv            The user reference associated with allocated
-                                  resource span.
-@Return         PVRSRV_OK - success
-*/ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
 RA_Alloc(RA_ARENA *pArena,
-                RA_LENGTH_T uRequestSize,
-                IMG_UINT8 uImportMultiplier,
-                RA_FLAGS_T uImportFlags,
-                RA_LENGTH_T uAlignment,
-                const IMG_CHAR *pszAnnotation,
-                RA_BASE_T *base,
-                RA_LENGTH_T *pActualSize,
-                RA_PERISPAN_HANDLE *phPriv)
+         RA_LENGTH_T uRequestSize,
+         IMG_UINT8 uImportMultiplier,
+         RA_FLAGS_T uImportFlags,
+         RA_LENGTH_T uAlignment,
+         const IMG_CHAR *pszAnnotation,
+         RA_BASE_T *base,
+         RA_LENGTH_T *pActualSize,
+         RA_PERISPAN_HANDLE *phPriv)
 {
        PVRSRV_ERROR eError;
        IMG_BOOL bResult;
@@ -1358,7 +1439,7 @@ RA_Alloc(RA_ARENA *pArena,
        if (pArena == NULL || uImportMultiplier == 0 || uSize == 0)
        {
                PVR_DPF((PVR_DBG_ERROR,
-                                "%s: One of the necessary parameters is 0", __func__));
+                       "%s: One of the necessary parameters is 0", __func__));
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
@@ -1374,10 +1455,10 @@ RA_Alloc(RA_ARENA *pArena,
        PVR_ASSERT((uAlignment == 0) || (uAlignment & (uAlignment - 1)) == 0);
 
        PVR_DPF((PVR_DBG_MESSAGE,
-                        "%s: arena='%s', size=0x%llx(0x%llx), "
-                        "alignment=0x%llx", __func__, pArena->name,
-                        (unsigned long long)uSize, (unsigned long long)uRequestSize,
-                        (unsigned long long)uAlignment));
+               "%s: arena='%s', size=0x%llx(0x%llx), "
+               "alignment=0x%llx", __func__, pArena->name,
+               (unsigned long long)uSize, (unsigned long long)uRequestSize,
+               (unsigned long long)uAlignment));
 
        /* if allocation failed then we might have an import source which
           can provide more resource, else we will have to fail the
@@ -1385,100 +1466,73 @@ RA_Alloc(RA_ARENA *pArena,
        bResult = _AttemptAllocAligned(pArena, uSize, uFlags, uAlignment, base, phPriv);
        if (!bResult)
        {
-               IMG_HANDLE hPriv;
-               RA_BASE_T import_base;
-               RA_LENGTH_T uImportSize = uSize;
-
-               /*
-                       Ensure that we allocate sufficient space to meet the uAlignment
-                       constraint
-                */
-               if (uAlignment > pArena->uQuantum)
+               RA_BASE_T uImportBase;
+               RA_LENGTH_T uImportSize;
+               BT *pBT = NULL;
+
+               eError = _AttemptImportSpanAlloc(pArena,
+                                                uSize,
+                                                uImportMultiplier,
+                                                uFlags,
+                                                uAlignment,
+                                                pszAnnotation,
+                                                &uImportBase,
+                                                &uImportSize,
+                                                &pBT);
+               if (eError != PVRSRV_OK)
                {
-                       uImportSize += (uAlignment - pArena->uQuantum);
+                       OSLockRelease(pArena->hLock);
+                       return eError;
                }
 
-               /* apply over-allocation multiplier after all alignment adjustments */
-               uImportSize *= uImportMultiplier;
+               bResult = _AttemptAllocAligned(pArena, uSize, uFlags, uAlignment, base, phPriv);
+               if (!bResult)
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                               "%s: name='%s' second alloc failed!",
+                               __func__, pArena->name));
 
-               /* ensure that we import according to the quanta of this arena */
-               uImportSize = (uImportSize + pArena->uQuantum - 1) & ~(pArena->uQuantum - 1);
+                       /*
+                         On failure of _AttemptAllocAligned() depending on the exact point
+                         of failure, the imported segment may have been used and freed, or
+                         left untouched. If the later, we need to return it.
+                       */
+                       _FreeBT(pArena, pBT);
 
-               eError = pArena->pImportAlloc(pArena->pImportHandle,
-                                                                         uImportSize, uImportFlags,
-                                                                         pszAnnotation,
-                                                                         &import_base, &uImportSize,
-                                                                         &hPriv);
-               if (PVRSRV_OK != eError)
-               {
                        OSLockRelease(pArena->hLock);
-                       return eError;
+                       return PVRSRV_ERROR_RA_ATTEMPT_ALLOC_ALIGNED_FAILED;
                }
                else
                {
-                       BT *pBT;
-                       pBT = _InsertResourceSpan(pArena, import_base, uImportSize, uFlags);
-                       /* successfully import more resource, create a span to
-                          represent it and retry the allocation attempt */
-                       if (pBT == NULL)
-                       {
-                               /* insufficient resources to insert the newly acquired span,
-                                  so free it back again */
-                               pArena->pImportFree(pArena->pImportHandle, import_base, hPriv);
-
-                               PVR_DPF((PVR_DBG_MESSAGE, "%s: name='%s', "
-                                                "size=0x%llx failed!", __func__, pArena->name,
-                                                (unsigned long long)uSize));
-                               /* RA_Dump (arena); */
-
-                               OSLockRelease(pArena->hLock);
-                               return PVRSRV_ERROR_RA_INSERT_RESOURCE_SPAN_FAILED;
-                       }
-
-                       pBT->hPriv = hPriv;
-
-                       bResult = _AttemptAllocAligned(pArena, uSize, uFlags, uAlignment, base, phPriv);
-                       if (!bResult)
+                       /* Check if the new allocation was in the span we just added... */
+                       if (*base < uImportBase  ||  *base > (uImportBase + uImportSize))
                        {
                                PVR_DPF((PVR_DBG_ERROR,
-                                                "%s: name='%s' second alloc failed!",
-                                                __func__, pArena->name));
+                                       "%s: name='%s' alloc did not occur in the imported span!",
+                                       __func__, pArena->name));
 
                                /*
-                                 On failure of _AttemptAllocAligned() depending on the exact point
-                                 of failure, the imported segment may have been used and freed, or
-                                 left untouched. If the later, we need to return it.
+                                 Remove the imported span which should not be in use (if it is then
+                                 that is okay, but essentially no span should exist that is not used).
                                */
                                _FreeBT(pArena, pBT);
-
-                               OSLockRelease(pArena->hLock);
-                               return PVRSRV_ERROR_RA_ATTEMPT_ALLOC_ALIGNED_FAILED;
                        }
                        else
                        {
-                               /* Check if the new allocation was in the span we just added... */
-                               if (*base < import_base  ||  *base > (import_base + uImportSize))
-                               {
-                                       PVR_DPF((PVR_DBG_ERROR,
-                                                        "%s: name='%s' alloc did not occur in the imported span!",
-                                                        __func__, pArena->name));
-
-                                       /*
-                                         Remove the imported span which should not be in use (if it is then
-                                         that is okay, but essentially no span should exist that is not used).
-                                       */
-                                       _FreeBT(pArena, pBT);
-                               }
+                               pArena->ui64FreeArenaSize += uImportSize;
+                               pArena->ui64TotalArenaSize += uImportSize;
                        }
                }
        }
 
        PVR_DPF((PVR_DBG_MESSAGE, "%s: name='%s', size=0x%llx, "
-                        "*base=0x%llx = %d", __func__, pArena->name, (unsigned long long)uSize,
-                        (unsigned long long)*base, bResult));
+               "*base=0x%llx = %d", __func__, pArena->name, (unsigned long long)uSize,
+               (unsigned long long)*base, bResult));
 
        PVR_ASSERT(is_arena_valid(pArena));
 
+       pArena->ui64FreeArenaSize -= uSize;
+
        OSLockRelease(pArena->hLock);
        return PVRSRV_OK;
 }
@@ -1546,28 +1600,13 @@ static BT *RA_Find_BT_VARange(RA_ARENA *pArena,
        return NULL;
 }
 
-
-/*************************************************************************/ /*!
-@Function       RA_Alloc_Range
-@Description    To allocate requested device virtual address resource from an arena.
-@Input          pArena            The arena
-@Input          uRequestSize      The size of resource segment requested.
-@Input          uImportFlags            Flags influencing allocation policy.
-@Input          uAlignment        The uAlignment constraint required for the
-                                  allocated segment, use 0 if uAlignment not required, otherwise
-                                  must be a power of 2.
-@input          base              Allocated base resource
-@Output         pActualSize       The actual size of resource segment
-                                  allocated, typically rounded up by quantum.
-@Return         PVRSRV_OK - success
-*/ /**************************************************************************/
 IMG_INTERNAL PVRSRV_ERROR
 RA_Alloc_Range(RA_ARENA *pArena,
-                          RA_LENGTH_T uRequestSize,
-                          RA_FLAGS_T uImportFlags,
-                          RA_LENGTH_T uAlignment,
-                          RA_BASE_T base,
-                          RA_LENGTH_T *pActualSize)
+               RA_LENGTH_T uRequestSize,
+               RA_FLAGS_T uImportFlags,
+               RA_LENGTH_T uAlignment,
+               RA_BASE_T base,
+               RA_LENGTH_T *pActualSize)
 {
        RA_LENGTH_T uSize = uRequestSize;
        BT *pBT = NULL;
@@ -1575,8 +1614,8 @@ RA_Alloc_Range(RA_ARENA *pArena,
 
        if (pArena == NULL || uSize == 0)
        {
-               PVR_DPF ((PVR_DBG_ERROR,
-                               "%s: One of the necessary parameters is 0", __func__));
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: One of the necessary parameters is 0", __func__));
                return PVRSRV_ERROR_INVALID_PARAMS;
        }
 
@@ -1675,18 +1714,14 @@ RA_Alloc_Range(RA_ARENA *pArena,
                *pActualSize = uSize;
        }
 
+       pArena->ui64FreeArenaSize -= uSize;
+
 unlock_:
        OSLockRelease(pArena->hLock);
 
        return eError;
 }
 
-/*************************************************************************/ /*!
-@Function       RA_Free
-@Description    To free a resource segment.
-@Input          pArena     The arena the segment was originally allocated from.
-@Input          base       The base of the resource span to free.
-*/ /**************************************************************************/
 IMG_INTERNAL void
 RA_Free(RA_ARENA *pArena, RA_BASE_T base)
 {
@@ -1704,23 +1739,428 @@ RA_Free(RA_ARENA *pArena, RA_BASE_T base)
        PVR_ASSERT(is_arena_valid(pArena));
 
        PVR_DPF((PVR_DBG_MESSAGE, "%s: name='%s', base=0x%llx", __func__, pArena->name,
-                        (unsigned long long)base));
+               (unsigned long long)base));
 
        pBT = (BT *) HASH_Remove_Extended(pArena->pSegmentHash, &base);
        PVR_ASSERT(pBT != NULL);
 
        if (pBT)
        {
+               pArena->ui64FreeArenaSize += pBT->uSize;
+
                PVR_ASSERT(pBT->base == base);
                _FreeBT(pArena, pBT);
        }
        else
        {
-               PVR_DPF((PVR_DBG_ERROR, "%s: no resource span found for given base (0x%llX) in arena %s",
-                                                                               __func__, (unsigned long long) base,
-                                                                                       pArena->name));
+               PVR_DPF((PVR_DBG_ERROR,
+                       "%s: no resource span found for given base (0x%llX) in arena %s",
+                        __func__, (unsigned long long) base, pArena->name));
        }
 
        PVR_ASSERT(is_arena_valid(pArena));
        OSLockRelease(pArena->hLock);
 }
+
+IMG_INTERNAL void
+RA_Get_Usage_Stats(RA_ARENA *pArena, PRA_USAGE_STATS psRAStats)
+{
+       psRAStats->ui64TotalArenaSize = pArena->ui64TotalArenaSize;
+       psRAStats->ui64FreeArenaSize = pArena->ui64FreeArenaSize;
+}
+
+/* #define _DBG(...) PVR_LOG((__VA_ARGS__)) */
+#define _DBG(...)
+
+IMG_INTERNAL RA_ARENA_ITERATOR *
+RA_IteratorAcquire(RA_ARENA *pArena, IMG_BOOL bIncludeFreeSegments)
+{
+       RA_ARENA_ITERATOR *pIter = OSAllocMem(sizeof(*pIter));
+       PVR_LOG_RETURN_IF_FALSE(pIter != NULL, "OSAllocMem", NULL);
+
+       OSLockAcquireNested(pArena->hLock, pArena->ui32LockClass);
+
+       pIter->pArena = pArena;
+       pIter->bIncludeFreeSegments = bIncludeFreeSegments;
+
+       RA_IteratorReset(pIter);
+
+       return pIter;
+}
+
+IMG_INTERNAL void
+RA_IteratorRelease(RA_ARENA_ITERATOR *pIter)
+{
+       PVR_ASSERT(pIter != NULL);
+
+       if (pIter == NULL)
+       {
+               return;
+       }
+
+       OSLockRelease(pIter->pArena->hLock);
+
+       OSFreeMem(pIter);
+}
+
+IMG_INTERNAL void
+RA_IteratorReset(RA_ARENA_ITERATOR *pIter)
+{
+       BT *pNext;
+
+       PVR_ASSERT(pIter != NULL);
+
+       pNext = pIter->pArena->pHeadSegment;
+
+       /* find next element if we're not including the free ones */
+       if (!pIter->bIncludeFreeSegments)
+       {
+               while (pNext != NULL && pNext->type != btt_live)
+               {
+                       _DBG("(%s()) skipping segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+                            "type=%u", __func__, (void *) pNext->base, pNext->uSize,
+                            pNext->type);
+                       pNext = pNext->pNextSegment;
+               }
+       }
+
+       _DBG("(%s()) current segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+            "type=%u", __func__,
+            pNext != NULL ? (void *) pNext->base : NULL,
+            pNext != NULL ? pNext->uSize : 0,
+            pNext != NULL ? pNext->type : 0);
+
+       /* if bIncludeFreeSegments then pNext here is either a valid pointer to
+        * "live" segment or NULL and if !bIncludeFreeSegments then it's either
+        * a valid pointer to any next segment or NULL */
+       pIter->pCurrent = pNext;
+}
+
+IMG_INTERNAL IMG_BOOL
+RA_IteratorNext(RA_ARENA_ITERATOR *pIter, RA_ITERATOR_DATA *pData)
+{
+       BT *pNext;
+
+       PVR_ASSERT(pIter != NULL);
+
+       if (pIter == NULL)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "pIter in %s() is NULL", __func__));
+               return IMG_FALSE;
+       }
+
+       if (pIter->pCurrent == NULL)
+       {
+               return IMG_FALSE;
+       }
+
+       pNext = pIter->pCurrent;
+
+       _DBG("(%s()) current segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+            "type=%u", __func__, (void *) pNext->base, pNext->uSize,
+            pNext->type);
+
+       pData->uiAddr = pIter->pCurrent->base;
+       pData->uiSize = pIter->pCurrent->uSize;
+       pData->bFree = pIter->pCurrent->type == btt_free;
+
+       /* combine contiguous segments */
+       while ((pNext = pNext->pNextSegment) != NULL &&
+              pNext->type == btt_live &&
+              pNext->base == pData->uiAddr + pData->uiSize)
+       {
+               _DBG("(%s()) combining segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+                    "type=%u", __func__, (void *) pNext->base, pNext->uSize,
+                    pNext->type);
+               pData->uiSize += pNext->uSize;
+       }
+
+       /* advance to next */
+       if (!pIter->bIncludeFreeSegments)
+       {
+               while (pNext != NULL && pNext->type != btt_live)
+               {
+                       _DBG("(%s()) skipping segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+                            "type=%u", __func__, (void *) pNext->base, pNext->uSize,
+                            pNext->type);
+                       pNext = pNext->pNextSegment;
+               }
+       }
+
+       _DBG("(%s()) next segment=%px, size=0x%" IMG_UINT64_FMTSPECx ", "
+            "type=%u", __func__,
+            pNext != NULL ? (void *) pNext->base : NULL,
+            pNext != NULL ? pNext->uSize : 0,
+            pNext != NULL ? pNext->type : 0);
+
+       /* if bIncludeFreeSegments then pNext here is either a valid pointer to
+        * "live" segment or NULL and if !bIncludeFreeSegments then it's either
+        * a valid pointer to any next segment or NULL */
+       pIter->pCurrent = pNext;
+
+       return IMG_TRUE;
+}
+
+IMG_INTERNAL PVRSRV_ERROR
+RA_BlockDump(RA_ARENA *pArena, void (*pfnLogDump)(void*, IMG_CHAR*, ...), void *pPrivData)
+{
+       RA_ARENA_ITERATOR *pIter = NULL;
+       RA_ITERATOR_DATA sIterData;
+       const IMG_UINT32 uiLineWidth = 64;
+
+       IMG_UINT32 **papRegionArray = NULL;
+       IMG_UINT32 uiRegionCount = 0;
+
+       const IMG_UINT32 uiChunkSize = 32; /* 32-bit chunks */
+       const IMG_UINT32 uiChunkCount = (uiLineWidth / uiChunkSize) * 2; /* This should equal 2 or a multiple of 2 */
+       const IMG_UINT32 uiRegionSize = uiChunkSize * uiChunkCount;
+
+       IMG_UINT32 uiRecognisedQuantum = 0;
+
+       IMG_UINT32 uiLastBase = 0;
+       IMG_UINT32 uiLastSize = 0;
+
+       IMG_UINT32 i;
+       PVRSRV_ERROR eError = PVRSRV_OK;
+
+       /* -- papRegionArray Structure --
+        *  papRegionArray Indexes
+        *  |         Chunk 0      Chunk 1      Chunk 2      Chunk 3
+        *  v     |------------|------------|------------|------------|
+        * [0] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 | -- |
+        * [1] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 |    |
+        * [2] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 |    |
+        * [3] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 |    | Regions
+        * [4] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 |    |
+        * [5] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 |    |
+        * [6] -> | 0000000000 | 0000000000 | 0000000000 | 0000000000 | -- |
+        * ...
+        */
+
+       if (pArena == NULL || pfnLogDump == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       pIter = RA_IteratorAcquire(pArena, IMG_FALSE);
+       PVR_LOG_RETURN_IF_NOMEM(pIter, "RA_IteratorAcquire");
+
+       uiRecognisedQuantum = pArena->uQuantum > 0 ? pArena->uQuantum : 4096;
+
+       while (RA_IteratorNext(pIter, &sIterData))
+       {
+               if (sIterData.uiAddr >= uiLastBase)
+               {
+                       uiLastBase = sIterData.uiAddr;
+                       uiLastSize = sIterData.uiSize;
+               }
+       }
+
+       uiRegionCount = ((uiLastBase + uiLastSize) / uiRecognisedQuantum) / uiRegionSize;
+       if (((uiLastBase + uiLastSize) / uiRecognisedQuantum) % uiRegionSize != 0
+          || uiRegionCount == 0)
+       {
+               uiRegionCount += 1;
+       }
+
+       papRegionArray = OSAllocZMem(sizeof(IMG_UINT32*) * uiRegionCount);
+       PVR_LOG_GOTO_IF_NOMEM(papRegionArray, eError, cleanup_array);
+
+       RA_IteratorReset(pIter);
+
+       while (RA_IteratorNext(pIter, &sIterData))
+       {
+               IMG_UINT32 uiAddrRegionIdx = 0;
+               IMG_UINT32 uiAddrRegionOffset = 0;
+               IMG_UINT32 uiAddrChunkIdx = 0;
+               IMG_UINT32 uiAddrChunkOffset = 0;
+               IMG_UINT32 uiAddrChunkShift; /* The bit-shift needed to fill the chunk */
+
+               IMG_UINT32 uiQuantisedSize;
+               IMG_UINT32 uiQuantisedSizeMod;
+               IMG_UINT32 uiAllocLastRegionIdx = 0; /* The last region that this alloc appears in */
+               IMG_UINT32 uiAllocChunkSize = 0; /* The number of chunks this alloc spans */
+
+               IMG_INT32 iBitSetCount = 0;
+               IMG_INT32 iOverflowCheck = 0;
+               IMG_INT32 iOverflow = 0;
+               IMG_UINT32 uiRegionIdx = 0;
+               IMG_UINT32 uiChunkIdx = 0;
+
+#if defined(__KERNEL__) && defined(__linux__)
+               IMG_UINT64 uiDataDivRecQuant = sIterData.uiSize;
+               uiQuantisedSizeMod = do_div(uiDataDivRecQuant, uiRecognisedQuantum);
+               uiQuantisedSize = (IMG_UINT32)uiDataDivRecQuant;
+
+               uiDataDivRecQuant = sIterData.uiAddr;
+               do_div(uiDataDivRecQuant, uiRecognisedQuantum);
+               uiAddrRegionOffset = do_div(uiDataDivRecQuant, uiRegionSize);
+               uiAddrRegionIdx = (IMG_UINT32)uiDataDivRecQuant;
+
+               uiDataDivRecQuant = sIterData.uiAddr;
+               do_div(uiDataDivRecQuant, uiRecognisedQuantum);
+#else
+               IMG_UINT64 uiDataDivRecQuant = sIterData.uiAddr / uiRecognisedQuantum;
+               uiAddrRegionIdx = uiDataDivRecQuant / uiRegionSize;
+               uiAddrRegionOffset = uiDataDivRecQuant % uiRegionSize;
+
+               uiQuantisedSize = sIterData.uiSize / uiRecognisedQuantum;
+               uiQuantisedSizeMod = sIterData.uiSize % uiRecognisedQuantum;
+#endif
+               uiAddrChunkIdx = uiAddrRegionOffset / uiChunkSize;
+               uiAddrChunkOffset = uiAddrRegionOffset % uiChunkSize;
+               uiAddrChunkShift = uiChunkSize - uiAddrChunkOffset;
+               uiRegionIdx = uiAddrRegionIdx;
+               uiChunkIdx = uiAddrChunkIdx;
+
+               if ((uiQuantisedSize == 0) || (uiQuantisedSizeMod != 0))
+               {
+                       uiQuantisedSize += 1;
+               }
+
+#if defined(__KERNEL__) && defined(__linux__)
+               uiDataDivRecQuant += uiQuantisedSize - 1;
+               do_div(uiDataDivRecQuant, uiRegionSize);
+               uiAllocLastRegionIdx = (IMG_UINT32)uiDataDivRecQuant;
+#else
+               uiAllocLastRegionIdx =
+                   (uiDataDivRecQuant + uiQuantisedSize - 1) / uiRegionSize;
+#endif
+               uiAllocChunkSize = (uiAddrChunkOffset + uiQuantisedSize) / uiChunkSize;
+
+               if ((uiAddrChunkOffset + uiQuantisedSize) % uiChunkSize > 0)
+               {
+                       uiAllocChunkSize += 1;
+               }
+
+               iBitSetCount = uiQuantisedSize;
+               iOverflowCheck = uiQuantisedSize - uiAddrChunkShift;
+
+               if (iOverflowCheck > 0)
+               {
+                       iOverflow = iOverflowCheck;
+                       iBitSetCount = uiQuantisedSize - iOverflow;
+               }
+
+               /**
+                * Allocate memory to represent the chunks for each region the allocation
+                * spans. If one was already allocated before don't do it again.
+                */
+               for (i = 0; uiAddrRegionIdx + i <= uiAllocLastRegionIdx; i++)
+               {
+                       if (papRegionArray[uiAddrRegionIdx + i] == NULL)
+                       {
+                               papRegionArray[uiAddrRegionIdx + i] = OSAllocZMem(sizeof(IMG_UINT32) * uiChunkCount);
+                               PVR_LOG_GOTO_IF_NOMEM(papRegionArray[uiAddrRegionIdx + i], eError, cleanup_regions);
+                       }
+               }
+
+               for (i = 0; i < uiAllocChunkSize; i++)
+               {
+                       if (uiChunkIdx >= uiChunkCount)
+                       {
+                               uiRegionIdx++;
+                               uiChunkIdx = 0;
+                       }
+
+                       if ((IMG_UINT32)iBitSetCount != uiChunkSize)
+                       {
+                               IMG_UINT32 uiBitMask = 0;
+
+                               uiBitMask = (1U << iBitSetCount) - 1;
+                               uiBitMask <<= (uiAddrChunkShift - iBitSetCount);
+
+                               papRegionArray[uiRegionIdx][uiChunkIdx] |= uiBitMask;
+                       }
+                       else
+                       {
+                               papRegionArray[uiRegionIdx][uiChunkIdx] |= 0xFFFFFFFF;
+                       }
+
+                       uiChunkIdx++;
+                       iOverflow -= uiChunkSize;
+                       iBitSetCount = iOverflow >= 0 ? uiChunkSize : uiChunkSize + iOverflow;
+                       if (iOverflow < 0)
+                       {
+                               uiAddrChunkShift = 32;
+                       }
+               }
+       }
+
+       RA_IteratorRelease(pIter);
+
+       pfnLogDump(pPrivData, "~~~ '%s' Resource Arena Block Dump", pArena->name);
+       pfnLogDump(pPrivData, "    Block Size: %uB", uiRecognisedQuantum);
+       pfnLogDump(pPrivData,
+                  "    Span Memory Usage: %"IMG_UINT64_FMTSPEC"B"
+                  "    Free Span Memory: %"IMG_UINT64_FMTSPEC"B",
+                  pArena->ui64TotalArenaSize,
+                  pArena->ui64FreeArenaSize);
+       pfnLogDump(pPrivData,
+                  "===============================================================================");
+
+       for (i = 0; i < uiRegionCount; i++)
+       {
+               static IMG_BOOL bEmptyRegion = IMG_FALSE;
+               if (papRegionArray[i] != NULL)
+               {
+                       IMG_CHAR pszLine[65];
+                       IMG_UINT32 j;
+
+                       bEmptyRegion = IMG_FALSE;
+                       pszLine[64] = '\0';
+
+                       for (j = 0; j < uiChunkCount; j+=2)
+                       {
+                               IMG_UINT8 uiBit = 0;
+                               IMG_UINT32 k;
+                               IMG_UINT64 uiLineAddress =
+                                   (i * uiRegionSize + (j >> 1) * uiLineWidth) * uiRecognisedQuantum;
+
+                               /**
+                                * Move through each of the 32 bits in the chunk and check their
+                                * value. If it is 1 we set the corresponding character to '#',
+                                * otherwise it is set to '.' representing empty space
+                                */
+                               for (k = 1 << 31; k != 0; k >>= 1)
+                               {
+                                       pszLine[uiBit] = papRegionArray[i][j] & k ? '#' : '.';
+                                       pszLine[32 + uiBit] = papRegionArray[i][j+1] & k ? '#' : '.';
+                                       uiBit++;
+                               }
+
+                               pfnLogDump(pPrivData,
+                                          "| 0x%08"IMG_UINT64_FMTSPECx" | %s",
+                                          uiLineAddress,
+                                          pszLine);
+                       }
+                       OSFreeMem(papRegionArray[i]);
+               }
+               else
+               {
+                       /* We only print this once per gap of n regions */
+                       if (!bEmptyRegion)
+                       {
+                               pfnLogDump(pPrivData, "     ....");
+                               bEmptyRegion = IMG_TRUE;
+                       }
+               }
+       }
+       OSFreeMem(papRegionArray);
+       return eError;
+
+cleanup_regions:
+       for (i = 0; i < uiRegionCount; i++)
+       {
+               if (papRegionArray[i] != NULL)
+               {
+                       OSFreeMem(papRegionArray[i]);
+               }
+       }
+
+cleanup_array:
+       OSFreeMem(papRegionArray);
+       RA_IteratorRelease(pIter);
+
+       return eError;
+}
index 57a3afd..36234ae 100644 (file)
@@ -60,10 +60,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "log2.h"
 #if defined(__KERNEL__)
 #include "pvrsrv.h"
+#include "srvcore.h"
+#else
+#include "srvcore_intern.h"
 #endif
 
-#include "devicemem_utils.h"
-#include "client_cache_bridge.h"
 
 #define SYNC_BLOCK_LIST_CHUNCK_SIZE    10
 
@@ -119,9 +120,6 @@ static PVRSRV_ERROR
 AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext,
                         SYNC_PRIM_BLOCK **ppsSyncBlock)
 {
-#ifdef CACHE_TEST
-       struct DEVMEM_MEMDESC_TAG *pxmdsc = NULL;
-#endif
        SYNC_PRIM_BLOCK *psSyncBlk;
        IMG_HANDLE hSyncPMR;
        IMG_HANDLE hSyncImportHandle;
@@ -166,18 +164,6 @@ AllocSyncPrimitiveBlock(SYNC_PRIM_CONTEXT *psContext,
        eError = DevmemAcquireCpuVirtAddr(psSyncBlk->hMemDesc,
                                          (void **) &psSyncBlk->pui32LinAddr);
        PVR_GOTO_IF_ERROR(eError, fail_cpuvaddr);
-#ifdef CACHE_TEST
-       pxmdsc = (struct DEVMEM_MEMDESC_TAG *)psSyncBlk->hMemDesc;
-       printk("in %s L:%d mdsc->size:%lld, import->size:%lld, flag:%llx\n", __func__, __LINE__, pxmdsc->uiAllocSize, pxmdsc->psImport->uiSize, (unsigned long long)(pxmdsc->psImport->uiFlags & PVRSRV_MEMALLOCFLAG_CPU_CACHE_MODE_MASK));
-       if(pxmdsc->uiAllocSize > 4096 && !(PVRSRV_CHECK_CPU_UNCACHED(pxmdsc->psImport->uiFlags) || PVRSRV_CHECK_CPU_WRITE_COMBINE(pxmdsc->psImport->uiFlags)))
-       {
-               printk("in %s L:%d cache_op:%d\n", __func__, __LINE__,PVRSRV_CACHE_OP_INVALIDATE);
-               BridgeCacheOpExec (GetBridgeHandle(pxmdsc->psImport->hDevConnection),pxmdsc->psImport->hPMR,(IMG_UINT64)(uintptr_t)psSyncBlk->pui32LinAddr - pxmdsc->uiOffset,pxmdsc->uiOffset,pxmdsc->uiAllocSize,PVRSRV_CACHE_OP_INVALIDATE);
-       }
-#endif
-
-
-       
 
        *ppsSyncBlock = psSyncBlk;
        return PVRSRV_OK;
@@ -201,7 +187,9 @@ FreeSyncPrimitiveBlock(SYNC_PRIM_BLOCK *psSyncBlk)
 
        DevmemReleaseCpuVirtAddr(psSyncBlk->hMemDesc);
        DevmemFree(psSyncBlk->hMemDesc);
-       BridgeFreeSyncPrimitiveBlock(GetBridgeHandle(psContext->hDevConnection),
+       (void) DestroyServerResource(psContext->hDevConnection,
+                                    NULL,
+                                    BridgeFreeSyncPrimitiveBlock,
                                     psSyncBlk->hServerSyncPrimBlock);
        OSFreeMem(psSyncBlk);
 }
@@ -325,16 +313,19 @@ static void SyncPrimLocalFree(SYNC_PRIM *psSyncInt, IMG_BOOL bFreeFirstSyncPrim)
 #endif
        {
                PVRSRV_ERROR eError;
-               IMG_HANDLE hBridge =
-                               GetBridgeHandle(psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection);
+               SHARED_DEV_CONNECTION hDevConnection =
+                       psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection;
 
-               if (GetInfoPageDebugFlags(psSyncInt->u.sLocal.psSyncBlock->psContext->hDevConnection) & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED)
+               if (GetInfoPageDebugFlags(hDevConnection) & DEBUG_FEATURE_FULL_SYNC_TRACKING_ENABLED)
                {
                        if (psSyncInt->u.sLocal.hRecord)
                        {
                                /* remove this sync record */
-                               eError = BridgeSyncRecordRemoveByHandle(hBridge,
-                                                                       psSyncInt->u.sLocal.hRecord);
+                               eError = DestroyServerResource(hDevConnection,
+                                                              NULL,
+                                                              BridgeSyncRecordRemoveByHandle,
+                                                              psSyncInt->u.sLocal.hRecord);
+                               PVR_LOG_IF_ERROR(eError, "BridgeSyncRecordRemoveByHandle");
                        }
                }
                else
@@ -342,7 +333,7 @@ static void SyncPrimLocalFree(SYNC_PRIM *psSyncInt, IMG_BOOL bFreeFirstSyncPrim)
                        IMG_UINT32 ui32FWAddr = psSyncBlock->ui32FirmwareAddr +
                                        SyncPrimGetOffset(psSyncInt);
 
-                       eError = BridgeSyncFreeEvent(hBridge, ui32FWAddr);
+                       eError = BridgeSyncFreeEvent(GetBridgeHandle(hDevConnection), ui32FWAddr);
                        PVR_LOG_IF_ERROR(eError, "BridgeSyncFreeEvent");
                }
 #if defined(PVRSRV_ENABLE_SYNC_POISONING)
index 8d7b6e0..dc3f17a 100644 (file)
@@ -70,6 +70,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "pvrsrv_tlcommon.h"
 #include "client_pvrtl_bridge.h"
 
+#if defined(__KERNEL__)
+#include "srvcore.h"
+#else
+#include "srvcore_intern.h"
+#endif
+
 /* Defines/Constants
  */
 
@@ -94,9 +100,12 @@ typedef struct _TL_STREAM_DESC_
         * is outstanding. Undefined at all other times. */
        IMG_UINT32      uiReadLen;
 
-       /* Flag indicating if the RESERVE_TOO_BIG error was already printed.
-        * It's used to reduce number of errors in kernel log. */
-       IMG_BOOL bPrinted;
+       /* Counter indicating how many writes to a stream failed.
+        * It's used to reduce number of errors in output log. */
+       IMG_UINT32 ui32WritesFailed;
+
+       /* Name of the stream. */
+       IMG_CHAR szName[PRVSRVTL_MAX_STREAM_NAME_SIZE];
 } TL_STREAM_DESC, *PTL_STREAM_DESC;
 
 
@@ -164,6 +173,9 @@ PVRSRV_ERROR TLClientOpenStream(SHARED_DEV_CONNECTION hDevConnection,
        (void) DevmemUnmakeLocalImportHandle(hDevConnection,
                        hTLImportHandle);
 
+       /* Copy stream name */
+       OSStringLCopy(psSD->szName, pszName, PRVSRVTL_MAX_STREAM_NAME_SIZE);
+
        /* Return client descriptor handle to caller */
        *phSD = psSD;
        return PVRSRV_OK;
@@ -220,10 +232,19 @@ PVRSRV_ERROR TLClientCloseStream(SHARED_DEV_CONNECTION hDevConnection,
 
        /* Send close to server to clean up kernel mode resources for this
         * handle and release the memory. */
-       eError = BridgeTLCloseStream(GetBridgeHandle(hDevConnection),
-                       psSD->hServerSD);
+       eError = DestroyServerResource(hDevConnection,
+                                      NULL,
+                                      BridgeTLCloseStream,
+                                      psSD->hServerSD);
        PVR_LOG_IF_ERROR(eError, "BridgeTLCloseStream");
 
+       if (psSD->ui32WritesFailed != 0)
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s() %u writes failed to stream %s (%c)",
+                       __func__, psSD->ui32WritesFailed, psSD->szName,
+                       psSD->ui32WritesFailed == IMG_UINT32_MAX ? 'T' : 'F'));
+       }
+
        OSCachedMemSet(psSD, 0x00, sizeof(TL_STREAM_DESC));
        OSFreeMem(psSD);
 
@@ -454,11 +475,21 @@ PVRSRV_ERROR TLClientWriteData(SHARED_DEV_CONNECTION hDevConnection,
 
        eError = BridgeTLWriteData(GetBridgeHandle(hDevConnection),
                        psSD->hServerSD, ui32Size, pui8Data);
-       PVR_LOG_IF_ERROR(eError, "BridgeTLWriteData");
 
-       if (eError == PVRSRV_ERROR_STREAM_FULL && !psSD->bPrinted)
+       if (eError == PVRSRV_ERROR_STREAM_FULL)
+       {
+               if (psSD->ui32WritesFailed == 0)
+               {
+                       PVR_LOG_ERROR(eError, "BridgeTLWriteData");
+               }
+               if (psSD->ui32WritesFailed != IMG_UINT32_MAX)
+               {
+                       psSD->ui32WritesFailed++;
+               }
+       }
+       else if (eError != PVRSRV_OK)
        {
-               psSD->bPrinted = IMG_TRUE;
+               PVR_LOG_ERROR(eError, "BridgeTLWriteData");
        }
 
        return eError;
diff --git a/drivers/gpu/drm/img/img-rogue/services/shared/commonall_symbols.csv b/drivers/gpu/drm/img/img-rogue/services/shared/commonall_symbols.csv
deleted file mode 100755 (executable)
index 294e4f7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/tlclient.c,TLClientOpenStream 107,TLClientCloseStream 191,TLClientDiscoverStreams 237,TLClientReserveStream 255,TLClientReserveStream2 281,TLClientCommitStream 305,TLClientAcquireData 325,_TLClientReleaseDataLen 381,TLClientReleaseData 412,TLClientReleaseDataLess 424,TLClientWriteData 445
-/ra.c,_RequestAllocFail 222,pvr_log2 265-0,pvr_log2 273-1,_IsInSegmentList 300,_IsInFreeList 327,is_arena_valid 360,_SegmentListInsertAfter 436,_SegmentListInsert 457,_SegmentListRemove 479,_BuildBT 502,_SegmentSplit 536,_FreeListInsert 566,_FreeListRemove 661,_InsertResource 720,_InsertResourceSpan 756,_RemoveResourceSpan 777,_FreeBT 805,find_chunk_in_bucket 870,RA_Create 1078,_LogRegionCreation 1135,RA_Create_With_Span 1174,RA_Delete 1208,RA_Add 1286,RA_Alloc 1351,RA_Find_BT_VARange 1499,RA_Alloc_Range 1570,RA_Free 1691
-/sync.c,_SyncPrimContextUnref 85,_SyncPrimContextRef 101,AllocSyncPrimitiveBlock 118,FreeSyncPrimitiveBlock 181,SyncPrimBlockImport 199,SyncPrimBlockUnimport 255,SyncPrimGetOffset 276,SyncPrimGetCPULinAddr 287,SyncPrimLocalFree 295,SyncPrimLocalUnref 350,SyncPrimGetFirmwareAddrLocal 362,_Log2 370,SyncPrimContextCreate 382,SyncPrimContextDestroy 456,_SyncPrimAlloc 488,SyncPrimAlloc 600,_SyncPrimSetValue 609,SyncPrimFree 634,SyncPrimNoHwUpdate 666,SyncPrimSet 687,SyncPrimLocalGetHandleAndOffset 712,SyncPrimGetFirmwareAddr 740,SyncPrimPDump 771,SyncPrimPDumpValue 798,SyncPrimPDumpPol 830,SyncPrimPDumpCBP 864
-/hash.c,HASH_Func_Default 124,HASH_Key_Comp_Default 164,_ChainInsert 191,_Rehash 218,_Resize 246,HASH_Create_Extended_Int 311,HASH_Create_Extended_Debug 352,HASH_Create_Int 377,HASH_Create_Debug 385,HASH_Delete_Extended 409,HASH_Delete 477,HASH_Insert_Extended 493,HASH_Insert 542,HASH_Remove_Extended 556,HASH_Remove 610,HASH_Retrieve_Extended 624,HASH_Retrieve 661,HASH_Iterate 675,HASH_Dump 706
-/devicememx_pdump.c,DevmemXPDumpLoadMem 57
-/mem_utils.c,DeviceMemCopy 183,DeviceMemSet 280,DeviceMemCopyBytes 364,DeviceMemSetBytes 377,StringLCopy 398-0,StringLCopy 430-1
-/pvrsrv_error.c,PVRSRVGetErrorString 47
-/devicemem_utils.c,DevmemCPUMapSVMKernelManaged 73,DevmemCPUUnmapSVMKernelManaged 128,DevmemCPUMapSVMUserManaged 138,DevmemCPUUnmapSVMUserManaged 257,DevmemImportStructDevMapSVM 273,DevmemImportStructDevUnmapSVM 317,DevmemImportStructAcquire 347,DevmemImportStructRelease 361,DevmemImportDiscard 388,DevmemMemDescAlloc 398,DevmemMemDescInit 441,DevmemMemDescAcquire 462,DevmemMemDescRelease 477,DevmemMemDescDiscard 541,DevmemValidateParams 555,DevmemImportStructAlloc 597,DevmemImportStructInit 659,DevmemReserveVARange 681,DevmemImportStructDevMap 723,DevmemImportStructDevUnmap 1016,DevmemImportStructCPUMap 1085,DevmemImportStructCPUUnmap 1134
-/devicemem_pdump.c,DevmemPDumpLoadMem 65,DevmemPDumpLoadZeroMem 86,DevmemPDumpLoadMemValue32 107,DevmemPDumpLoadMemValue64 125,DevmemPDumpPageCatBaseToSAddr 142,DevmemPDumpSaveToFile 173,DevmemPDumpSaveToFileVirtual 195,DevmemPDumpDataDescriptor 225,DevmemPDumpDevmemPol32 255,DevmemPDumpDevmemCheck32 294,DevmemPDumpCBP 336
-/htbuffer.c,HTBControl 82,_HTBLog 100,HTBLog 153,HTBLogSimple 173
-/devicemem.c,_GetPremappedVA 104,DevmemOverrideFlagsOrPassThrough 159,CheckAnnotationLength 210,AllocateDeviceMemory 233,DeviceMemChangeSparse 306,FreeDeviceMemory 431,SubAllocImportAlloc 444,SubAllocImportFree 588,PopulateContextFromBlueprint 610,UnpopulateContextFromBlueprint 697,DevmemCreateContext 746,DevmemAcquireDevPrivData 804,DevmemReleaseDevPrivData 820,DevmemFindHeapByName 836,DevmemDestroyContext 856,DevmemHeapConfigCount 910,DevmemHeapCount 921,DevmemHeapConfigName 934,DevmemHeapDetails 954,DevmemGetHeapInt 980,DevmemCreateHeap 998,DevmemGetHeapBaseDevVAddr 1213,DevmemExportalignAdjustSizeAndAlign 1225,DevmemDestroyHeap 1255,DevmemSubAllocateAndMap 1338,_MemSet 1368,DevmemSubAllocate 1388,DevmemAllocateExportable 1672,DevmemAllocateSparse 1773,DevmemMakeLocalImportHandle 1865,DevmemUnmakeLocalImportHandle 1874,_Mapping_Export 1890,_Mapping_Unexport 1937,DevmemExport 1950,DevmemUnexport 1998,DevmemImport 2010,DevmemUnpin 2091,DevmemPin 2175,DevmemGetSize 2226,DevmemGetAnnotation 2236,DevmemFree 2249,DevmemReleaseDevAddrAndFree 2263,DevmemMapToDevice 2272,DevmemMapToDeviceAddress 2378,DevmemGetDevVirtAddr 2472,DevmemAcquireDevVirtAddr 2486,DevmemReleaseDevVirtAddr 2522,DevmemAcquireCpuVirtAddr 2568,DevmemReacquireCpuVirtAddr 2652,DevmemReleaseCpuVirtAddr 2684,DevmemLocalGetImportHandle 2719,DevmemGetImportUID 2734,DevmemGetReservation 2757,DevmemGetPMRData 2779,DevmemGetFlags 2796,DevmemGetConnection 2808,DevmemLocalImport 2820,DevmemIsDevVirtAddrValid 2908,DevmemGetFaultAddress 2918,DevmemFlushDeviceSLCRange 2928,DevmemInvalidateFBSCTable 2941,DevmemGetHeapLog2PageSize 2952,DevmemGetHeapReservedSize 2958,RegisterDevmemPFNotify 2979,DevmemHeapSetPremapStatus 2997
-/uniq_key_splay_tree.c,PVRSRVSplay 57,PVRSRVInsert 154,PVRSRVDelete 214,PVRSRVFindNode 252
index 472dd57..268ba65 100644 (file)
@@ -158,12 +158,9 @@ static bool rgxfw_hwperf_pow_st_indirect(RGX_HWPERF_CNTBLK_ID eBlkType, IMG_UINT
 
 # define rgxfw_hwperf_pow_st_direct   ((void*)NULL)
 # define rgxfw_hwperf_pow_st_indirect ((void*)NULL)
-# define rgxfw_hwperf_pow_st_gandalf  ((void*)NULL)
 
 #endif /* !defined(RGX_FIRMWARE) || !defined(RGX_FEATURE_PERFBUS) */
 
-# define rgxfw_hwperf_pow_st_gandalf  ((void*)NULL)
-
 /*****************************************************************************
  RGXFW_HWPERF_CNTBLK_TYPE_MODEL struct PFNs pfnIsBlkPowered() end
  *****************************************************************************/
index d0ce7a7..3de9e67 100644 (file)
@@ -51,7 +51,47 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 extern "C" {
 #endif
 
-#if !defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) || !defined(DEBUG) || !defined(PVRSRV_ENABLE_PROCESS_STATS) || !defined(PVRSRV_ENABLE_MEMORY_STATS) || defined(DOXYGEN)
+/*
+ * PVRSRV_ENABLE_PROCESS_STATS enables process statistics regarding events,
+ *     resources and memory across all processes
+ * PVRSRV_ENABLE_MEMORY_STATS enables recording of Linux kernel memory
+ *     allocations, provided that PVRSRV_ENABLE_PROCESS_STATS is enabled
+ *   - Output can be found in:
+ *     /(sys/kernel/debug|proc)/pvr/proc_stats/[live|retired]_pids_stats/mem_area
+ * PVRSRV_DEBUG_LINUX_MEMORY_STATS provides more details about memory
+ *     statistics in conjunction with PVRSRV_ENABLE_MEMORY_STATS
+ * PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON is defined to encompass both memory
+ *     allocation statistics functionalities described above in a single macro
+ */
+#if defined(PVRSRV_ENABLE_PROCESS_STATS) && defined(PVRSRV_ENABLE_MEMORY_STATS) && defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS) && defined(DEBUG)
+#define PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
+#endif
+
+/*
+ * When using detailed memory allocation statistics, the line number and
+ * file name where the allocation happened are also provided.
+ * When this feature is not used, these parameters are not needed.
+ */
+#if defined(PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON)
+#define DEBUG_MEMSTATS_PARAMS ,void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine
+#define DEBUG_MEMSTATS_ARGS   ,pvAllocFromFile, ui32AllocFromLine
+#define DEBUG_MEMSTATS_UNREF  (void)pvAllocFromFile; (void)ui32AllocFromLine;
+#define DEBUG_MEMSTATS_VALUES ,__FILE__, __LINE__
+#else
+#define DEBUG_MEMSTATS_PARAMS /*!<
+                                 * Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
+                                 * build option. */
+#define DEBUG_MEMSTATS_ARGS   /*!<
+                                 * Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
+                                 * build option. */
+#define DEBUG_MEMSTATS_UNREF  /*!<
+                                 * Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
+                                 * build option. */
+#define DEBUG_MEMSTATS_VALUES  /*!<
+                                 * Used for PVRSRV_DEBUG_LINUX_MEMORY_STATS_ON
+                                 * build option. */
+#endif
+
 
 /**************************************************************************/ /*!
 @Function       OSAllocMem
@@ -62,8 +102,13 @@ extern "C" {
 @Return         Pointer to allocated memory on success.
                 Otherwise NULL.
  */ /**************************************************************************/
+#if defined(DOXYGEN)
 void *OSAllocMem(IMG_UINT32 ui32Size);
-#define OSAllocMem(_size) (OSAllocMem)((_size))
+#else
+void *OSAllocMem(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS);
+#define OSAllocMem(_size)      (OSAllocMem)((_size) DEBUG_MEMSTATS_VALUES)
+#endif
+
 /**************************************************************************/ /*!
 @Function       OSAllocZMem
 @Description    Allocates CPU memory and initializes the contents to zero.
@@ -73,27 +118,25 @@ void *OSAllocMem(IMG_UINT32 ui32Size);
 @Return         Pointer to allocated memory on success.
                 Otherwise NULL.
  */ /**************************************************************************/
+#if defined(DOXYGEN)
 void *OSAllocZMem(IMG_UINT32 ui32Size);
-#define OSAllocZMem(_size) (OSAllocZMem)((_size))
-
 #else
-void *OSAllocMem(IMG_UINT32 ui32Size, void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine);
-void *OSAllocZMem(IMG_UINT32 ui32Size, void *pvAllocFromFile, IMG_UINT32 ui32AllocFromLine);
-#define OSAllocMem(_size)      (OSAllocMem)((_size), (__FILE__), (__LINE__))
-#define OSAllocZMem(_size)     (OSAllocZMem)((_size), (__FILE__), (__LINE__))
+void *OSAllocZMem(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS);
+#define OSAllocZMem(_size)     (OSAllocZMem)((_size) DEBUG_MEMSTATS_VALUES)
 #endif
 
+
 /**************************************************************************/ /*!
 @Function       OSAllocMemNoStats
 @Description    Allocates CPU memory. Contents are uninitialized.
-                If passed a size of zero, function should not assert,
-                but just return a NULL pointer.
-                The allocated memory is not accounted for by process stats.
-                Process stats are an optional feature (enabled only when
-                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
-                of memory allocated to help in debugging. Where this is not
-                required, OSAllocMem() and OSAllocMemNoStats() equate to
-                the same operation.
+                 If passed a size of zero, function should not assert,
+                 but just return a NULL pointer.
+                 The allocated memory is not accounted for by process stats.
+                 Process stats are an optional feature (enabled only when
+                 PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                 of memory allocated to help in debugging. Where this is not
+                 required, OSAllocMem() and OSAllocMemNoStats() equate to
+                 the same operation.
 @Input          ui32Size        Size of required allocation (in bytes)
 @Return         Pointer to allocated memory on success.
                 Otherwise NULL.
@@ -103,14 +146,14 @@ void *OSAllocMemNoStats(IMG_UINT32 ui32Size);
 /**************************************************************************/ /*!
 @Function       OSAllocZMemNoStats
 @Description    Allocates CPU memory and initializes the contents to zero.
-                If passed a size of zero, function should not assert,
-                but just return a NULL pointer.
-                The allocated memory is not accounted for by process stats.
-                Process stats are an optional feature (enabled only when
-                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
-                of memory allocated to help in debugging. Where this is not
-                required, OSAllocZMem() and OSAllocZMemNoStats() equate to
-                the same operation.
+                 If passed a size of zero, function should not assert,
+                 but just return a NULL pointer.
+                 The allocated memory is not accounted for by process stats.
+                 Process stats are an optional feature (enabled only when
+                 PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                 of memory allocated to help in debugging. Where this is not
+                 required, OSAllocZMem() and OSAllocZMemNoStats() equate to
+                 the same operation.
 @Input          ui32Size        Size of required allocation (in bytes)
 @Return         Pointer to allocated memory on success.
                 Otherwise NULL.
@@ -128,12 +171,12 @@ void OSFreeMem(void *pvCpuVAddr);
 /**************************************************************************/ /*!
 @Function       OSFreeMemNoStats
 @Description    Frees previously allocated CPU memory.
-                The freed memory does not update the figures in process stats.
-                Process stats are an optional feature (enabled only when
-                PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
-                of memory allocated to help in debugging. Where this is not
-                required, OSFreeMem() and OSFreeMemNoStats() equate to the
-                same operation.
+                 The freed memory does not update the figures in process stats.
+                 Process stats are an optional feature (enabled only when
+                 PVRSRV_ENABLE_PROCESS_STATS is defined) which track the amount
+                 of memory allocated to help in debugging. Where this is not
+                 required, OSFreeMem() and OSFreeMemNoStats() equate to the
+                 same operation.
 @Input          pvCpuVAddr       Pointer to the memory to be freed.
 @Return         None.
  */ /**************************************************************************/
index 120ea4b..1466eb3 100644 (file)
@@ -636,7 +636,7 @@ PVRSRV_ERROR
 DevmemGetReservation(DEVMEM_MEMDESC *psMemDesc,
                     IMG_HANDLE *hReservation);
 
-IMG_INTERNAL PVRSRV_ERROR
+IMG_INTERNAL void
 DevmemGetPMRData(DEVMEM_MEMDESC *psMemDesc,
                IMG_HANDLE *hPMR,
                IMG_DEVMEM_OFFSET_T *puiPMROffset);
@@ -681,6 +681,13 @@ DevmemInvalidateFBSCTable(DEVMEM_CONTEXT *psContext,
 IMG_UINT32
 DevmemGetHeapLog2PageSize(DEVMEM_HEAP *psHeap);
 
+/* DevmemGetMemFlags()
+ *
+ * Get the memalloc flags for a certain memdesc.
+ */
+PVRSRV_MEMALLOCFLAGS_T
+DevmemGetMemAllocFlags(DEVMEM_MEMDESC *psMemDesc);
+
 /* DevmemGetHeapReservedSize()
  *
  * Get the reserved size used for a certain heap.
@@ -706,19 +713,6 @@ RegisterDevmemPFNotify(DEVMEM_CONTEXT *psContext,
                        IMG_BOOL       bRegister);
 
 /*************************************************************************/ /*!
-@Function       GetMaxDevMemSize
-@Description    Get the amount of device memory on current platform
-                (memory size in Bytes)
-@Output         puiLMASize            LMA memory size
-@Output         puiUMASize            UMA memory size
-@Return         Error code
-*/ /**************************************************************************/
-IMG_INTERNAL PVRSRV_ERROR
-GetMaxDevMemSize(SHARED_DEV_CONNECTION hDevConnection,
-                IMG_DEVMEM_SIZE_T *puiLMASize,
-                IMG_DEVMEM_SIZE_T *puiUMASize);
-
-/*************************************************************************/ /*!
 @Function       DevmemHeapSetPremapStatus
 @Description    In some special cases like virtualisation, a device memory heap
                            must be entirely backed by physical memory and mapped into the
index 621ca51..3dcef24 100644 (file)
@@ -54,6 +54,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "osfunc.h"
 #include "lock.h"
 #include "osmmap.h"
+#include "pvrsrv_memallocflags_internal.h"
 
 #define DEVMEM_HEAPNAME_MAXLENGTH 160
 
@@ -288,6 +289,10 @@ struct DEVMEM_MEMDESC_TAG
 
        IMG_UINT32 ui32AllocationIndex;
 
+#if defined(DEBUG)
+       IMG_BOOL bPoisonOnFree;
+#endif
+
 #if defined(PVRSRV_ENABLE_GPU_MEMORY_INFO)
        IMG_HANDLE hRIHandle;                   /*!< Handle to RI information */
 #endif
@@ -444,7 +449,7 @@ IMG_BOOL DevmemImportStructRelease(DEVMEM_IMPORT *psImport);
 
 /******************************************************************************
 @Function       DevmemImportDiscard
-@Description    Discard a created, but unitilised import structure.
+@Description    Discard a created, but uninitialised import structure.
                 This must only be called before DevmemImportStructInit
                 after which DevmemImportStructRelease must be used to
                 "free" the import structure.
@@ -459,6 +464,16 @@ void DevmemImportDiscard(DEVMEM_IMPORT *psImport);
 ******************************************************************************/
 PVRSRV_ERROR DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc);
 
+#if defined(DEBUG)
+/******************************************************************************
+@Function       DevmemMemDescSetPoF
+@Description    Sets the Poison on Free flag to true for this MemDesc if the
+                given MemAllocFlags have the Poison on Free bit set.
+                Poison on Free is a debug only feature.
+******************************************************************************/
+void DevmemMemDescSetPoF(DEVMEM_MEMDESC *psMemDesc, PVRSRV_MEMALLOCFLAGS_T uiFlags);
+#endif
+
 /******************************************************************************
 @Function       DevmemMemDescInit
 @Description    Sets the given offset and import struct fields in the MemDesc.
@@ -519,4 +534,72 @@ static INLINE DEVMEM_PROPERTIES_T GetImportProperties(DEVMEM_IMPORT *psImport)
        return uiProperties;
 }
 
+/******************************************************************************
+@Function       DevmemCPUMemSet
+@Description    Given a CPU Mapped Devmem address, set the memory at that
+                range (address, address + size) to the uiPattern provided.
+                Flags determine the OS abstracted MemSet method to use.
+******************************************************************************/
+static INLINE void DevmemCPUMemSet(void *pvMem,
+                                   IMG_UINT8 uiPattern,
+                                   IMG_DEVMEM_SIZE_T uiSize,
+                                   PVRSRV_MEMALLOCFLAGS_T uiFlags)
+{
+       if (PVRSRV_CHECK_CPU_UNCACHED(uiFlags))
+       {
+               OSDeviceMemSet(pvMem, uiPattern, uiSize);
+       }
+       else
+       {
+               /* it's safe to use OSCachedMemSet() for cached and wc memory */
+               OSCachedMemSet(pvMem, uiPattern, uiSize);
+       }
+}
+
+/******************************************************************************
+@Function       DevmemCPUMapCheckImportProperties
+@Description    Given a MemDesc check that the import properties are correct
+                to allow for mapping the MemDesc to the CPU.
+                Returns PVRSRV_OK on success.
+******************************************************************************/
+static INLINE PVRSRV_ERROR DevmemCPUMapCheckImportProperties(DEVMEM_MEMDESC *psMemDesc)
+{
+       DEVMEM_PROPERTIES_T uiProperties = GetImportProperties(psMemDesc->psImport);
+
+       if (uiProperties &
+                       (DEVMEM_PROPERTIES_UNPINNED | DEVMEM_PROPERTIES_SECURE))
+       {
+#if defined(SUPPORT_SECURITY_VALIDATION)
+               if (uiProperties & DEVMEM_PROPERTIES_SECURE)
+               {
+                       PVR_DPF((PVR_DBG_WARNING,
+                                       "%s: Allocation is a secure buffer. "
+                                       "It should not be possible to map to CPU, but for security "
+                                       "validation this will be allowed for testing purposes, "
+                                       "as long as the buffer is pinned.",
+                                       __func__));
+               }
+
+               if (uiProperties & DEVMEM_PROPERTIES_UNPINNED)
+#endif
+               {
+                       PVR_DPF((PVR_DBG_ERROR,
+                                       "%s: Allocation is currently unpinned or a secure buffer. "
+                                       "Not possible to map to CPU!",
+                                       __func__));
+                       return PVRSRV_ERROR_INVALID_MAP_REQUEST;
+               }
+       }
+
+       if (uiProperties & DEVMEM_PROPERTIES_NO_CPU_MAPPING)
+       {
+               PVR_DPF((PVR_DBG_ERROR,
+                               "%s: CPU Mapping is not possible on this allocation!",
+                               __func__));
+               return PVRSRV_ERROR_INVALID_MAP_REQUEST;
+       }
+
+       return PVRSRV_OK;
+}
+
 #endif /* DEVICEMEM_UTILS_H */
index 0f965cc..3ef7821 100644 (file)
@@ -64,12 +64,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        *(phLock) = OSAllocMem(sizeof(struct mutex)); \
        if (*(phLock)) { mutex_init(*(phLock)); e = PVRSRV_OK; }; \
        e;})
-#define OSLockDestroy(hLock) ({mutex_destroy((hLock)); OSFreeMem((hLock)); PVRSRV_OK;})
-#define OSLockDestroyNoStats(hLock) ({mutex_destroy((hLock)); OSFreeMemNoStats((hLock)); PVRSRV_OK;})
+#define OSLockDestroy(hLock) ({mutex_destroy((hLock)); OSFreeMem((hLock));})
+#define OSLockDestroyNoStats(hLock) ({mutex_destroy((hLock)); OSFreeMemNoStats((hLock));})
 
-#define OSLockAcquire(hLock) ({mutex_lock((hLock)); PVRSRV_OK;})
-#define OSLockAcquireNested(hLock, subclass) ({mutex_lock_nested((hLock), (subclass)); PVRSRV_OK;})
-#define OSLockRelease(hLock) ({mutex_unlock((hLock)); PVRSRV_OK;})
+#define OSLockAcquire(hLock) ({mutex_lock((hLock));})
+#define OSLockAcquireNested(hLock, subclass) ({mutex_lock_nested((hLock), (subclass));})
+#define OSLockRelease(hLock) ({mutex_unlock((hLock));})
 
 #define OSLockIsLocked(hLock) ((mutex_is_locked((hLock)) == 1) ? IMG_TRUE : IMG_FALSE)
 #define OSTryLockAcquire(hLock) ((mutex_trylock(hLock) == 1) ? IMG_TRUE : IMG_FALSE)
@@ -114,10 +114,10 @@ static inline IMG_INT OSAtomicOr(ATOMIC_T *pCounter, IMG_INT iVal)
 }
 
 #define OSAtomicAdd(pCounter, incr) atomic_add_return(incr,pCounter)
-#define OSAtomicAddUnless(pCounter, incr, test) __atomic_add_unless(pCounter,incr,test)
+#define OSAtomicAddUnless(pCounter, incr, test) atomic_add_unless(pCounter, (incr), (test))
 
 #define OSAtomicSubtract(pCounter, incr) atomic_add_return(-(incr),pCounter)
-#define OSAtomicSubtractUnless(pCounter, incr, test) OSAtomicAddUnless(pCounter, -(incr), test)
+#define OSAtomicSubtractUnless(pCounter, incr, test) OSAtomicAddUnless(pCounter, -(incr), (test))
 
 #else /* defined(__linux__) && defined(__KERNEL__) */
 
@@ -147,7 +147,7 @@ PVRSRV_ERROR OSLockCreate(POS_LOCK *phLock);
 @Return         None.
  */ /**************************************************************************/
 IMG_INTERNAL
-PVRSRV_ERROR OSLockDestroy(POS_LOCK hLock);
+void OSLockDestroy(POS_LOCK hLock);
 
 #if defined(INTEGRITY_OS)
 #define OSLockDestroyNoStats OSLockDestroy
@@ -412,11 +412,17 @@ IMG_INT32 OSAtomicOr(ATOMIC_T *pCounter, IMG_INT32 iVal);
 
 /* For now, spin-locks are required on Linux only, so other platforms fake
  * spinlocks with normal mutex locks */
+/*! Type definitions for OS_SPINLOCK accessor and creation / deletion */
 typedef unsigned long OS_SPINLOCK_FLAGS;
+/*! Pointer to an OS Spinlock */
 #define POS_SPINLOCK POS_LOCK
+/*! Wrapper for OSLockCreate() */
 #define OSSpinLockCreate(ppLock) OSLockCreate(ppLock)
+/*! Wrapper for OSLockDestroy() */
 #define OSSpinLockDestroy(pLock) OSLockDestroy(pLock)
+/*! Wrapper for OSLockAcquire() */
 #define OSSpinLockAcquire(pLock, flags) {flags = 0; OSLockAcquire(pLock);}
+/*! Wrapper for OSLockRelease() */
 #define OSSpinLockRelease(pLock, flags) {flags = 0; OSLockRelease(pLock);}
 
 #endif /* defined(__linux__) */
index 1b566e0..40a509d 100644 (file)
@@ -74,7 +74,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
                                      be done (read-only, etc). These may not
                                      be honoured if the PMR does not permit
                                      them.
-@Input          uiPMRLength          The size of the PMR.
 @Output         phOSMMapPrivDataOut  Returned private data.
 @Output         ppvMappingAddressOut The returned mapping.
 @Output         puiMappingLengthOut  The size of the returned mapping.
index c830b70..d306af7 100644 (file)
@@ -53,6 +53,25 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 typedef struct _RA_ARENA_ RA_ARENA;                    //PRQA S 3313
 
+/** Resource arena's iterator.
+ *  struct _RA_ARENA_ITERATOR_ deliberately opaque
+ */
+typedef struct _RA_ARENA_ITERATOR_ RA_ARENA_ITERATOR;
+
+typedef struct _RA_ITERATOR_DATA_ {
+       IMG_UINT64 uiAddr;
+       IMG_UINT64 uiSize;
+       IMG_BOOL bFree;
+} RA_ITERATOR_DATA;
+
+/** Resource arena usage statistics.
+ *  struct _RA_USAGE_STATS
+ */
+typedef struct _RA_USAGE_STATS {
+       IMG_UINT64      ui64TotalArenaSize;
+       IMG_UINT64      ui64FreeArenaSize;
+}RA_USAGE_STATS, *PRA_USAGE_STATS;
+
 /*
  * Per-Arena handle - this is private data for the caller of the RA.
  * The RA knows nothing about this data. It is given it in RA_Create, and
@@ -85,8 +104,8 @@ typedef IMG_UINT64 RA_LENGTH_T;
  * */
 
 /* --- Resource allocation policy definitions ---
-* | 31.........4|......3....|........2.............|1..................0|
-* | Reserved    | No split  | Area bucket selection| Free node selection|
+* | 31.........4|......3....|........2.............|1...................0|
+* | Reserved    | No split  | Area bucket selection| Alloc node selection|
 */
 
 /*
@@ -103,7 +122,7 @@ typedef IMG_UINT64 RA_LENGTH_T;
  * As a result any future higher size allocation requests are likely to succeed
  */
 #define RA_POLICY_ALLOC_OPTIMAL                (1U)
-#define RA_POLICY_ALLOC_OPTIMAL_MASK                   (3U)
+#define RA_POLICY_ALLOC_NODE_SELECT_MASK                       (3U)
 
 /*
  * Bucket selection policies
@@ -324,4 +343,44 @@ RA_Alloc_Range(RA_ARENA *pArena,
 void
 RA_Free(RA_ARENA *pArena, RA_BASE_T base);
 
+/**
+ *  @Function   RA_Get_Usage_Stats
+ *
+ *  @Description    To collect the arena usage statistics.
+ *
+ *  @Input  pArena - the arena to acquire usage statistics from.
+ *  @Input  psRAStats - the buffer to hold the usage statistics of the arena.
+ *
+ *  @Return None
+ */
+IMG_INTERNAL void
+RA_Get_Usage_Stats(RA_ARENA *pArena, PRA_USAGE_STATS psRAStats);
+
+IMG_INTERNAL RA_ARENA_ITERATOR *
+RA_IteratorAcquire(RA_ARENA *pArena, IMG_BOOL bIncludeFreeSegments);
+
+IMG_INTERNAL void
+RA_IteratorReset(RA_ARENA_ITERATOR *pIter);
+
+IMG_INTERNAL void
+RA_IteratorRelease(RA_ARENA_ITERATOR *pIter);
+
+IMG_INTERNAL IMG_BOOL
+RA_IteratorNext(RA_ARENA_ITERATOR *pIter, RA_ITERATOR_DATA *pData);
+
+/*************************************************************************/ /*!
+@Function       RA_BlockDump
+@Description    Debug dump of all memory allocations within the RA and the space
+                between. A '#' represents a block of memory (the arena's quantum
+                in size) that has been allocated whereas a '.' represents a free
+                block.
+@Input          pArena        The arena to dump.
+@Input          pfnLogDump    The dumping method.
+@Input          pPrivData     Data to be passed into the pfnLogDump method.
+*/ /**************************************************************************/
+IMG_INTERNAL PVRSRV_ERROR
+RA_BlockDump(RA_ARENA *pArena,
+             __printf(2, 3) void (*pfnLogDump)(void*, IMG_CHAR*, ...),
+             void *pPrivData);
+
 #endif
index 3bbb15b..f126915 100644 (file)
@@ -115,30 +115,6 @@ SyncPrimAlloc(PSYNC_PRIM_CONTEXT      hSyncPrimContext,
               PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
               const IMG_CHAR          *pszClassName);
 
-#if defined(__KERNEL__)
-/*************************************************************************/ /*!
-@Function       SyncPrimAllocForServerSync
-
-@Description    Allocate a new synchronisation primitive on the specified
-                synchronisation context for a server sync
-
-@Input          hSyncPrimContext        Handle to the synchronisation
-                                        primitive context
-
-@Output         ppsSync                 Created synchronisation primitive
-
-@Input          pszClassName            Sync source annotation
-
-@Return         PVRSRV_OK if the synchronisation primitive was
-                successfully created
-*/
-/*****************************************************************************/
-PVRSRV_ERROR
-SyncPrimAllocForServerSync(PSYNC_PRIM_CONTEXT      hSyncPrimContext,
-                           PVRSRV_CLIENT_SYNC_PRIM **ppsSync,
-                           const IMG_CHAR          *pszClassName);
-#endif
-
 /*************************************************************************/ /*!
 @Function       SyncPrimFree
 
index 87dd096..29c8360 100644 (file)
@@ -66,7 +66,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        Private structure's
 */
 #define SYNC_PRIM_NAME_SIZE            50
-typedef struct SYNC_PRIM_CONTEXT
+typedef struct SYNC_PRIM_CONTEXT_TAG
 {
        SHARED_DEV_CONNECTION       hDevConnection;
        IMG_CHAR                                        azName[SYNC_PRIM_NAME_SIZE];    /*!< Name of the RA */
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/common/env/linux/interrupt_support.c b/drivers/gpu/drm/img/img-rogue/services/system/common/env/linux/interrupt_support.c
new file mode 100644 (file)
index 0000000..c67d453
--- /dev/null
@@ -0,0 +1,151 @@
+/*************************************************************************/ /*!
+@File
+@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.
+*/ /**************************************************************************/
+
+#include <linux/interrupt.h>
+
+#include "pvr_debug.h"
+#include "allocmem.h"
+#include "interrupt_support.h"
+
+typedef struct LISR_DATA_TAG
+{
+       IMG_UINT32      ui32IRQ;
+       PFN_SYS_LISR    pfnLISR;
+       void            *pvData;
+} LISR_DATA;
+
+static irqreturn_t SystemISRWrapper(int irq, void *dev_id)
+{
+       LISR_DATA *psLISRData = (LISR_DATA *)dev_id;
+
+       PVR_UNREFERENCED_PARAMETER(irq);
+
+       if (psLISRData)
+       {
+               if (psLISRData->pfnLISR(psLISRData->pvData))
+               {
+                       return IRQ_HANDLED;
+               }
+       }
+       else
+       {
+               PVR_DPF((PVR_DBG_ERROR, "%s: Missing interrupt data", __func__));
+       }
+
+       return IRQ_NONE;
+}
+
+PVRSRV_ERROR OSInstallSystemLISR(IMG_HANDLE *phLISR,
+                                IMG_UINT32 ui32IRQ,
+                                const IMG_CHAR *pszDevName,
+                                PFN_SYS_LISR pfnLISR,
+                                void *pvData,
+                                IMG_UINT32 ui32Flags)
+{
+       LISR_DATA *psLISRData;
+       unsigned long ulIRQFlags = 0;
+
+       if (pfnLISR == NULL || pvData == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32Flags & ~SYS_IRQ_FLAG_MASK)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       switch (ui32Flags & SYS_IRQ_FLAG_TRIGGER_MASK)
+       {
+               case SYS_IRQ_FLAG_TRIGGER_DEFAULT:
+                       break;
+               case SYS_IRQ_FLAG_TRIGGER_LOW:
+                       ulIRQFlags |= IRQF_TRIGGER_LOW;
+                       break;
+               case SYS_IRQ_FLAG_TRIGGER_HIGH:
+                       ulIRQFlags |= IRQF_TRIGGER_HIGH;
+                       break;
+               default:
+                       return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       if (ui32Flags & SYS_IRQ_FLAG_SHARED)
+       {
+               ulIRQFlags |= IRQF_SHARED;
+       }
+
+       psLISRData = OSAllocMem(sizeof(*psLISRData));
+       if (psLISRData == NULL)
+       {
+               return PVRSRV_ERROR_OUT_OF_MEMORY;
+       }
+
+       psLISRData->ui32IRQ = ui32IRQ;
+       psLISRData->pfnLISR = pfnLISR;
+       psLISRData->pvData = pvData;
+
+       if (request_irq(ui32IRQ, SystemISRWrapper, ulIRQFlags, pszDevName, psLISRData))
+       {
+               OSFreeMem(psLISRData);
+
+               return PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER;
+       }
+
+       *phLISR = (IMG_HANDLE)psLISRData;
+
+       return PVRSRV_OK;
+}
+
+PVRSRV_ERROR OSUninstallSystemLISR(IMG_HANDLE hLISR)
+{
+       LISR_DATA *psLISRData = (LISR_DATA *)hLISR;
+
+       if (psLISRData == NULL)
+       {
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+
+       free_irq(psLISRData->ui32IRQ, psLISRData);
+
+       OSFreeMem(psLISRData);
+
+       return PVRSRV_OK;
+}
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/Kbuild.mk b/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/Kbuild.mk
deleted file mode 100755 (executable)
index 712a7e6..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-########################################################################### ###
-#@File
-#@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.
-### ###########################################################################
-
-PVRSRVKM_NAME = $(PVRSRV_MODNAME)
-
-ifeq ($(KERNEL_DRIVER_DIR),)
- SYSTEM_BASEDIR := services/system/rogue/$(PVR_SYSTEM)
-else
- SYSTEM_BASEDIR := external/$(KERNEL_DRIVER_DIR)/$(PVR_SYSTEM)
-endif
-
-$(PVRSRVKM_NAME)-y += \
- $(SYSTEM_BASEDIR)/mt8173_mfgsys.o \
- $(SYSTEM_BASEDIR)/mt8173_sysconfig.o \
- services/system/rogue/common/env/linux/dma_support.o \
- services/server/common/vmm_pvz_client.o \
- services/server/common/vmm_pvz_server.o \
- services/server/common/vz_vmm_pvz.o \
- services/server/common/vz_vmm_vm.o \
- services/system/rogue/common/vmm_type_$(VMM_TYPE).o
-
-ifeq ($(SUPPORT_ION),1)
- $(PVRSRVKM_NAME)-y += \
-  services/system/rogue/common/env/linux/ion_support_generic.o
-endif
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.c b/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.c
deleted file mode 100644 (file)
index 5080acc..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
-* Copyright (c) 2014 MediaTek Inc.
-* Author: Chiawen Lee <chiawen.lee@mediatek.com>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*/
-
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/pm_runtime.h>
-#include <linux/regulator/consumer.h>
-#include <linux/thermal.h>
-
-#include "mt8173_mfgsys.h"
-
-static const char * const top_mfg_clk_name[] = {
-       "mfg_mem_in_sel",
-       "mfg_axi_in_sel",
-       "top_axi",
-       "top_mem",
-};
-
-#define MAX_TOP_MFG_CLK ARRAY_SIZE(top_mfg_clk_name)
-
-#define REG_MFG_AXI BIT(0)
-#define REG_MFG_MEM BIT(1)
-#define REG_MFG_G3D BIT(2)
-#define REG_MFG_26M BIT(3)
-#define REG_MFG_ALL (REG_MFG_AXI | REG_MFG_MEM | REG_MFG_G3D | REG_MFG_26M)
-
-#define REG_MFG_CG_STA 0x00
-#define REG_MFG_CG_SET 0x04
-#define REG_MFG_CG_CLR 0x08
-
-static void mtk_mfg_clr_clock_gating(void __iomem *reg)
-{
-       writel(REG_MFG_ALL, reg + REG_MFG_CG_CLR);
-}
-
-static int mtk_mfg_prepare_clock(struct mtk_mfg *mfg)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < MAX_TOP_MFG_CLK; i++) {
-               ret = clk_prepare(mfg->top_clk[i]);
-               if (ret)
-                       goto unwind;
-       }
-       ret = clk_prepare(mfg->top_mfg);
-       if (ret)
-               goto unwind;
-
-       return 0;
-unwind:
-       while (i--)
-               clk_unprepare(mfg->top_clk[i]);
-
-       return ret;
-}
-
-static void mtk_mfg_unprepare_clock(struct mtk_mfg *mfg)
-{
-       int i;
-
-       clk_unprepare(mfg->top_mfg);
-       for (i = MAX_TOP_MFG_CLK - 1; i >= 0; i--)
-               clk_unprepare(mfg->top_clk[i]);
-}
-
-static int mtk_mfg_enable_clock(struct mtk_mfg *mfg)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < MAX_TOP_MFG_CLK; i++) {
-               ret = clk_enable(mfg->top_clk[i]);
-               if (ret)
-                       goto unwind;
-       }
-       ret = clk_enable(mfg->top_mfg);
-       if (ret)
-               goto unwind;
-       mtk_mfg_clr_clock_gating(mfg->reg_base);
-
-       return 0;
-unwind:
-       while (i--)
-               clk_disable(mfg->top_clk[i]);
-
-       return ret;
-}
-
-static void mtk_mfg_disable_clock(struct mtk_mfg *mfg)
-{
-       int i;
-
-       clk_disable(mfg->top_mfg);
-       for (i = MAX_TOP_MFG_CLK - 1; i >= 0; i--)
-               clk_disable(mfg->top_clk[i]);
-}
-
-static void mtk_mfg_enable_hw_apm(struct mtk_mfg *mfg)
-{
-       writel(0x003c3d4d, mfg->reg_base + 0x24);
-       writel(0x4d45440b, mfg->reg_base + 0x28);
-       writel(0x7a710184, mfg->reg_base + 0xe0);
-       writel(0x835f6856, mfg->reg_base + 0xe4);
-       writel(0x002b0234, mfg->reg_base + 0xe8);
-       writel(0x80000000, mfg->reg_base + 0xec);
-       writel(0x08000000, mfg->reg_base + 0xa0);
-}
-
-int mtk_mfg_enable(struct mtk_mfg *mfg)
-{
-       int ret;
-
-       ret = pm_runtime_get_sync(mfg->dev);
-       if (ret)
-               return ret;
-
-       ret = mtk_mfg_enable_clock(mfg);
-       if (ret)
-               goto err_pm_runtime_put;
-
-       mtk_mfg_enable_hw_apm(mfg);
-
-       return 0;
-
-err_pm_runtime_put:
-       pm_runtime_put_sync(mfg->dev);
-       return ret;
-}
-
-static void mtk_mfg_disable_hw_apm(struct mtk_mfg *mfg)
-{
-       writel(0x00, mfg->reg_base + 0xec);
-}
-
-void mtk_mfg_disable(struct mtk_mfg *mfg)
-{
-       mtk_mfg_disable_hw_apm(mfg);
-
-       mtk_mfg_disable_clock(mfg);
-       pm_runtime_put_sync(mfg->dev);
-}
-
-int mtk_mfg_freq_set(struct mtk_mfg *mfg, unsigned long freq)
-{
-       int ret;
-
-       ret = clk_prepare_enable(mfg->top_mfg);
-       if (ret) {
-               dev_err(mfg->dev, "enable and prepare top_mfg failed, %d\n", ret);
-               return ret;
-       }
-
-       ret = clk_set_parent(mfg->top_mfg, mfg->clk26m);
-       if (ret) {
-               dev_err(mfg->dev, "Set clk parent to clk26m failed, %d\n", ret);
-               goto unprepare_top_mfg;
-       }
-
-       ret = clk_set_rate(mfg->mmpll, freq);
-       if (ret)
-               dev_err(mfg->dev, "Set freq to %lu Hz failed, %d\n", freq, ret);
-
-       ret = clk_set_parent(mfg->top_mfg, mfg->top_mmpll);
-       if (ret)
-               dev_err(mfg->dev, "Set clk parent to top_mmpll failed, %d\n", ret);
-
-unprepare_top_mfg:
-       clk_disable_unprepare(mfg->top_mfg);
-
-       if (!ret)
-               dev_dbg(mfg->dev, "Freq set to %lu Hz\n", freq);
-
-       return ret;
-}
-
-int mtk_mfg_volt_set(struct mtk_mfg *mfg, int volt)
-{
-       int ret;
-
-       ret = regulator_set_voltage(mfg->vgpu, volt, volt);
-       if (ret != 0) {
-               dev_err(mfg->dev, "Set voltage to %u uV failed, %d\n",
-                       volt, ret);
-               return ret;
-       }
-
-       dev_dbg(mfg->dev, "Voltage set to %d uV\n", volt);
-
-       return 0;
-}
-
-static int mtk_mfg_bind_device_resource(struct mtk_mfg *mfg)
-{
-       struct device *dev = mfg->dev;
-       struct platform_device *pdev = to_platform_device(dev);
-       int i;
-       struct resource *res;
-
-       mfg->top_clk = devm_kcalloc(dev, MAX_TOP_MFG_CLK,
-                                   sizeof(*mfg->top_clk), GFP_KERNEL);
-       if (!mfg->top_clk)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-       mfg->rgx_start = res->start;
-       mfg->rgx_size = resource_size(res);
-
-       mfg->rgx_irq = platform_get_irq_byname(pdev, "RGX");
-       if (mfg->rgx_irq < 0)
-               return mfg->rgx_irq;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       mfg->reg_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(mfg->reg_base))
-               return PTR_ERR(mfg->reg_base);
-
-       mfg->mmpll = devm_clk_get(dev, "mmpll_clk");
-       if (IS_ERR(mfg->mmpll)) {
-               dev_err(dev, "devm_clk_get mmpll_clk failed !!!\n");
-               return PTR_ERR(mfg->mmpll);
-       }
-
-       for (i = 0; i < MAX_TOP_MFG_CLK; i++) {
-               mfg->top_clk[i] = devm_clk_get(dev, top_mfg_clk_name[i]);
-               if (IS_ERR(mfg->top_clk[i])) {
-                       dev_err(dev, "devm_clk_get %s failed !!!\n",
-                               top_mfg_clk_name[i]);
-                       return PTR_ERR(mfg->top_clk[i]);
-               }
-       }
-
-       mfg->top_mfg = devm_clk_get(dev, "top_mfg");
-       if (IS_ERR(mfg->top_mfg)) {
-               dev_err(dev, "devm_clk_get top_mfg failed !!!\n");
-               return PTR_ERR(mfg->top_mfg);
-       }
-
-       mfg->top_mmpll = devm_clk_get(dev, "top_mmpll");
-       if (IS_ERR(mfg->top_mmpll)) {
-               dev_err(dev, "devm_clk_get top_mmpll failed !!!\n");
-               return PTR_ERR(mfg->top_mmpll);
-       }
-
-       mfg->clk26m = devm_clk_get(dev, "clk26m");
-       if (IS_ERR(mfg->clk26m)) {
-               dev_err(dev, "devm_clk_get clk26m failed !!!\n");
-               return PTR_ERR(mfg->clk26m);
-       }
-
-#if defined(CONFIG_DEVFREQ_THERMAL)
-       mfg->tz = thermal_zone_get_zone_by_name("cpu_thermal");
-       if (IS_ERR(mfg->tz)) {
-               dev_warn(dev, "Failed to get cpu_thermal zone\n");
-       }
-#endif
-
-       mfg->vgpu = devm_regulator_get(dev, "mfgsys-power");
-       if (IS_ERR(mfg->vgpu))
-               return PTR_ERR(mfg->vgpu);
-
-       pm_runtime_enable(dev);
-
-       return 0;
-}
-
-static void mtk_mfg_unbind_device_resource(struct mtk_mfg *mfg)
-{
-       struct device *dev = mfg->dev;
-
-       pm_runtime_disable(dev);
-}
-
-struct mtk_mfg *mtk_mfg_create(struct device *dev)
-{
-       int err;
-       struct mtk_mfg *mfg;
-
-       mtk_mfg_debug("mtk_mfg_create Begin\n");
-
-       mfg = devm_kzalloc(dev, sizeof(*mfg), GFP_KERNEL);
-       if (!mfg)
-               return ERR_PTR(-ENOMEM);
-       mfg->dev = dev;
-
-       err = mtk_mfg_bind_device_resource(mfg);
-       if (err != 0)
-               return ERR_PTR(err);
-
-       mutex_init(&mfg->set_power_state);
-
-       err = mtk_mfg_prepare_clock(mfg);
-       if (err)
-               goto err_unbind_resource;
-
-       mtk_mfg_debug("mtk_mfg_create End\n");
-
-       return mfg;
-err_unbind_resource:
-       mtk_mfg_unbind_device_resource(mfg);
-
-       return ERR_PTR(err);
-}
-
-void mtk_mfg_destroy(struct mtk_mfg *mfg)
-{
-       mtk_mfg_unprepare_clock(mfg);
-
-       mtk_mfg_unbind_device_resource(mfg);
-}
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.h b/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_mfgsys.h
deleted file mode 100644 (file)
index 3c1e9ca..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-* Copyright (c) 2014 MediaTek Inc.
-* Author: Chiawen Lee <chiawen.lee@mediatek.com>
-*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License version 2 as
-* published by the Free Software Foundation.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*/
-
-#ifndef MT8173_MFGSYS_H
-#define MT8173_MFGSYS_H
-
-#include <linux/device.h>
-
-/* unit ms, timeout interval for DVFS detection */
-#define MTK_DVFS_SWITCH_INTERVAL  300
-
-#define ENABLE_MTK_MFG_DEBUG 0
-
-#if ENABLE_MTK_MFG_DEBUG
-#define mtk_mfg_debug(fmt, args...) pr_info("[MFG]" fmt, ##args)
-#else
-#define mtk_mfg_debug(fmt, args...) do { } while (0)
-#endif
-
-struct mtk_mfg {
-       struct device *dev;
-
-       struct clk **top_clk;
-       void __iomem *reg_base;
-
-       resource_size_t rgx_start;
-       resource_size_t rgx_size;
-       int rgx_irq;
-
-       /* mutex protect for set power state */
-       struct mutex set_power_state;
-
-       /* for gpu device freq/volt update */
-       struct regulator *vgpu;
-       struct clk *mmpll;
-       struct clk *top_mfg;
-       struct clk *top_mmpll;
-       struct clk *clk26m;
-
-#if (defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))) || \
-       (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
-       struct thermal_zone_device *tz;
-#endif
-};
-
-struct mtk_mfg *mtk_mfg_create(struct device *dev);
-void mtk_mfg_destroy(struct mtk_mfg *mfg);
-
-int mtk_mfg_enable(struct mtk_mfg *mfg);
-void mtk_mfg_disable(struct mtk_mfg *mfg);
-
-int mtk_mfg_freq_set(struct mtk_mfg *mfg, unsigned long freq);
-int mtk_mfg_volt_set(struct mtk_mfg *mfg, int volt);
-
-#endif /* MT8173_MFGSYS_H*/
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_sysconfig.c b/drivers/gpu/drm/img/img-rogue/services/system/rogue/mt8173/mt8173_sysconfig.c
deleted file mode 100644 (file)
index 7efae1e..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          System Configuration
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    System Configuration functions
-@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.
-*/ /**************************************************************************/
-
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/pm_opp.h>
-#include <linux/thermal.h>
-#if defined(CONFIG_DEVFREQ_THERMAL)
-#include <linux/devfreq_cooling.h>
-#endif
-
-#include "physheap.h"
-#include "pvrsrv_device.h"
-#include "rgxdevice.h"
-#include "syscommon.h"
-#if defined(SUPPORT_ION)
-#include "ion_support.h"
-#endif
-
-#include "mt8173_mfgsys.h"
-
-#define SYS_RGX_ACTIVE_POWER_LATENCY_MS 10
-#define RGX_HW_CORE_CLOCK_SPEED 395000000
-
-/* Setup RGX specific timing data */
-static RGX_TIMING_INFORMATION gsRGXTimingInfo = {
-       .ui32CoreClockSpeed = RGX_HW_CORE_CLOCK_SPEED,
-       .bEnableActivePM = IMG_TRUE,
-       .ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS,
-       .bEnableRDPowIsland = IMG_TRUE,
-};
-
-static RGX_DATA gsRGXData = {
-       .psRGXTimingInfo = &gsRGXTimingInfo,
-};
-
-static PVRSRV_DEVICE_CONFIG    gsDevice;
-
-typedef struct
-{
-       IMG_UINT32 ui32IRQ;
-       PFN_LISR pfnLISR;
-       void *pvLISRData;
-} LISR_WRAPPER_DATA;
-
-static irqreturn_t MTKLISRWrapper(int iIrq, void *pvData)
-{
-       LISR_WRAPPER_DATA *psWrapperData = pvData;
-
-       if (psWrapperData->pfnLISR(psWrapperData->pvLISRData))
-       {
-               return IRQ_HANDLED;
-       }
-
-       return IRQ_NONE;
-}
-
-/*
- * CPU to Device physical address translation
- */
-static
-void UMAPhysHeapCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                  IMG_UINT32 ui32NumOfAddr,
-                                  IMG_DEV_PHYADDR *psDevPAddr,
-                                  IMG_CPU_PHYADDR *psCpuPAddr)
-{
-       PVR_UNREFERENCED_PARAMETER(hPrivData);
-
-       /* Optimise common case */
-       psDevPAddr[0].uiAddr = psCpuPAddr[0].uiAddr;
-       if (ui32NumOfAddr > 1) {
-               IMG_UINT32 ui32Idx;
-               for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
-                       psDevPAddr[ui32Idx].uiAddr = psCpuPAddr[ui32Idx].uiAddr;
-       }
-}
-
-/*
- * Device to CPU physical address translation
- */
-static
-void UMAPhysHeapDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                  IMG_UINT32 ui32NumOfAddr,
-                                  IMG_CPU_PHYADDR *psCpuPAddr,
-                                  IMG_DEV_PHYADDR *psDevPAddr)
-{
-       PVR_UNREFERENCED_PARAMETER(hPrivData);
-
-       /* Optimise common case */
-       psCpuPAddr[0].uiAddr = psDevPAddr[0].uiAddr;
-       if (ui32NumOfAddr > 1) {
-               IMG_UINT32 ui32Idx;
-               for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
-                       psCpuPAddr[ui32Idx].uiAddr = psDevPAddr[ui32Idx].uiAddr;
-       }
-}
-
-static PHYS_HEAP_FUNCTIONS gsPhysHeapFuncs = {
-       .pfnCpuPAddrToDevPAddr = UMAPhysHeapCpuPAddrToDevPAddr,
-       .pfnDevPAddrToCpuPAddr = UMAPhysHeapDevPAddrToCpuPAddr,
-};
-
-static PHYS_HEAP_CONFIG gsPhysHeapConfig = {
-       .pszPDumpMemspaceName = "SYSMEM",
-       .eType = PHYS_HEAP_TYPE_UMA,
-       .psMemFuncs = &gsPhysHeapFuncs,
-       .hPrivData = NULL,
-       .ui32UsageFlags = PHYS_HEAP_USAGE_GPU_LOCAL,
-};
-
-static PVRSRV_ERROR MTKSysDevPrePowerState(
-               IMG_HANDLE hSysData,
-               PVRSRV_SYS_POWER_STATE eNewPowerState,
-               PVRSRV_SYS_POWER_STATE eCurrentPowerState,
-               IMG_BOOL bForced)
-{
-       struct mtk_mfg *mfg = hSysData;
-
-       mtk_mfg_debug("MTKSysDevPrePowerState (%d->%d), bForced = %d\n",
-                     eCurrentPowerState, eNewPowerState, bForced);
-
-       mutex_lock(&mfg->set_power_state);
-
-       if ((PVRSRV_SYS_POWER_STATE_OFF == eNewPowerState) &&
-           (PVRSRV_SYS_POWER_STATE_ON == eCurrentPowerState))
-               mtk_mfg_disable(mfg);
-
-       mutex_unlock(&mfg->set_power_state);
-       return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR MTKSysDevPostPowerState(
-               IMG_HANDLE hSysData,
-               PVRSRV_SYS_POWER_STATE eNewPowerState,
-               PVRSRV_SYS_POWER_STATE eCurrentPowerState,
-               IMG_BOOL bForced)
-{
-       struct mtk_mfg *mfg = hSysData;
-       PVRSRV_ERROR ret;
-
-       mtk_mfg_debug("MTKSysDevPostPowerState (%d->%d)\n",
-                     eCurrentPowerState, eNewPowerState);
-
-       mutex_lock(&mfg->set_power_state);
-
-       if ((PVRSRV_SYS_POWER_STATE_ON == eNewPowerState) &&
-           (PVRSRV_SYS_POWER_STATE_OFF == eCurrentPowerState)) {
-               if (mtk_mfg_enable(mfg)) {
-                       ret = PVRSRV_ERROR_DEVICE_POWER_CHANGE_FAILURE;
-                       goto done;
-               }
-       }
-
-       ret = PVRSRV_OK;
-done:
-       mutex_unlock(&mfg->set_power_state);
-
-       return ret;
-}
-
-#ifdef SUPPORT_LINUX_DVFS
-#if defined(CONFIG_DEVFREQ_THERMAL)
-
-#define FALLBACK_STATIC_TEMPERATURE 65000
-
-/* Temperatures on power over-temp-and-voltage curve (C) */
-static const int vt_temperatures[] = { 25, 45, 65, 85, 105 };
-
-/* Voltages on power over-temp-and-voltage curve (mV) */
-static const int vt_voltages[] = { 900, 1000, 1130 };
-
-#define POWER_TABLE_NUM_TEMP ARRAY_SIZE(vt_temperatures)
-#define POWER_TABLE_NUM_VOLT ARRAY_SIZE(vt_voltages)
-
-static const unsigned int
-power_table[POWER_TABLE_NUM_VOLT][POWER_TABLE_NUM_TEMP] = {
-       /*   25     45      65      85     105 */
-       { 14540, 35490,  60420, 120690, 230000 },  /*  900 mV */
-       { 21570, 41910,  82380, 159140, 298620 },  /* 1000 mV */
-       { 32320, 72950, 111320, 209290, 382700 },  /* 1130 mV */
-};
-
-/** Frequency and Power in Khz and mW respectively */
-static const int f_range[] = {253500, 299000, 396500, 455000, 494000, 598000};
-static const IMG_UINT32 max_dynamic_power[] = {612, 722, 957, 1100, 1194, 1445};
-
-static u32 interpolate(int value, const int *x, const unsigned int *y, int len)
-{
-       u64 tmp64;
-       u32 dx;
-       u32 dy;
-       int i, ret;
-
-       if (value <= x[0])
-               return y[0];
-       if (value >= x[len - 1])
-               return y[len - 1];
-
-       for (i = 1; i < len - 1; i++) {
-               /* If value is identical, no need to interpolate */
-               if (value == x[i])
-                       return y[i];
-               if (value < x[i])
-                       break;
-       }
-
-       /* Linear interpolation between the two (x,y) points */
-       dy = y[i] - y[i - 1];
-       dx = x[i] - x[i - 1];
-
-       tmp64 = value - x[i - 1];
-       tmp64 *= dy;
-       do_div(tmp64, dx);
-       ret = y[i - 1] + tmp64;
-
-       return ret;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-static unsigned long mtk_mfg_get_static_power(struct devfreq *df,
-                                             unsigned long voltage)
-#else
-static unsigned long mtk_mfg_get_static_power(unsigned long voltage)
-#endif
-{
-       struct mtk_mfg *mfg = gsDevice.hSysData;
-       struct thermal_zone_device *tz = mfg->tz;
-       unsigned long power;
-#if !defined(CHROMIUMOS_KERNEL) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
-       unsigned long temperature = FALLBACK_STATIC_TEMPERATURE;
-#else
-       int temperature = FALLBACK_STATIC_TEMPERATURE;
-#endif
-       int low_idx = 0, high_idx = POWER_TABLE_NUM_VOLT - 1;
-       int i;
-
-       if (!tz)
-               return 0;
-
-       if (tz->ops->get_temp(tz, &temperature))
-               dev_warn(mfg->dev, "Failed to read temperature\n");
-       do_div(temperature, 1000);
-
-       for (i = 0; i < POWER_TABLE_NUM_VOLT; i++) {
-               if (voltage <= vt_voltages[POWER_TABLE_NUM_VOLT - 1 - i])
-                       high_idx = POWER_TABLE_NUM_VOLT - 1 - i;
-
-               if (voltage >= vt_voltages[i])
-                       low_idx = i;
-       }
-
-       if (low_idx == high_idx) {
-               power = interpolate(temperature,
-                                   vt_temperatures,
-                                   &power_table[low_idx][0],
-                                   POWER_TABLE_NUM_TEMP);
-       } else {
-               unsigned long dvt =
-                               vt_voltages[high_idx] - vt_voltages[low_idx];
-               unsigned long power1, power2;
-
-               power1 = interpolate(temperature,
-                                    vt_temperatures,
-                                    &power_table[high_idx][0],
-                                    POWER_TABLE_NUM_TEMP);
-
-               power2 = interpolate(temperature,
-                                    vt_temperatures,
-                                    &power_table[low_idx][0],
-                                    POWER_TABLE_NUM_TEMP);
-
-               power = (power1 - power2) * (voltage - vt_voltages[low_idx]);
-               do_div(power, dvt);
-               power += power2;
-       }
-
-       /* convert to mw */
-       do_div(power, 1000);
-
-       mtk_mfg_debug("mtk_mfg_get_static_power: %lu at Temperature %d\n",
-                     power, temperature);
-       return power;
-}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
-static unsigned long mtk_mfg_get_dynamic_power(struct devfreq *df,
-                                              unsigned long freq,
-                                              unsigned long voltage)
-#else
-static unsigned long mtk_mfg_get_dynamic_power(unsigned long freq,
-                                              unsigned long voltage)
-#endif
-{
-       #define NUM_RANGE  ARRAY_SIZE(f_range)
-       /** Frequency and Power in Khz and mW respectively */
-       IMG_INT32 i, low_idx = 0, high_idx = NUM_RANGE - 1;
-       IMG_UINT32 power;
-
-       for (i = 0; i < NUM_RANGE; i++) {
-               if (freq <= f_range[NUM_RANGE - 1 - i])
-                       high_idx = NUM_RANGE - 1 - i;
-
-               if (freq >= f_range[i])
-                       low_idx = i;
-       }
-
-       if (low_idx == high_idx) {
-               power = max_dynamic_power[low_idx];
-       } else {
-               IMG_UINT32 f_interval = f_range[high_idx] - f_range[low_idx];
-               IMG_UINT32 p_interval = max_dynamic_power[high_idx] -
-                               max_dynamic_power[low_idx];
-
-               power = p_interval * (freq - f_range[low_idx]);
-               do_div(power, f_interval);
-               power += max_dynamic_power[low_idx];
-       }
-
-       power = (IMG_UINT32)div_u64((IMG_UINT64)power * voltage * voltage,
-                                   1000000UL);
-
-       return power;
-       #undef NUM_RANGE
-}
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))
-static int mtk_mfg_get_real_power(struct devfreq *df,
-                                                  u32 *power,
-                                              unsigned long freq,
-                                              unsigned long voltage)
-{
-       if (!df || !power)
-               return -EINVAL;
-
-       *power = mtk_mfg_get_static_power(df, voltage) +
-                    mtk_mfg_get_dynamic_power(df, freq, voltage);
-
-       return 0;
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) */
-
-static struct devfreq_cooling_power sPowerOps = {
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
-       .get_static_power = mtk_mfg_get_static_power,
-       .get_dynamic_power = mtk_mfg_get_dynamic_power,
-#else
-       .get_real_power = mtk_mfg_get_real_power,
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
-};
-#endif
-
-static void SetFrequency(IMG_UINT32 freq)
-{
-       struct mtk_mfg *mfg = gsDevice.hSysData;
-
-       /* freq is in Hz */
-       mtk_mfg_freq_set(mfg, freq);
-}
-
-static void SetVoltage(IMG_UINT32 volt)
-{
-       struct mtk_mfg *mfg = gsDevice.hSysData;
-
-       mtk_mfg_volt_set(mfg, volt);
-}
-#endif
-
-PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
-{
-       struct device *dev = pvOSDevice;
-       struct mtk_mfg *mfg;
-
-       if (gsDevice.pvOSDevice)
-       {
-               return PVRSRV_ERROR_INVALID_DEVICE;
-       }
-
-       mfg = mtk_mfg_create(dev);
-       if (IS_ERR(mfg)) {
-               if (PTR_ERR(mfg) == -EPROBE_DEFER)
-                       return PVRSRV_ERROR_PROBE_DEFER;
-               else
-                       return PVRSRV_ERROR_INIT_FAILURE;
-       }
-
-       dma_set_mask(dev, DMA_BIT_MASK(33));
-
-       /* Make sure everything we don't care about is set to 0 */
-       memset(&gsDevice, 0, sizeof(gsDevice));
-
-       /* Setup RGX device */
-       gsDevice.pvOSDevice = pvOSDevice;
-       gsDevice.pszName = "mt8173";
-       gsDevice.pszVersion = NULL;
-
-       /* Device's physical heaps */
-       gsDevice.pasPhysHeaps = &gsPhysHeapConfig;
-       gsDevice.ui32PhysHeapCount = 1;
-
-       gsDevice.ui32IRQ = mfg->rgx_irq;
-
-       gsDevice.sRegsCpuPBase.uiAddr = mfg->rgx_start;
-       gsDevice.ui32RegsSize = mfg->rgx_size;
-
-#ifdef SUPPORT_LINUX_DVFS
-       gsDevice.sDVFS.sDVFSDeviceCfg.bIdleReq = IMG_TRUE;
-       gsDevice.sDVFS.sDVFSDeviceCfg.pfnSetFrequency = SetFrequency;
-       gsDevice.sDVFS.sDVFSDeviceCfg.pfnSetVoltage = SetVoltage;
-       gsDevice.sDVFS.sDVFSDeviceCfg.ui32PollMs = MTK_DVFS_SWITCH_INTERVAL;
-#if defined(CONFIG_DEVFREQ_THERMAL)
-       gsDevice.sDVFS.sDVFSDeviceCfg.psPowerOps = &sPowerOps;
-#endif
-
-       gsDevice.sDVFS.sDVFSGovernorCfg.ui32UpThreshold = 90;
-       gsDevice.sDVFS.sDVFSGovernorCfg.ui32DownDifferential = 10;
-#endif
-
-       /* power management on HW system */
-       gsDevice.pfnPrePowerState = MTKSysDevPrePowerState;
-       gsDevice.pfnPostPowerState = MTKSysDevPostPowerState;
-
-       /* clock frequency */
-       gsDevice.pfnClockFreqGet = NULL;
-
-       gsDevice.hDevData = &gsRGXData;
-       gsDevice.hSysData = mfg;
-
-       gsDevice.bHasFBCDCVersion31 = IMG_FALSE;
-       gsDevice.bDevicePA0IsValid  = IMG_FALSE;
-
-       /* device error notify callback function */
-       gsDevice.pfnSysDevErrorNotify = NULL;
-
-       *ppsDevConfig = &gsDevice;
-
-#if defined(SUPPORT_ION)
-       IonInit(NULL);
-#endif
-
-       return PVRSRV_OK;
-}
-
-void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig)
-{
-       struct mtk_mfg *mfg = psDevConfig->hSysData;
-
-#if defined(SUPPORT_ION)
-       IonDeinit();
-#endif
-
-       mtk_mfg_destroy(mfg);
-
-       psDevConfig->pvOSDevice = NULL;
-}
-
-PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
-                                                                 IMG_UINT32 ui32IRQ,
-                                                                 const IMG_CHAR *pszName,
-                                                                 PFN_LISR pfnLISR,
-                                                                 void *pvData,
-                                                                 IMG_HANDLE *phLISRData)
-{
-       LISR_WRAPPER_DATA *psWrapperData;
-
-       PVR_UNREFERENCED_PARAMETER(hSysData);
-
-       psWrapperData = kmalloc(sizeof(*psWrapperData), GFP_KERNEL);
-       if (!psWrapperData)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       psWrapperData->ui32IRQ = ui32IRQ;
-       psWrapperData->pfnLISR = pfnLISR;
-       psWrapperData->pvLISRData = pvData;
-
-       if (request_irq(ui32IRQ, MTKLISRWrapper, IRQF_TRIGGER_LOW, pszName,
-                                       psWrapperData))
-       {
-               kfree(psWrapperData);
-
-               return PVRSRV_ERROR_UNABLE_TO_REGISTER_ISR_HANDLER;
-       }
-
-       *phLISRData = (IMG_HANDLE) psWrapperData;
-
-       return PVRSRV_OK;
-}
-
-PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
-{
-       LISR_WRAPPER_DATA *psWrapperData = hLISRData;
-
-       free_irq(psWrapperData->ui32IRQ, psWrapperData);
-
-       OSFreeMem(psWrapperData);
-
-       return PVRSRV_OK;
-}
-
-PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
-                         DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                         void *pvDumpDebugFile)
-{
-       PVR_UNREFERENCED_PARAMETER(psDevConfig);
-       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-       PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
-
-       return PVRSRV_OK;
-}
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/Kbuild.mk b/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/Kbuild.mk
deleted file mode 100755 (executable)
index 9c702e3..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-########################################################################### ###
-#@File
-#@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.
-### ###########################################################################
-PVRSRVKM_NAME = $(PVRSRV_MODNAME)
-
-$(PVRSRVKM_NAME)-y += \
-       services/system/rogue/$(PVR_SYSTEM)/sysconfig.o \
-       services/system/rogue/common/env/linux/pci_support.o \
-       services/system/rogue/common/env/linux/dma_support.o \
-       services/system/common/sysconfig_cmn.o \
-       services/server/common/vmm_pvz_client.o \
-       services/server/common/vmm_pvz_server.o \
-       services/server/common/vz_vmm_pvz.o \
-       services/server/common/vz_vmm_vm.o \
-       services/system/rogue/common/vmm_type_$(VMM_TYPE).o
-
-ccflags-y += \
-       -I$(TOP)/services/system/rogue/common/env/linux -I$(TOP)/services/system/rogue/common/env/linux \
-       -I$(TOP)/kernel/drivers/staging/imgtec \
-       -I$(TOP)/kernel/drivers/staging/imgtec/tc \
-       -I$(TOP)/include/rogue/system/rgx_tc -I$(TOP)/include/system/rgx_tc
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/sysconfig.c b/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_linux_tc/sysconfig.c
deleted file mode 100644 (file)
index d7db612..0000000
+++ /dev/null
@@ -1,863 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          System Configuration
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    System Configuration functions
-@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.
-*/ /**************************************************************************/
-
-#include <linux/version.h>
-
-#include "sysinfo.h"
-#include "apollo_regs.h"
-
-#include "pvrsrv.h"
-#include "pvrsrv_device.h"
-#include "rgxdevice.h"
-#include "syscommon.h"
-#include "allocmem.h"
-#include "pvr_debug.h"
-
-#if defined(SUPPORT_ION)
-#include PVR_ANDROID_ION_HEADER
-#include "ion_support.h"
-#include "ion_sys.h"
-#endif
-
-#include "tc_drv.h"
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-/* Must be consecutive and start from 0 */
-#define PHY_HEAP_CARD_GPU 0
-#define PHY_HEAP_CARD_EXT 1
-#define PHY_HEAP_LMA_NUM  2
-
-#define PHY_HEAP_SYSTEM   PHY_HEAP_LMA_NUM
-#define PHY_HEAP_NUM      3
-
-#define SYS_RGX_ACTIVE_POWER_LATENCY_MS (10)
-
-#if defined(SUPPORT_LINUX_DVFS) || defined(SUPPORT_PDVFS)
-
-/* Fake DVFS configuration used purely for testing purposes */
-
-static const IMG_OPP asOPPTable[] =
-{
-       { 8,  25000000},
-       { 16, 50000000},
-       { 32, 75000000},
-       { 64, 100000000},
-};
-
-#define LEVEL_COUNT (sizeof(asOPPTable) / sizeof(IMG_OPP))
-
-static void SetFrequency(IMG_UINT32 ui32Frequency)
-{
-       PVR_DPF((PVR_DBG_ERROR, "SetFrequency %u", ui32Frequency));
-}
-
-static void SetVoltage(IMG_UINT32 ui32Voltage)
-{
-       PVR_DPF((PVR_DBG_ERROR, "SetVoltage %u", ui32Voltage));
-}
-
-#endif
-
-static void TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                     IMG_UINT32 ui32NumOfAddr,
-                                     IMG_DEV_PHYADDR *psDevPAddr,
-                                     IMG_CPU_PHYADDR *psCpuPAddr);
-
-static void TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                     IMG_UINT32 ui32NumOfAddr,
-                                     IMG_CPU_PHYADDR *psCpuPAddr,
-                                     IMG_DEV_PHYADDR *psDevPAddr);
-
-static PHYS_HEAP_FUNCTIONS gsLocalPhysHeapFuncs =
-{
-       .pfnCpuPAddrToDevPAddr = TCLocalCpuPAddrToDevPAddr,
-       .pfnDevPAddrToCpuPAddr = TCLocalDevPAddrToCpuPAddr,
-};
-
-static void TCHostCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                                                        IMG_UINT32 ui32NumOfAddr,
-                                                                        IMG_DEV_PHYADDR *psDevPAddr,
-                                                                        IMG_CPU_PHYADDR *psCpuPAddr);
-
-static void TCHostDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                                                        IMG_UINT32 ui32NumOfAddr,
-                                                                        IMG_CPU_PHYADDR *psCpuPAddr,
-                                                                        IMG_DEV_PHYADDR *psDevPAddr);
-
-static PHYS_HEAP_FUNCTIONS gsHostPhysHeapFuncs =
-{
-       .pfnCpuPAddrToDevPAddr = TCHostCpuPAddrToDevPAddr,
-       .pfnDevPAddrToCpuPAddr = TCHostDevPAddrToCpuPAddr,
-};
-
-typedef struct _SYS_DATA_ SYS_DATA;
-
-struct _SYS_DATA_
-{
-       struct platform_device *pdev;
-
-       struct tc_rogue_platform_data *pdata;
-
-       struct resource *registers;
-
-#if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-       struct ion_client *ion_client;
-       struct ion_handle *ion_rogue_allocation;
-#endif
-};
-
-#define SYSTEM_INFO_FORMAT_STRING "FPGA Revision: %s - TCF Core Revision: %s - TCF Core Target Build ID: %s - PCI Version: %s - Macro Version: %s"
-#define FPGA_REV_MAX_LEN      8 /* current longest format: "x.y.z" */
-#define TCF_CORE_REV_MAX_LEN  8 /* current longest format: "x.y.z" */
-#define TCF_CORE_CFG_MAX_LEN  4 /* current longest format: "x" */
-#define PCI_VERSION_MAX_LEN   4 /* current longest format: "x" */
-#define MACRO_VERSION_MAX_LEN 8 /* current longest format: "x.yz" */
-
-static IMG_CHAR *GetDeviceVersionString(SYS_DATA *psSysData)
-{
-       int err;
-       char str_fpga_rev[FPGA_REV_MAX_LEN]={0};
-       char str_tcf_core_rev[TCF_CORE_REV_MAX_LEN]={0};
-       char str_tcf_core_target_build_id[TCF_CORE_CFG_MAX_LEN]={0};
-       char str_pci_ver[PCI_VERSION_MAX_LEN]={0};
-       char str_macro_ver[MACRO_VERSION_MAX_LEN]={0};
-
-       IMG_CHAR *pszVersion;
-       IMG_UINT32 ui32StringLength;
-
-       err = tc_sys_strings(psSysData->pdev->dev.parent,
-                                                        str_fpga_rev, sizeof(str_fpga_rev),
-                                                        str_tcf_core_rev, sizeof(str_tcf_core_rev),
-                                                        str_tcf_core_target_build_id, sizeof(str_tcf_core_target_build_id),
-                                                        str_pci_ver, sizeof(str_pci_ver),
-                                                        str_macro_ver, sizeof(str_macro_ver));
-       if (err)
-       {
-               return NULL;
-       }
-
-       /* Calculate how much space we need to allocate for the string */
-       ui32StringLength = OSStringLength(SYSTEM_INFO_FORMAT_STRING);
-       ui32StringLength += OSStringLength(str_fpga_rev);
-       ui32StringLength += OSStringLength(str_tcf_core_rev);
-       ui32StringLength += OSStringLength(str_tcf_core_target_build_id);
-       ui32StringLength += OSStringLength(str_pci_ver);
-       ui32StringLength += OSStringLength(str_macro_ver);
-
-       /* Create the version string */
-       pszVersion = OSAllocMem(ui32StringLength * sizeof(IMG_CHAR));
-       if (pszVersion)
-       {
-               OSSNPrintf(&pszVersion[0], ui32StringLength,
-                                  SYSTEM_INFO_FORMAT_STRING,
-                                  str_fpga_rev,
-                                  str_tcf_core_rev,
-                                  str_tcf_core_target_build_id,
-                                  str_pci_ver,
-                                  str_macro_ver);
-       }
-       else
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: failed to create format string", __func__));
-       }
-
-       return pszVersion;
-}
-
-#if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-static SYS_DATA *gpsIonPrivateData;
-
-PVRSRV_ERROR IonInit(void *pvPrivateData)
-{
-       PVRSRV_ERROR eError = PVRSRV_OK;
-       SYS_DATA *psSysData = pvPrivateData;
-       gpsIonPrivateData = psSysData;
-
-       psSysData->ion_client = ion_client_create(psSysData->pdata->ion_device, SYS_RGX_DEV_NAME);
-       if (IS_ERR(psSysData->ion_client))
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to create ION client (%ld)", __func__, PTR_ERR(psSysData->ion_client)));
-               eError = PVRSRV_ERROR_ION_NO_CLIENT;
-               goto err_out;
-       }
-       /* Allocate the whole rogue ion heap and pass that to services to manage */
-       psSysData->ion_rogue_allocation = ion_alloc(psSysData->ion_client, psSysData->pdata->rogue_heap_memory_size, 4096, (1 << psSysData->pdata->ion_heap_id), 0);
-       if (IS_ERR(psSysData->ion_rogue_allocation))
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate ION rogue buffer (%ld)", __func__, PTR_ERR(psSysData->ion_rogue_allocation)));
-               eError = PVRSRV_ERROR_ION_FAILED_TO_ALLOC;
-               goto err_destroy_client;
-
-       }
-
-       return PVRSRV_OK;
-err_destroy_client:
-       ion_client_destroy(psSysData->ion_client);
-       psSysData->ion_client = NULL;
-err_out:
-       return eError;
-}
-
-void IonDeinit(void)
-{
-       SYS_DATA *psSysData = gpsIonPrivateData;
-       ion_free(psSysData->ion_client, psSysData->ion_rogue_allocation);
-       psSysData->ion_rogue_allocation = NULL;
-       ion_client_destroy(psSysData->ion_client);
-       psSysData->ion_client = NULL;
-}
-
-struct ion_device *IonDevAcquire(void)
-{
-       return gpsIonPrivateData->pdata->ion_device;
-}
-
-void IonDevRelease(struct ion_device *ion_device)
-{
-       PVR_ASSERT(ion_device == gpsIonPrivateData->pdata->ion_device);
-}
-#endif /* defined(SUPPORT_ION) */
-
-static void TCLocalCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                     IMG_UINT32 ui32NumOfAddr,
-                                     IMG_DEV_PHYADDR *psDevPAddr,
-                                     IMG_CPU_PHYADDR *psCpuPAddr)
-{
-       PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
-       SYS_DATA *psSysData = psDevConfig->hSysData;
-       IMG_UINT32 ui32Idx;
-
-       for (ui32Idx = 0; ui32Idx < ui32NumOfAddr; ui32Idx++)
-       {
-               psDevPAddr[ui32Idx].uiAddr =
-                       psCpuPAddr[ui32Idx].uiAddr - psSysData->pdata->tc_memory_base;
-       }
-}
-
-static void TCLocalDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                     IMG_UINT32 ui32NumOfAddr,
-                                     IMG_CPU_PHYADDR *psCpuPAddr,
-                                     IMG_DEV_PHYADDR *psDevPAddr)
-{
-       PVRSRV_DEVICE_CONFIG *psDevConfig = (PVRSRV_DEVICE_CONFIG *)hPrivData;
-       SYS_DATA *psSysData = psDevConfig->hSysData;
-       IMG_UINT32 ui32Idx;
-
-       for (ui32Idx = 0; ui32Idx < ui32NumOfAddr; ui32Idx++)
-       {
-               psCpuPAddr[ui32Idx].uiAddr =
-                       psDevPAddr[ui32Idx].uiAddr + psSysData->pdata->tc_memory_base;
-       }
-}
-
-static void TCHostCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                                                        IMG_UINT32 uiNumOfAddr,
-                                                                        IMG_DEV_PHYADDR *psDevPAddr,
-                                                                        IMG_CPU_PHYADDR *psCpuPAddr)
-{
-       PVR_ASSERT(sizeof(*psDevPAddr) == sizeof(*psCpuPAddr));
-       OSCachedMemCopy(psDevPAddr, psCpuPAddr, uiNumOfAddr * sizeof(*psDevPAddr));
-}
-
-static void TCHostDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                                                        IMG_UINT32 uiNumOfAddr,
-                                                                        IMG_CPU_PHYADDR *psCpuPAddr,
-                                                                        IMG_DEV_PHYADDR *psDevPAddr)
-{
-       PVR_ASSERT(sizeof(*psCpuPAddr) == sizeof(*psDevPAddr));
-       OSCachedMemCopy(psCpuPAddr, psDevPAddr, uiNumOfAddr * sizeof(*psCpuPAddr));
-}
-
-static PVRSRV_ERROR
-InitLocalHeap(PHYS_HEAP_CONFIG *psPhysHeap,
-                         IMG_UINT64 uiBaseAddr, IMG_UINT64 uiStartAddr,
-                         IMG_UINT64 uiSize, PHYS_HEAP_FUNCTIONS *psFuncs,
-                         PHYS_HEAP_USAGE_FLAGS ui32Flags)
-{
-       psPhysHeap->sCardBase.uiAddr = uiBaseAddr;
-       psPhysHeap->sStartAddr.uiAddr = IMG_CAST_TO_CPUPHYADDR_UINT(uiStartAddr);
-       psPhysHeap->uiSize = uiSize;
-
-       psPhysHeap->eType = PHYS_HEAP_TYPE_LMA;
-       psPhysHeap->pszPDumpMemspaceName = "LMA";
-       psPhysHeap->psMemFuncs = psFuncs;
-       psPhysHeap->ui32UsageFlags = ui32Flags;
-
-       return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR
-InitLocalHeaps(const SYS_DATA *psSysData, PHYS_HEAP_CONFIG *pasPhysHeaps)
-{
-       struct tc_rogue_platform_data *pdata = psSysData->pdata;
-       PHYS_HEAP_FUNCTIONS *psHeapFuncs;
-       IMG_UINT64 uiLocalCardBase;
-       PVRSRV_ERROR eError;
-
-       if (psSysData->pdata->mem_mode == TC_MEMORY_HYBRID)
-       {
-               psHeapFuncs = &gsHostPhysHeapFuncs;
-               uiLocalCardBase = psSysData->pdata->tc_memory_base;
-       }
-       else
-       {
-               psHeapFuncs = &gsLocalPhysHeapFuncs;
-               uiLocalCardBase = 0;
-       }
-
-       eError = InitLocalHeap(&pasPhysHeaps[PHY_HEAP_CARD_GPU],
-                                                  uiLocalCardBase, pdata->rogue_heap_memory_base,
-                                                  pdata->rogue_heap_memory_size, psHeapFuncs,
-                                                  PHYS_HEAP_USAGE_GPU_LOCAL);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
-
-       eError = InitLocalHeap(&pasPhysHeaps[PHY_HEAP_CARD_EXT],
-                                                  uiLocalCardBase, pdata->pdp_heap_memory_base,
-                                                  pdata->pdp_heap_memory_size, psHeapFuncs,
-                                                  PHYS_HEAP_USAGE_EXTERNAL | PHYS_HEAP_USAGE_DISPLAY);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
-
-       return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR
-InitHostHeaps(const SYS_DATA *psSysData, PHYS_HEAP_CONFIG *pasPhysHeaps)
-{
-       pasPhysHeaps[PHY_HEAP_SYSTEM].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHY_HEAP_SYSTEM].pszPDumpMemspaceName = "SYSMEM";
-       pasPhysHeaps[PHY_HEAP_SYSTEM].psMemFuncs = &gsHostPhysHeapFuncs;
-       pasPhysHeaps[PHY_HEAP_SYSTEM].ui32UsageFlags = PHYS_HEAP_USAGE_CPU_LOCAL;
-
-       return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR
-PhysHeapsInit(const SYS_DATA *psSysData, PHYS_HEAP_CONFIG *pasPhysHeaps,
-                         void *pvPrivData)
-{
-       PVRSRV_ERROR eError;
-       IMG_UINT32 i;
-
-       eError = InitLocalHeaps(psSysData, pasPhysHeaps);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
-
-       eError = InitHostHeaps(psSysData, pasPhysHeaps);
-       if (eError != PVRSRV_OK)
-       {
-               return eError;
-       }
-
-       /* Initialise fields that don't change between memory modes.
-        * Fix up heap IDs. This is needed for multi-testchip systems to
-        * ensure the heap IDs are unique as this is what Services expects.
-        */
-       for (i = 0; i < PHY_HEAP_NUM; i++)
-       {
-               pasPhysHeaps[i].hPrivData = pvPrivData;
-       }
-
-       return PVRSRV_OK;
-}
-
-static PVRSRV_ERROR
-PhysHeapsCreate(const SYS_DATA *psSysData, void *pvPrivData,
-                               PHYS_HEAP_CONFIG **ppasPhysHeapsOut,
-                               IMG_UINT32 *puiPhysHeapCountOut)
-{
-       PHYS_HEAP_CONFIG *pasPhysHeaps;
-       PVRSRV_ERROR eError;
-
-       pasPhysHeaps = OSAllocMem(sizeof(*pasPhysHeaps) * PHY_HEAP_NUM);
-       if (!pasPhysHeaps)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       eError = PhysHeapsInit(psSysData, pasPhysHeaps, pvPrivData);
-       if (eError != PVRSRV_OK)
-       {
-               OSFreeMem(pasPhysHeaps);
-               return eError;
-       }
-
-       *ppasPhysHeapsOut = pasPhysHeaps;
-       *puiPhysHeapCountOut = PHY_HEAP_NUM;
-
-       return PVRSRV_OK;
-}
-
-static void DeviceConfigDestroy(PVRSRV_DEVICE_CONFIG *psDevConfig)
-{
-       if (psDevConfig->pszVersion)
-       {
-               OSFreeMem(psDevConfig->pszVersion);
-       }
-
-       OSFreeMem(psDevConfig->pasPhysHeaps);
-
-       OSFreeMem(psDevConfig);
-}
-
-static void odinTCDevPhysAddr2DmaAddr(PVRSRV_DEVICE_CONFIG *psDevConfig,
-                                                                         IMG_DMA_ADDR *psDmaAddr,
-                                                                         IMG_DEV_PHYADDR *psDevPAddr,
-                                                                         IMG_BOOL *pbValid,
-                                                                         IMG_UINT32 ui32NumAddr,
-                                                                         IMG_BOOL bSparseAlloc)
-{
-       IMG_CPU_PHYADDR sCpuPAddr = {0};
-       IMG_UINT32 ui32Idx;
-
-       /* Fast path */
-       if (!bSparseAlloc)
-       {
-               /* In Odin, DMA address space is the same as host CPU */
-               TCLocalDevPAddrToCpuPAddr(psDevConfig,
-                                                                 1,
-                                                                 &sCpuPAddr,
-                                                                 psDevPAddr);
-               psDmaAddr->uiAddr = sCpuPAddr.uiAddr;
-       }
-       else
-       {
-               for (ui32Idx = 0; ui32Idx < ui32NumAddr; ui32Idx++)
-               {
-                       if (pbValid[ui32Idx])
-                       {
-                               TCLocalDevPAddrToCpuPAddr(psDevConfig,
-                                                                                 1,
-                                                                                 &sCpuPAddr,
-                                                                                 &psDevPAddr[ui32Idx]);
-                               psDmaAddr[ui32Idx].uiAddr = sCpuPAddr.uiAddr;
-                       }
-                       else
-                       {
-                               /* Invalid DMA address marker */
-                               psDmaAddr[ui32Idx].uiAddr = ~((IMG_UINT64)0x0);
-                       }
-               }
-       }
-}
-
-static void * odinTCgetCDMAChan(PVRSRV_DEVICE_CONFIG *psDevConfig, char *name)
-{
-       struct device* psDev = (struct device*) psDevConfig->pvOSDevice;
-       return tc_dma_chan(psDev->parent, name);
-}
-
-static void odinTCFreeCDMAChan(PVRSRV_DEVICE_CONFIG *psDevConfig,
-                                                          void* channel)
-{
-
-       struct device* psDev = (struct device*) psDevConfig->pvOSDevice;
-       struct dma_chan *chan = (struct dma_chan*) channel;
-
-       tc_dma_chan_free(psDev->parent, chan);
-}
-
-static PVRSRV_ERROR DeviceConfigCreate(SYS_DATA *psSysData,
-                                                                          PVRSRV_DEVICE_CONFIG **ppsDevConfigOut)
-{
-       PVRSRV_DEVICE_CONFIG *psDevConfig;
-       RGX_DATA *psRGXData;
-       RGX_TIMING_INFORMATION *psRGXTimingInfo;
-       PHYS_HEAP_CONFIG *pasPhysHeaps;
-       IMG_UINT32 uiPhysHeapCount;
-       PVRSRV_ERROR eError;
-
-       psDevConfig = OSAllocZMem(sizeof(*psDevConfig) +
-                                                         sizeof(*psRGXData) +
-                                                         sizeof(*psRGXTimingInfo));
-       if (!psDevConfig)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       psRGXData = (RGX_DATA *) IMG_OFFSET_ADDR(psDevConfig, sizeof(*psDevConfig));
-       psRGXTimingInfo = (RGX_TIMING_INFORMATION *) IMG_OFFSET_ADDR(psRGXData, sizeof(*psRGXData));
-
-       eError = PhysHeapsCreate(psSysData, psDevConfig, &pasPhysHeaps, &uiPhysHeapCount);
-       if (eError != PVRSRV_OK)
-       {
-               goto ErrorFreeDevConfig;
-       }
-
-       /* Setup RGX specific timing data */
-#if defined(TC_APOLLO_BONNIE)
-       /* For BonnieTC there seems to be an additional 5x multiplier that occurs to the clock as measured speed is 540Mhz not 108Mhz. */
-       psRGXTimingInfo->ui32CoreClockSpeed = tc_core_clock_speed(&psSysData->pdev->dev)  * 6 * 5;
-#else
-       psRGXTimingInfo->ui32CoreClockSpeed = tc_core_clock_speed(&psSysData->pdev->dev)  * 6;
-#endif
-       psRGXTimingInfo->bEnableActivePM = IMG_FALSE;
-       psRGXTimingInfo->bEnableRDPowIsland = IMG_FALSE;
-       psRGXTimingInfo->ui32ActivePMLatencyms = SYS_RGX_ACTIVE_POWER_LATENCY_MS;
-
-       /* Set up the RGX data */
-       psRGXData->psRGXTimingInfo = psRGXTimingInfo;
-
-       /* Setup the device config */
-       psDevConfig->pvOSDevice = &psSysData->pdev->dev;
-       psDevConfig->pszName = "tc";
-       psDevConfig->pszVersion = GetDeviceVersionString(psSysData);
-
-       psDevConfig->sRegsCpuPBase.uiAddr = psSysData->registers->start;
-       psDevConfig->ui32RegsSize = resource_size(psSysData->registers);
-
-       psDevConfig->ui32IRQ = TC_INTERRUPT_EXT;
-
-       psDevConfig->eCacheSnoopingMode = PVRSRV_DEVICE_SNOOP_NONE;
-
-       psDevConfig->pasPhysHeaps = pasPhysHeaps;
-       psDevConfig->ui32PhysHeapCount = uiPhysHeapCount;
-
-       /* Only required for LMA but having this always set shouldn't be a problem */
-       psDevConfig->bDevicePA0IsValid = IMG_TRUE;
-
-       psDevConfig->hDevData = psRGXData;
-       psDevConfig->hSysData = psSysData;
-
-#if defined(SUPPORT_LINUX_DVFS) || defined(SUPPORT_PDVFS)
-       /* Fake DVFS configuration used purely for testing purposes */
-       psDevConfig->sDVFS.sDVFSDeviceCfg.pasOPPTable = asOPPTable;
-       psDevConfig->sDVFS.sDVFSDeviceCfg.ui32OPPTableSize = LEVEL_COUNT;
-       psDevConfig->sDVFS.sDVFSDeviceCfg.pfnSetFrequency = SetFrequency;
-       psDevConfig->sDVFS.sDVFSDeviceCfg.pfnSetVoltage = SetVoltage;
-#endif
-#if defined(SUPPORT_LINUX_DVFS)
-       psDevConfig->sDVFS.sDVFSDeviceCfg.ui32PollMs = 1000;
-       psDevConfig->sDVFS.sDVFSDeviceCfg.bIdleReq = IMG_TRUE;
-       psDevConfig->sDVFS.sDVFSGovernorCfg.ui32UpThreshold = 90;
-       psDevConfig->sDVFS.sDVFSGovernorCfg.ui32DownDifferential = 10;
-#endif
-
-       /* DMA channel config */
-       psDevConfig->pfnSlaveDMAGetChan = odinTCgetCDMAChan;
-       psDevConfig->pfnSlaveDMAFreeChan = odinTCFreeCDMAChan;
-       psDevConfig->pfnDevPhysAddr2DmaAddr = odinTCDevPhysAddr2DmaAddr;
-       psDevConfig->pszDmaTxChanName = psSysData->pdata->tc_dma_tx_chan_name;
-       psDevConfig->pszDmaRxChanName = psSysData->pdata->tc_dma_rx_chan_name;
-       psDevConfig->bHasDma = IMG_TRUE;
-       /* Following two values are expressed in number of bytes */
-       psDevConfig->ui32DmaTransferUnit = 1;
-       psDevConfig->ui32DmaAlignment = 1;
-
-       *ppsDevConfigOut = psDevConfig;
-
-       return PVRSRV_OK;
-
-ErrorFreeDevConfig:
-       OSFreeMem(psDevConfig);
-       return eError;
-}
-
-PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
-{
-       PVRSRV_DEVICE_CONFIG *psDevConfig;
-       SYS_DATA *psSysData;
-       resource_size_t uiRegistersSize;
-       PVRSRV_ERROR eError;
-       int err = 0;
-
-       PVR_ASSERT(pvOSDevice);
-
-       psSysData = OSAllocZMem(sizeof(*psSysData));
-       if (psSysData == NULL)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       psSysData->pdev = to_platform_device((struct device *)pvOSDevice);
-       psSysData->pdata = psSysData->pdev->dev.platform_data;
-
-       PVR_ASSERT(TC_MEMORY_CONFIG == psSysData->pdata->mem_mode);
-
-       /*
-        * The device cannot address system memory, so there is no DMA
-        * limitation.
-        */
-       if (psSysData->pdata->mem_mode == TC_MEMORY_LOCAL)
-       {
-               dma_set_mask(pvOSDevice, DMA_BIT_MASK(64));
-       }
-       else
-       {
-               dma_set_mask(pvOSDevice, DMA_BIT_MASK(32));
-       }
-
-       err = tc_enable(psSysData->pdev->dev.parent);
-       if (err)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to enable PCI device (%d)", __func__, err));
-               eError = PVRSRV_ERROR_PCI_CALL_FAILED;
-               goto ErrFreeSysData;
-       }
-
-       psSysData->registers = platform_get_resource_byname(psSysData->pdev,
-                                                                                                               IORESOURCE_MEM,
-                                                                                                               "rogue-regs");
-       if (!psSysData->registers)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                                "%s: Failed to get Rogue register information",
-                                __func__));
-               eError = PVRSRV_ERROR_PCI_REGION_UNAVAILABLE;
-               goto ErrorDevDisable;
-       }
-
-       /* Check the address range is large enough. */
-       uiRegistersSize = resource_size(psSysData->registers);
-       if (uiRegistersSize < SYS_RGX_REG_REGION_SIZE)
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                                "%s: Rogue register region isn't big enough (was %pa, required 0x%08x)",
-                                __func__, &uiRegistersSize, SYS_RGX_REG_REGION_SIZE));
-
-               eError = PVRSRV_ERROR_PCI_REGION_TOO_SMALL;
-               goto ErrorDevDisable;
-       }
-
-       /* Reserve the address range */
-       if (!request_mem_region(psSysData->registers->start,
-                                                       resource_size(psSysData->registers),
-                                                       SYS_RGX_DEV_NAME))
-       {
-               PVR_DPF((PVR_DBG_ERROR,
-                                "%s: Rogue register memory region not available",
-                                __func__));
-               eError = PVRSRV_ERROR_PCI_CALL_FAILED;
-
-               goto ErrorDevDisable;
-       }
-
-       eError = DeviceConfigCreate(psSysData, &psDevConfig);
-       if (eError != PVRSRV_OK)
-       {
-               goto ErrorReleaseMemRegion;
-       }
-
-#if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-       eError = IonInit(psSysData);
-       if (eError != PVRSRV_OK)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: Failed to initialise ION", __func__));
-               goto ErrorDeviceConfigDestroy;
-       }
-#endif
-
-       /* Set psDevConfig->pfnSysDevErrorNotify callback */
-       psDevConfig->pfnSysDevErrorNotify = SysRGXErrorNotify;
-
-       *ppsDevConfig = psDevConfig;
-
-       return PVRSRV_OK;
-
-#if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-ErrorDeviceConfigDestroy:
-       DeviceConfigDestroy(psDevConfig);
-#endif
-ErrorReleaseMemRegion:
-       release_mem_region(psSysData->registers->start,
-                                          resource_size(psSysData->registers));
-ErrorDevDisable:
-       tc_disable(psSysData->pdev->dev.parent);
-ErrFreeSysData:
-       OSFreeMem(psSysData);
-       return eError;
-}
-
-void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig)
-{
-       SYS_DATA *psSysData = (SYS_DATA *)psDevConfig->hSysData;
-
-#if defined(SUPPORT_ION) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
-       IonDeinit();
-#endif
-
-       DeviceConfigDestroy(psDevConfig);
-
-       release_mem_region(psSysData->registers->start,
-                                          resource_size(psSysData->registers));
-       tc_disable(psSysData->pdev->dev.parent);
-
-       OSFreeMem(psSysData);
-}
-
-PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
-                               DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                               void *pvDumpDebugFile)
-{
-#if defined(TC_APOLLO_TCF5)
-       PVR_UNREFERENCED_PARAMETER(psDevConfig);
-       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-       return PVRSRV_OK;
-#else
-       SYS_DATA *psSysData = psDevConfig->hSysData;
-       PVRSRV_ERROR eError = PVRSRV_OK;
-       u32 tmp = 0;
-       u32 pll;
-
-       PVR_DUMPDEBUG_LOG("------[ rgx_tc system debug ]------");
-
-       if (tc_sys_info(psSysData->pdev->dev.parent, &tmp, &pll))
-               goto err_out;
-
-       if (tmp > 0)
-               PVR_DUMPDEBUG_LOG("Chip temperature: %d degrees C", tmp);
-       PVR_DUMPDEBUG_LOG("PLL status: %x", pll);
-
-err_out:
-       return eError;
-#endif
-}
-
-typedef struct
-{
-       struct device *psDev;
-       int iInterruptID;
-       void *pvData;
-       PFN_LISR pfnLISR;
-} LISR_DATA;
-
-static void TCInterruptHandler(void* pvData)
-{
-       LISR_DATA *psLISRData = pvData;
-       psLISRData->pfnLISR(psLISRData->pvData);
-}
-
-PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
-                                 IMG_UINT32 ui32IRQ,
-                                 const IMG_CHAR *pszName,
-                                 PFN_LISR pfnLISR,
-                                 void *pvData,
-                                 IMG_HANDLE *phLISRData)
-{
-       SYS_DATA *psSysData = (SYS_DATA *)hSysData;
-       LISR_DATA *psLISRData;
-       PVRSRV_ERROR eError;
-       int err;
-
-       if (ui32IRQ != TC_INTERRUPT_EXT)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: No device matching IRQ %d", __func__, ui32IRQ));
-               return PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
-       }
-
-       psLISRData = OSAllocZMem(sizeof(*psLISRData));
-       if (!psLISRData)
-       {
-               eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-               goto err_out;
-       }
-
-       psLISRData->pfnLISR = pfnLISR;
-       psLISRData->pvData = pvData;
-       psLISRData->iInterruptID = ui32IRQ;
-       psLISRData->psDev = psSysData->pdev->dev.parent;
-
-       err = tc_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, TCInterruptHandler, psLISRData);
-       if (err)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: tc_set_interrupt_handler() failed (%d)", __func__, err));
-               eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
-               goto err_free_data;
-       }
-
-       err = tc_enable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
-       if (err)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: tc_enable_interrupt() failed (%d)", __func__, err));
-               eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
-               goto err_unset_interrupt_handler;
-       }
-
-       *phLISRData = psLISRData;
-       eError = PVRSRV_OK;
-
-       PVR_TRACE(("Installed device LISR " IMG_PFN_FMTSPEC " with tc module to ID %u",
-                          pfnLISR, ui32IRQ));
-
-err_out:
-       return eError;
-err_unset_interrupt_handler:
-       tc_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
-err_free_data:
-       OSFreeMem(psLISRData);
-       goto err_out;
-}
-
-PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
-{
-       LISR_DATA *psLISRData = (LISR_DATA *) hLISRData;
-       int err;
-
-       err = tc_disable_interrupt(psLISRData->psDev, psLISRData->iInterruptID);
-       if (err)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: tc_disable_interrupt() failed (%d)", __func__, err));
-       }
-
-       err = tc_set_interrupt_handler(psLISRData->psDev, psLISRData->iInterruptID, NULL, NULL);
-       if (err)
-       {
-               PVR_DPF((PVR_DBG_ERROR, "%s: tc_set_interrupt_handler() failed (%d)", __func__, err));
-       }
-
-       PVR_TRACE(("Uninstalled device LISR " IMG_PFN_FMTSPEC " with tc module from ID %u",
-                          psLISRData->pfnLISR, psLISRData->iInterruptID));
-
-       OSFreeMem(psLISRData);
-
-       return PVRSRV_OK;
-}
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/Kbuild.mk b/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/Kbuild.mk
deleted file mode 100755 (executable)
index daf7b74..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-########################################################################### ###
-#@File
-#@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.
-### ###########################################################################
-PVRSRVKM_NAME = $(PVRSRV_MODNAME)
-
-$(PVRSRVKM_NAME)-y += services/system/rogue/$(PVR_SYSTEM)/sysconfig.o \
- services/system/rogue/common/env/linux/dma_support.o \
- services/system/common/sysconfig_cmn.o \
- services/server/common/vmm_pvz_client.o \
- services/server/common/vmm_pvz_server.o \
- services/server/common/vz_vmm_pvz.o \
- services/server/common/vz_vmm_vm.o \
- services/system/rogue/common/vmm_type_$(VMM_TYPE).o
-
-ifeq ($(SUPPORT_ION),1)
-$(PVRSRVKM_NAME)-y += services/system/rogue/common/env/linux/ion_support_generic.o
-endif
diff --git a/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/sysconfig.c b/drivers/gpu/drm/img/img-rogue/services/system/rogue/rgx_nohw/sysconfig.c
deleted file mode 100644 (file)
index f04ef29..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/*************************************************************************/ /*!
-@File
-@Title          System Configuration
-@Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
-@Description    System Configuration functions
-@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.
-*/ /**************************************************************************/
-
-#include "pvrsrv_device.h"
-#include "syscommon.h"
-#include "vz_vmm_pvz.h"
-#include "allocmem.h"
-#include "sysinfo.h"
-#include "sysconfig.h"
-#include "physheap.h"
-#include "pvr_debug.h"
-#if defined(SUPPORT_ION)
-#include "ion_support.h"
-#endif
-#if defined(__linux__)
-#include <linux/dma-mapping.h>
-#endif
-#include "rgx_bvnc_defs_km.h"
-/*
- * In systems that support trusted device address protection, there are three
- * physical heaps from which pages should be allocated:
- * - one heap for normal allocations
- * - one heap for allocations holding META code memory
- * - one heap for allocations holding secured DRM data
- */
-
-#define PHYS_HEAP_IDX_GENERAL     0
-#define PHYS_HEAP_IDX_FW          1
-
-#if defined(SUPPORT_TRUSTED_DEVICE)
-#define PHYS_HEAP_IDX_TDFWMEM     2
-#define PHYS_HEAP_IDX_TDSECUREBUF 3
-#elif defined(SUPPORT_DEDICATED_FW_MEMORY)
-#define PHYS_HEAP_IDX_FW_MEMORY   2
-#endif
-
-/*
-       CPU to Device physical address translation
-*/
-static
-void UMAPhysHeapCpuPAddrToDevPAddr(IMG_HANDLE hPrivData,
-                                                                  IMG_UINT32 ui32NumOfAddr,
-                                                                  IMG_DEV_PHYADDR *psDevPAddr,
-                                                                  IMG_CPU_PHYADDR *psCpuPAddr)
-{
-       PVR_UNREFERENCED_PARAMETER(hPrivData);
-
-       /* Optimise common case */
-       psDevPAddr[0].uiAddr = psCpuPAddr[0].uiAddr;
-       if (ui32NumOfAddr > 1)
-       {
-               IMG_UINT32 ui32Idx;
-               for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
-               {
-                       psDevPAddr[ui32Idx].uiAddr = psCpuPAddr[ui32Idx].uiAddr;
-               }
-       }
-}
-
-/*
-       Device to CPU physical address translation
-*/
-static
-void UMAPhysHeapDevPAddrToCpuPAddr(IMG_HANDLE hPrivData,
-                                                                  IMG_UINT32 ui32NumOfAddr,
-                                                                  IMG_CPU_PHYADDR *psCpuPAddr,
-                                                                  IMG_DEV_PHYADDR *psDevPAddr)
-{
-       PVR_UNREFERENCED_PARAMETER(hPrivData);
-
-       /* Optimise common case */
-       psCpuPAddr[0].uiAddr = psDevPAddr[0].uiAddr;
-       if (ui32NumOfAddr > 1)
-       {
-               IMG_UINT32 ui32Idx;
-               for (ui32Idx = 1; ui32Idx < ui32NumOfAddr; ++ui32Idx)
-               {
-                       psCpuPAddr[ui32Idx].uiAddr = psDevPAddr[ui32Idx].uiAddr;
-               }
-       }
-}
-
-static PHYS_HEAP_FUNCTIONS gsPhysHeapFuncs =
-{
-       /* pfnCpuPAddrToDevPAddr */
-       UMAPhysHeapCpuPAddrToDevPAddr,
-       /* pfnDevPAddrToCpuPAddr */
-       UMAPhysHeapDevPAddrToCpuPAddr,
-};
-
-static PVRSRV_ERROR PhysHeapsCreate(PHYS_HEAP_CONFIG **ppasPhysHeapsOut,
-                                                                       IMG_UINT32 *puiPhysHeapCountOut)
-{
-       /*
-        * This function is called during device initialisation, which on Linux,
-        * means it won't be called concurrently. As such, there's no need to
-        * protect it with a lock or use an atomic variable.
-        */
-       PHYS_HEAP_CONFIG *pasPhysHeaps;
-       IMG_UINT32 uiHeapCount = 2;
-
-#if defined(SUPPORT_TRUSTED_DEVICE)
-       uiHeapCount += 2;
-#elif defined(SUPPORT_DEDICATED_FW_MEMORY)
-       uiHeapCount += 1;
-#endif
-
-       pasPhysHeaps = OSAllocZMem(sizeof(*pasPhysHeaps) * uiHeapCount);
-       if (!pasPhysHeaps)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].pszPDumpMemspaceName = "SYSMEM";
-       pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].psMemFuncs = &gsPhysHeapFuncs;
-       pasPhysHeaps[PHYS_HEAP_IDX_GENERAL].ui32UsageFlags = PHYS_HEAP_USAGE_GPU_LOCAL;
-
-       pasPhysHeaps[PHYS_HEAP_IDX_FW].pszPDumpMemspaceName = "SYSMEM_FW";
-       pasPhysHeaps[PHYS_HEAP_IDX_FW].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHYS_HEAP_IDX_FW].psMemFuncs = &gsPhysHeapFuncs;
-       pasPhysHeaps[PHYS_HEAP_IDX_FW].ui32UsageFlags = PHYS_HEAP_USAGE_FW_MAIN;
-
-#if defined(SUPPORT_TRUSTED_DEVICE)
-       pasPhysHeaps[PHYS_HEAP_IDX_TDFWMEM].pszPDumpMemspaceName = "TDFWMEM";
-       pasPhysHeaps[PHYS_HEAP_IDX_TDFWMEM].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHYS_HEAP_IDX_TDFWMEM].psMemFuncs = &gsPhysHeapFuncs;
-       pasPhysHeaps[PHYS_HEAP_IDX_TDFWMEM].ui32UsageFlags =
-               PHYS_HEAP_USAGE_FW_CODE | PHYS_HEAP_USAGE_FW_PRIV_DATA;
-
-       pasPhysHeaps[PHYS_HEAP_IDX_TDSECUREBUF].pszPDumpMemspaceName = "TDSECBUFMEM";
-       pasPhysHeaps[PHYS_HEAP_IDX_TDSECUREBUF].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHYS_HEAP_IDX_TDSECUREBUF].psMemFuncs = &gsPhysHeapFuncs;
-       pasPhysHeaps[PHYS_HEAP_IDX_TDSECUREBUF].ui32UsageFlags =
-               PHYS_HEAP_USAGE_GPU_SECURE;
-
-#elif defined(SUPPORT_DEDICATED_FW_MEMORY)
-       pasPhysHeaps[PHYS_HEAP_IDX_FW_MEMORY].pszPDumpMemspaceName = "DEDICATEDFWMEM";
-       pasPhysHeaps[PHYS_HEAP_IDX_FW_MEMORY].eType = PHYS_HEAP_TYPE_UMA;
-       pasPhysHeaps[PHYS_HEAP_IDX_FW_MEMORY].psMemFuncs = &gsPhysHeapFuncs;
-       pasPhysHeaps[PHYS_HEAP_IDX_FW_MEMORY].ui32UsageFlags =
-               PHYS_HEAP_USAGE_FW_CODE | PHYS_HEAP_USAGE_FW_PRIV_DATA;
-#endif
-
-       *ppasPhysHeapsOut = pasPhysHeaps;
-       *puiPhysHeapCountOut = uiHeapCount;
-
-       return PVRSRV_OK;
-}
-
-static void PhysHeapsDestroy(PHYS_HEAP_CONFIG *pasPhysHeaps)
-{
-       OSFreeMem(pasPhysHeaps);
-}
-
-static void SysDevFeatureDepInit(PVRSRV_DEVICE_CONFIG *psDevConfig, IMG_UINT64 ui64Features)
-{
-#if defined(SUPPORT_AXI_ACE_TEST)
-               if ( ui64Features & RGX_FEATURE_AXI_ACELITE_BIT_MASK)
-               {
-                       psDevConfig->eCacheSnoopingMode         = PVRSRV_DEVICE_SNOOP_CPU_ONLY;
-               }else
-#endif
-               {
-                       psDevConfig->eCacheSnoopingMode         = PVRSRV_DEVICE_SNOOP_NONE;
-               }
-}
-
-PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
-{
-       PVRSRV_DEVICE_CONFIG *psDevConfig;
-       RGX_DATA *psRGXData;
-       RGX_TIMING_INFORMATION *psRGXTimingInfo;
-       PHYS_HEAP_CONFIG *pasPhysHeaps;
-       IMG_UINT32 uiPhysHeapCount;
-       PVRSRV_ERROR eError;
-
-#if defined(__linux__)
-       dma_set_mask(pvOSDevice, DMA_BIT_MASK(40));
-#endif
-
-       psDevConfig = OSAllocZMem(sizeof(*psDevConfig) +
-                                                         sizeof(*psRGXData) +
-                                                         sizeof(*psRGXTimingInfo));
-       if (!psDevConfig)
-       {
-               return PVRSRV_ERROR_OUT_OF_MEMORY;
-       }
-
-       psRGXData = (RGX_DATA *)((IMG_CHAR *)psDevConfig + sizeof(*psDevConfig));
-       psRGXTimingInfo = (RGX_TIMING_INFORMATION *)((IMG_CHAR *)psRGXData + sizeof(*psRGXData));
-
-       eError = PhysHeapsCreate(&pasPhysHeaps, &uiPhysHeapCount);
-       if (eError)
-       {
-               goto ErrorFreeDevConfig;
-       }
-
-       /* Setup RGX specific timing data */
-       psRGXTimingInfo->ui32CoreClockSpeed        = RGX_NOHW_CORE_CLOCK_SPEED;
-       psRGXTimingInfo->bEnableActivePM           = IMG_FALSE;
-       psRGXTimingInfo->bEnableRDPowIsland        = IMG_FALSE;
-       psRGXTimingInfo->ui32ActivePMLatencyms     = SYS_RGX_ACTIVE_POWER_LATENCY_MS;
-
-       /* Set up the RGX data */
-       psRGXData->psRGXTimingInfo = psRGXTimingInfo;
-
-       /* Setup the device config */
-       psDevConfig->pvOSDevice                         = pvOSDevice;
-       psDevConfig->pszName                = "nohw";
-       psDevConfig->pszVersion             = NULL;
-       psDevConfig->pfnSysDevFeatureDepInit = SysDevFeatureDepInit;
-
-       /* Device setup information */
-       psDevConfig->sRegsCpuPBase.uiAddr   = 0x00f00000;
-       psDevConfig->ui32RegsSize           = 0x4000;
-       psDevConfig->ui32IRQ                = 0x00000bad;
-
-       psDevConfig->pasPhysHeaps                       = pasPhysHeaps;
-       psDevConfig->ui32PhysHeapCount          = uiPhysHeapCount;
-
-       /* No power management on no HW system */
-       psDevConfig->pfnPrePowerState       = NULL;
-       psDevConfig->pfnPostPowerState      = NULL;
-
-       psDevConfig->bHasFBCDCVersion31      = IMG_FALSE;
-
-       /* No clock frequency either */
-       psDevConfig->pfnClockFreqGet        = NULL;
-
-       psDevConfig->hDevData               = psRGXData;
-
-       /* Setup other system specific stuff */
-#if defined(SUPPORT_ION)
-       IonInit(NULL);
-#endif
-
-       /* Set psDevConfig->pfnSysDevErrorNotify callback */
-       psDevConfig->pfnSysDevErrorNotify = SysRGXErrorNotify;
-
-       *ppsDevConfig = psDevConfig;
-
-       return PVRSRV_OK;
-
-ErrorFreeDevConfig:
-       OSFreeMem(psDevConfig);
-       return eError;
-}
-
-void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig)
-{
-#if defined(SUPPORT_ION)
-       IonDeinit();
-#endif
-
-       PhysHeapsDestroy(psDevConfig->pasPhysHeaps);
-       OSFreeMem(psDevConfig);
-}
-
-PVRSRV_ERROR SysInstallDeviceLISR(IMG_HANDLE hSysData,
-                                                                 IMG_UINT32 ui32IRQ,
-                                                                 const IMG_CHAR *pszName,
-                                                                 PFN_LISR pfnLISR,
-                                                                 void *pvData,
-                                                                 IMG_HANDLE *phLISRData)
-{
-       PVR_UNREFERENCED_PARAMETER(hSysData);
-       PVR_UNREFERENCED_PARAMETER(ui32IRQ);
-       PVR_UNREFERENCED_PARAMETER(pszName);
-       PVR_UNREFERENCED_PARAMETER(pfnLISR);
-       PVR_UNREFERENCED_PARAMETER(pvData);
-       PVR_UNREFERENCED_PARAMETER(phLISRData);
-
-       return PVRSRV_OK;
-}
-
-PVRSRV_ERROR SysUninstallDeviceLISR(IMG_HANDLE hLISRData)
-{
-       PVR_UNREFERENCED_PARAMETER(hLISRData);
-
-       return PVRSRV_OK;
-}
-
-PVRSRV_ERROR SysDebugInfo(PVRSRV_DEVICE_CONFIG *psDevConfig,
-                               DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf,
-                               void *pvDumpDebugFile)
-{
-       PVR_UNREFERENCED_PARAMETER(psDevConfig);
-       PVR_UNREFERENCED_PARAMETER(pfnDumpDebugPrintf);
-       PVR_UNREFERENCED_PARAMETER(pvDumpDebugFile);
-       return PVRSRV_OK;
-}
-
-/******************************************************************************
- End of file (sysconfig.c)
-******************************************************************************/
index b4c915a..ed9b0b9 100644 (file)
@@ -388,7 +388,8 @@ PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
        struct platform_device *psDev;
 
        psDev = to_platform_device((struct device *)pvOSDevice);
-       printk("@@ dev ptr:%llx\n", (uint64_t)psDev);
+       printk("@@ dev ptr:%llx/%d/%d\n", (uint64_t)psDev,DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT,
+       PVRSRV_APPHINT_ENABLEPAGEFAULTDEBUG);
 #endif
 
        if (gsDevices[0].pvOSDevice)
@@ -450,6 +451,7 @@ PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig)
                gsDevices[0].ui32RegsSize           = STARFIVE_7110_GPU_SIZE;
        }
 
+       gsDevices[0].eDefaultHeap = PVRSRV_PHYS_HEAP_GPU_LOCAL;
 #if defined(__linux__)
        iIrq = platform_get_irq(psDev, 0);
        if (iIrq >= 0) {
index 034fde5..456c4d2 100644 (file)
@@ -53,7 +53,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 
 #define FATAL_ERROR_DETECTION_POLL_MS                          (10000)
-#if 1 //defined(VIRTUAL_PLATFORM)
+#if defined(VIRTUAL_PLATFORM)
 #define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT                (10000)
 #else
 #define DEVICES_WATCHDOG_POWER_ON_SLEEP_TIMEOUT                (1500)//(10000)
diff --git a/drivers/gpu/drm/img/img-rogue/set_env b/drivers/gpu/drm/img/img-rogue/set_env
deleted file mode 100755 (executable)
index 5d18843..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-
-#LINUX_HOME="/home/joyceooi/Desktop/dev/joyce/sft-riscvpi-freedom-u-sdk"
-LINUX_HOME=$1
-WINDOW_SYSTEM=nulldrmws
-
-#export PATH="${PATH}:${LINUX_HOME}/work/buildroot_initramfs/host/bin"
-export LINUX_ROOT="${LINUX_HOME}/soft_3rdpart/IMG_GPU/linux"
-export SYSROOT="${LINUX_HOME}/work/buildroot_initramfs/host/riscv64-buildroot-linux-gnu/sysroot"
-export KERNELDIR="${LINUX_HOME}/work/linux"
-export MIPS_ELF_ROOT="${LINUX_HOME}/soft_3rdpart/IMG_GPU/linux/mips-mti-elf/2014.07-1"
-export LLVM_BUILD_DIR="${LINUX_HOME}/soft_3rdpart/IMG_GPU/linux/llvm"
-export BUILD=debug
-export DISCIMAGE="${LINUX_HOME}/work/buildroot_initramfs_sysroot"
-export PVRSRV_NEED_PVR_DPF=1
-export PVRSRV_NEED_PVR_ASSERT=1
-export PVR_SERVICES_DEBUG=1
-export WINDOW_SYSTEM=${WINDOW_SYSTEM}
-export ARCH=riscv
-export CROSS_COMPILE=riscv64-unknown-linux-gnu-
-
-
index 6faa654..6a94c8c 100644 (file)
@@ -494,4 +494,28 @@ struct dma_buf_map {
 
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) */
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0))
+
+#define drm_prime_sg_to_page_array(sgt, pages, npages) \
+       drm_prime_sg_to_page_addr_arrays(sgt, pages, NULL, npages)
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)) */
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0))
+
+#define drm_gem_plane_helper_prepare_fb drm_gem_fb_prepare_fb
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0)) */
+
+/*
+ * Linux 5.11 renames the privileged uaccess routines for arm64 and Android
+ * kernel v5.10 merges the change as well. These routines are only used for
+ * arm64 so CONFIG_ARM64 testing can be ignored.
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)) || \
+       ((LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)) && !defined(ANDROID))
+#define uaccess_enable_privileged() uaccess_enable()
+#define uaccess_disable_privileged() uaccess_disable()
+#endif
+
 #endif /* __KERNEL_COMPATIBILITY_H__ */
index bbdac4d..a51c9de 100644 (file)
@@ -47,15 +47,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
 #include <linux/dma-resv.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
-#define dma_resv_get_list              dma_resv_shared_list
-#define dma_resv_get_excl              dma_resv_excl_fence
-#define dma_resv_test_signaled_rcu     dma_resv_test_signaled
-#define dma_resv_wait_timeout_rcu      dma_resv_wait_timeout
-
-#endif
-
 #else
 #include <linux/reservation.h>
 
@@ -76,4 +67,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define dma_resv_wait_timeout_rcu      reservation_object_wait_timeout_rcu
 #endif
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
+
+#define dma_resv_shared_list   dma_resv_get_list
+#define dma_resv_excl_fence    dma_resv_get_excl
+#define dma_resv_wait_timeout  dma_resv_wait_timeout_rcu
+#define dma_resv_test_signaled dma_resv_test_signaled_rcu
+#define dma_resv_get_fences    dma_resv_get_fences_rcu
+
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0)) */
+
 #endif /* __PVR_DMA_RESV_H__ */
index a8c744d..661d0fe 100644 (file)
@@ -64,7 +64,7 @@ static inline void *pvr_vmap(struct page **pages,
        return vmap(pages, count, flags, prot);
 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
        return vm_map_ram(pages, count, -1, prot);
-#else   //using this code path
+#else
        if (pgprot_val(prot) == pgprot_val(PAGE_KERNEL))
                return vm_map_ram(pages, count, -1);
        else
index ae7a51f..c62b3f7 100644 (file)
@@ -45,21 +45,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define PVRVERSION_H
 
 #define PVRVERSION_MAJ               1U
-#define PVRVERSION_MIN               15U
+#define PVRVERSION_MIN               17U
 
 #define PVRVERSION_FAMILY           "rogueddk"
-#define PVRVERSION_BRANCHNAME       "1.15"
-#define PVRVERSION_BUILD             6052913
+#define PVRVERSION_BRANCHNAME       "1.17"
+#define PVRVERSION_BUILD             6210866
 #define PVRVERSION_BSCONTROL        "Rogue_DDK_Linux_WS"
 
-#define PVRVERSION_STRING           "Rogue_DDK_Linux_WS rogueddk 1.15@6052913"
-#define PVRVERSION_STRING_SHORT     "1.15@6052913"
+#define PVRVERSION_STRING           "Rogue_DDK_Linux_WS rogueddk 1.17@6210866"
+#define PVRVERSION_STRING_SHORT     "1.17@6210866"
 
 #define COPYRIGHT_TXT               "Copyright (c) Imagination Technologies Ltd. All Rights Reserved."
 
-#define PVRVERSION_BUILD_HI          605
-#define PVRVERSION_BUILD_LO          2913
-#define PVRVERSION_STRING_NUMERIC   "1.15.605.2913"
+#define PVRVERSION_BUILD_HI          621
+#define PVRVERSION_BUILD_LO          866
+#define PVRVERSION_STRING_NUMERIC   "1.17.621.866"
 
 #define PVRVERSION_PACK(MAJOR,MINOR) (((IMG_UINT32)((IMG_UINT32)(MAJOR) & 0xFFFFU) << 16U) | (((MINOR) & 0xFFFFU) << 0U))
 #define PVRVERSION_UNPACK_MAJ(VERSION) (((VERSION) >> 16U) & 0xFFFFU)